diff --git a/pkg/tsdb/loki/frame.go b/pkg/tsdb/loki/frame.go index 43cef9abd26..35314e22e65 100644 --- a/pkg/tsdb/loki/frame.go +++ b/pkg/tsdb/loki/frame.go @@ -4,6 +4,7 @@ import ( "fmt" "sort" "strings" + "time" "github.com/grafana/grafana-plugin-sdk-go/data" ) @@ -51,9 +52,31 @@ func adjustFrame(frame *data.Frame, query *lokiQuery) *data.Frame { field.Config.DisplayNameFromDS = name } + // for streams-dataframes, we need to send to the browser the nanosecond-precision timestamp too. + // usually timestamps become javascript-date-objects in the browser automatically, which only + // have millisecond-precision. + // so we send a separate timestamp-as-string field too. + if !isMetricFrame { + stringTimeField := makeStringTimeField(timeFields[0]) + frame.Fields = append(frame.Fields, stringTimeField) + } + return frame } +func makeStringTimeField(field *data.Field) *data.Field { + length := field.Len() + stringTimestamps := make([]string, length) + + for i := 0; i < length; i++ { + if v, ok := field.ConcreteAt(i); ok { + nsNumber := v.(time.Time).UnixNano() + stringTimestamps[i] = fmt.Sprintf("%d", nsNumber) + } + } + return data.NewField("tsNs", field.Labels.Copy(), stringTimestamps) +} + func formatNamePrometheusStyle(labels map[string]string) string { var parts []string diff --git a/pkg/tsdb/loki/testdata/streams_simple.golden.txt b/pkg/tsdb/loki/testdata/streams_simple.golden.txt index c45d8de8db0..10312ee6f42 100644 --- a/pkg/tsdb/loki/testdata/streams_simple.golden.txt +++ b/pkg/tsdb/loki/testdata/streams_simple.golden.txt @@ -4,14 +4,14 @@ Frame[0] { "executedQueryString": "Expr: query1" } Name: {level="error", location="moon"} -Dimensions: 2 Fields by 1 Rows -+----------------------------------------+------------------------------------+ -| Name: time | Name: value | -| Labels: | Labels: level=error, location=moon | -| Type: []time.Time | Type: []string | -+----------------------------------------+------------------------------------+ -| 2022-02-16 16:50:44.81075712 +0000 UTC | log line error 1 | -+----------------------------------------+------------------------------------+ +Dimensions: 3 Fields by 1 Rows ++----------------------------------------+------------------------------------+---------------------+ +| Name: time | Name: value | Name: tsNs | +| Labels: | Labels: level=error, location=moon | Labels: | +| Type: []time.Time | Type: []string | Type: []string | ++----------------------------------------+------------------------------------+---------------------+ +| 2022-02-16 16:50:44.81075712 +0000 UTC | log line error 1 | 1645030244810757120 | ++----------------------------------------+------------------------------------+---------------------+ @@ -19,19 +19,19 @@ Frame[1] { "executedQueryString": "Expr: query1" } Name: {level="info", location="moon"} -Dimensions: 2 Fields by 4 Rows -+-----------------------------------------+-----------------------------------+ -| Name: time | Name: value | -| Labels: | Labels: level=info, location=moon | -| Type: []time.Time | Type: []string | -+-----------------------------------------+-----------------------------------+ -| 2022-02-16 16:50:47.02773504 +0000 UTC | log line info 1 | -| 2022-02-16 16:50:46.277587968 +0000 UTC | log line info 2 | -| 2022-02-16 16:50:45.539423744 +0000 UTC | log line info 3 | -| 2022-02-16 16:50:44.091700992 +0000 UTC | log line info 4 | -+-----------------------------------------+-----------------------------------+ +Dimensions: 3 Fields by 4 Rows ++-----------------------------------------+-----------------------------------+---------------------+ +| Name: time | Name: value | Name: tsNs | +| Labels: | Labels: level=info, location=moon | Labels: | +| Type: []time.Time | Type: []string | Type: []string | ++-----------------------------------------+-----------------------------------+---------------------+ +| 2022-02-16 16:50:47.02773504 +0000 UTC | log line info 1 | 1645030247027735040 | +| 2022-02-16 16:50:46.277587968 +0000 UTC | log line info 2 | 1645030246277587968 | +| 2022-02-16 16:50:45.539423744 +0000 UTC | log line info 3 | 1645030245539423744 | +| 2022-02-16 16:50:44.091700992 +0000 UTC | log line info 4 | 1645030244091700992 | ++-----------------------------------------+-----------------------------------+---------------------+ ====== TEST DATA RESPONSE (arrow base64) ====== -FRAME=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 -FRAME=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 +FRAME=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 +FRAME=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 diff --git a/public/app/plugins/datasource/loki/backendResultTransformer.test.ts b/public/app/plugins/datasource/loki/backendResultTransformer.test.ts new file mode 100644 index 00000000000..eb222f1b94f --- /dev/null +++ b/public/app/plugins/datasource/loki/backendResultTransformer.test.ts @@ -0,0 +1,87 @@ +import { ArrayVector, CoreApp, DataFrame, DataQueryRequest, DataQueryResponse, FieldType, toUtc } from '@grafana/data'; +import { cloneDeep } from 'lodash'; + +import { transformBackendResult } from './backendResultTransformer'; +import { LokiQuery } from './types'; + +const frame: DataFrame = { + name: 'frame1', + refId: 'A', + meta: { + executedQueryString: 'something1', + }, + fields: [ + { + name: 'Time', + type: FieldType.time, + config: {}, + values: new ArrayVector([1645029699311, 1645029699312, 1645029699313]), + }, + { + name: 'Value', + type: FieldType.string, + labels: { + level: 'error', + location: 'moon', + protocol: 'http', + }, + config: { + displayNameFromDS: '{level="error", location="moon", protocol="http"}', + }, + values: new ArrayVector(['line1', 'line2', 'line3']), + }, + { + name: 'tsNs', + type: FieldType.string, + config: {}, + values: new ArrayVector(['1645029699311000500', '1645029699312000500', '1645029699313000500']), + }, + ], + length: 1, +}; + +function makeRequest(expr: string): DataQueryRequest { + return { + requestId: 'test1', + interval: '1s', + intervalMs: 1000, + range: { + from: toUtc('2022-02-22T13:14:15'), + to: toUtc('2022-02-22T13:15:15'), + raw: { + from: toUtc('2022-02-22T13:14:15'), + to: toUtc('2022-02-22T13:15:15'), + }, + }, + scopedVars: {}, + targets: [ + { + refId: 'A', + expr, + }, + ], + timezone: 'UTC', + app: CoreApp.Explore, + startTime: 0, + }; +} + +describe('loki backendResultTransformer', () => { + it('processes a logs-dataframe correctly', () => { + const response: DataQueryResponse = { data: [cloneDeep(frame)] }; + const request = makeRequest('{level="info"} |= "thing1"'); + + const expectedFrame = cloneDeep(frame); + expectedFrame.meta = { + executedQueryString: 'something1', + preferredVisualisationType: 'logs', + searchWords: ['thing1'], + }; + expectedFrame.fields[2].type = FieldType.time; + + const expected: DataQueryResponse = { data: [expectedFrame] }; + + const result = transformBackendResult(response, request); + expect(result).toEqual(expected); + }); +}); diff --git a/public/app/plugins/datasource/loki/backendResultTransformer.ts b/public/app/plugins/datasource/loki/backendResultTransformer.ts index 5bd09ccb326..2639d95fda2 100644 --- a/public/app/plugins/datasource/loki/backendResultTransformer.ts +++ b/public/app/plugins/datasource/loki/backendResultTransformer.ts @@ -18,14 +18,34 @@ function setFrameMeta(frame: DataFrame, meta: QueryResultMeta): DataFrame { }; } +function processStreamFrame(frame: DataFrame, query: LokiQuery | undefined): DataFrame { + const meta: QueryResultMeta = { + preferredVisualisationType: 'logs', + searchWords: query !== undefined ? getHighlighterExpressionsFromQuery(formatQuery(query.expr)) : undefined, + }; + const newFrame = setFrameMeta(frame, meta); + const newFields = frame.fields.map((field) => { + // the nanosecond-timestamp field must have a type-time + if (field.name === 'tsNs') { + return { + ...field, + type: FieldType.time, + }; + } else { + return field; + } + }); + + return { + ...newFrame, + fields: newFields, + }; +} + function processStreamsFrames(frames: DataFrame[], queryMap: Map): DataFrame[] { return frames.map((frame) => { const query = frame.refId !== undefined ? queryMap.get(frame.refId) : undefined; - const meta: QueryResultMeta = { - preferredVisualisationType: 'logs', - searchWords: query !== undefined ? getHighlighterExpressionsFromQuery(formatQuery(query.expr)) : undefined, - }; - return setFrameMeta(frame, meta); + return processStreamFrame(frame, query); }); } diff --git a/public/app/plugins/datasource/loki/makeTableFrames.test.ts b/public/app/plugins/datasource/loki/makeTableFrames.test.ts index ed3160f0da6..2f33edf8792 100644 --- a/public/app/plugins/datasource/loki/makeTableFrames.test.ts +++ b/public/app/plugins/datasource/loki/makeTableFrames.test.ts @@ -133,7 +133,7 @@ const outputMulti = [ }, ]; -describe('loki backendResultTransformer', () => { +describe('loki makeTableFrames', () => { it('converts a single instant metric dataframe to table dataframe', () => { const result = makeTableFrames([frame1]); expect(result).toEqual(outputSingle);