From fbd2a6425b7210852d62e2410baecb2caaa0f54d Mon Sep 17 00:00:00 2001 From: Idriss Neumann Date: Thu, 14 Dec 2023 10:04:22 +0100 Subject: [PATCH] Issue #4: search the timestamp on the backend side --- pkg/quickwit/quickwit.go | 74 ++++++++++++++++++++++++++++++++++++++-- src/datasource.ts | 2 +- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/pkg/quickwit/quickwit.go b/pkg/quickwit/quickwit.go index 026651f..941139d 100644 --- a/pkg/quickwit/quickwit.go +++ b/pkg/quickwit/quickwit.go @@ -25,6 +25,69 @@ type QuickwitDatasource struct { dsInfo es.DatasourceInfo } +type QuickwitMapping struct { + IndexConfig struct { + DocMapping struct { + TimestampField string `json:"timestamp_field"` + FieldMappings []struct { + Name string `json:"name"` + InputFormats []string `json:"input_formats"` + } `json:"field_mappings"` + } `json:"doc_mapping"` + } `json:"index_config"` +} + +func getTimestampFieldInfos(index string, qwUrl string, cli *http.Client) (string, string, error) { + mappingEndpointUrl := qwUrl + "/indexes/" + index + qwlog.Info("Calling quickwit endpoint: " + mappingEndpointUrl) + r, err := cli.Get(mappingEndpointUrl) + if err != nil { + errMsg := fmt.Sprintf("Error when calling url = %s: err = %s", mappingEndpointUrl, err.Error()) + qwlog.Error(errMsg) + return "", "", err + } + + statusCode := r.StatusCode + if statusCode < 200 || statusCode >= 400 { + errMsg := fmt.Sprintf("Error when calling url = %s: statusCode = %d", mappingEndpointUrl, statusCode) + qwlog.Error(errMsg) + return "", "", fmt.Errorf(errMsg) + } + + defer r.Body.Close() + body, err := io.ReadAll(r.Body) + if err != nil { + errMsg := fmt.Sprintf("Error when calling url = %s: err = %s", mappingEndpointUrl, err.Error()) + qwlog.Error(errMsg) + return "", "", err + } + + var payload QuickwitMapping + err = json.Unmarshal(body, &payload) + if err != nil { + errMsg := fmt.Sprintf("Unmarshalling body error: %s", string(body)) + qwlog.Error(errMsg) + return "", "", fmt.Errorf(errMsg) + } + + timestampFieldName := payload.IndexConfig.DocMapping.TimestampField + timestampFieldFormat := "undef" + for _, field := range payload.IndexConfig.DocMapping.FieldMappings { + if field.Name == timestampFieldName && len(field.InputFormats) > 0 { + timestampFieldFormat = field.InputFormats[0] + break + } + } + + if timestampFieldFormat == "undef" { + errMsg := fmt.Sprintf("No format found for field: %s", string(timestampFieldName)) + return timestampFieldName, "", fmt.Errorf(errMsg) + } + + qwlog.Info(fmt.Sprintf("Found timestampFieldName = %s, timestampFieldFormat = %s", timestampFieldName, timestampFieldFormat)) + return timestampFieldName, timestampFieldFormat, nil +} + // Creates a Quickwit datasource. func NewQuickwitDatasource(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { qwlog.Debug("Initializing new data source instance") @@ -49,8 +112,8 @@ func NewQuickwitDatasource(settings backend.DataSourceInstanceSettings) (instanc return nil, err } - timeField, _ := jsonData["timeField"].(string) - timeOutputFormat, _ := jsonData["timeOutputFormat"].(string) + timeField, toerr := jsonData["timeField"].(string) + timeOutputFormat, toferr := jsonData["timeOutputFormat"].(string) logLevelField, ok := jsonData["logLevelField"].(string) if !ok { @@ -84,6 +147,13 @@ func NewQuickwitDatasource(settings backend.DataSourceInstanceSettings) (instanc maxConcurrentShardRequests = 256 } + if !toerr || !toferr { + timeField, timeOutputFormat, err = getTimestampFieldInfos(index, settings.URL, httpCli) + if nil != err { + return nil, err + } + } + configuredFields := es.ConfiguredFields{ TimeField: timeField, TimeOutputFormat: timeOutputFormat, diff --git a/src/datasource.ts b/src/datasource.ts index 236baa6..feac6a8 100644 --- a/src/datasource.ts +++ b/src/datasource.ts @@ -80,8 +80,8 @@ export class QuickwitDataSource from(this.getResource('indexes/' + this.index)).pipe( map((indexMetadata) => { let fields = getAllFields(indexMetadata.index_config.doc_mapping.field_mappings); - let timestampField = fields.find((field) => field.json_path === this.timeField); let timestampFieldName = indexMetadata.index_config.doc_mapping.timestamp_field + let timestampField = fields.find((field) => field.json_path === timestampFieldName); let timestampFormat = timestampField ? timestampField.field_mapping.output_format || '' : '' return { 'field': timestampFieldName, 'format': timestampFormat } })