Path: blob/main/component/otelcol/exporter/loki/internal/convert/convert_test.go
4100 views
package convert_test12import (3"context"4"testing"5"time"67"github.com/grafana/agent/component/common/loki"8"github.com/grafana/agent/component/otelcol/exporter/loki/internal/convert"9"github.com/grafana/agent/pkg/util"10"github.com/prometheus/client_golang/prometheus"11"github.com/stretchr/testify/require"12"go.opentelemetry.io/collector/pdata/plog"13)1415func TestConverter(t *testing.T) {16tt := []struct {17name string18input string19expectLine string20expectLabels string21expectTimestamp time.Time22}{23{24name: "log line without format hint",25input: `{26"resourceLogs": [27{28"resource": {29"attributes": [30{31"key": "host.name",32"value": {33"stringValue": "testHost"34}35}36],37"droppedAttributesCount": 138},39"scopeLogs": [40{41"scope": {42"name": "name",43"version": "version",44"droppedAttributesCount": 145},46"logRecords": [47{48"timeUnixNano": "1672827031972869000",49"observedTimeUnixNano": "1672827031972869000",50"severityNumber": 17,51"severityText": "Error",52"body": {53"stringValue": "hello world"54},55"attributes": [56{57"key": "sdkVersion",58"value": {59"stringValue": "1.0.1"60}61}62],63"droppedAttributesCount": 1,64"traceId": "0102030405060708090a0b0c0d0e0f10",65"spanId": "1112131415161718"66}67],68"schemaUrl": "ScopeLogsSchemaURL"69}70],71"schemaUrl": "testSchemaURL"72}73]74}`,75expectLine: `{"body":"hello world","traceid":"0102030405060708090a0b0c0d0e0f10","spanid":"1112131415161718","severity":"Error","attributes":{"sdkVersion":"1.0.1"},"resources":{"host.name":"testHost"}}`,76expectLabels: `{exporter="OTLP", level="ERROR"}`,77expectTimestamp: time.Date(2023, time.January, 4, 10, 10, 31, 972869000, time.UTC),78},79{80name: "log line with logfmt format hint in resource attributes",81input: `{82"resourceLogs": [83{84"resource": {85"attributes": [86{87"key": "host.name",88"value": {89"stringValue": "testHost"90}91},92{93"key": "loki.format",94"value": {95"stringValue": "logfmt"96}97}98],99"droppedAttributesCount": 1100},101"scopeLogs": [102{103"scope": {104"name": "name",105"version": "version",106"droppedAttributesCount": 1107},108"logRecords": [109{110"timeUnixNano": "1672827031972869000",111"observedTimeUnixNano": "1672827031972869000",112"severityNumber": 17,113"severityText": "Error",114"body": {115"stringValue": "msg=\"hello world\""116},117"attributes": [118{119"key": "sdkVersion",120"value": {121"stringValue": "1.0.1"122}123}124],125"droppedAttributesCount": 1,126"traceId": "0102030405060708090a0b0c0d0e0f10",127"spanId": "1112131415161718"128}129],130"schemaUrl": "ScopeLogsSchemaURL"131}132],133"schemaUrl": "testSchemaURL"134}135]136}`,137expectLine: `msg="hello world" traceID=0102030405060708090a0b0c0d0e0f10 spanID=1112131415161718 severity=Error attribute_sdkVersion=1.0.1 resource_host.name=testHost`,138expectLabels: `{exporter="OTLP", level="ERROR"}`,139expectTimestamp: time.Date(2023, time.January, 4, 10, 10, 31, 972869000, time.UTC),140},141{142name: "log line with logfmt format hint in log attributes",143input: `{144"resourceLogs": [145{146"resource": {147"attributes": [148{149"key": "host.name",150"value": {151"stringValue": "testHost"152}153}154],155"droppedAttributesCount": 1156},157"scopeLogs": [158{159"scope": {160"name": "name",161"version": "version",162"droppedAttributesCount": 1163},164"logRecords": [165{166"timeUnixNano": "1672827031972869000",167"observedTimeUnixNano": "1672827031972869000",168"severityNumber": 17,169"severityText": "Error",170"body": {171"stringValue": "msg=\"hello world\""172},173"attributes": [174{175"key": "sdkVersion",176"value": {177"stringValue": "1.0.1"178}179},180{181"key": "loki.format",182"value": {183"stringValue": "logfmt"184}185}186],187"droppedAttributesCount": 1,188"traceId": "0102030405060708090a0b0c0d0e0f10",189"spanId": "1112131415161718"190}191],192"schemaUrl": "ScopeLogsSchemaURL"193}194],195"schemaUrl": "testSchemaURL"196}197]198}`,199expectLine: `msg="hello world" traceID=0102030405060708090a0b0c0d0e0f10 spanID=1112131415161718 severity=Error attribute_sdkVersion=1.0.1 resource_host.name=testHost`,200expectLabels: `{exporter="OTLP", level="ERROR"}`,201expectTimestamp: time.Date(2023, time.January, 4, 10, 10, 31, 972869000, time.UTC),202},203{204name: "resource attributes converted to labels",205input: `{206"resourceLogs": [207{208"resource": {209"attributes": [210{211"key": "host.name",212"value": {213"stringValue": "testHost"214}215},216{217"key": "loki.resource.labels",218"value": {219"stringValue": "mylabel_1,mylabel_2"220}221},222{223"key": "mylabel_1",224"value": {225"stringValue": "value_1"226}227},228{229"key": "mylabel_2",230"value": {231"intValue": "42"232}233},234{235"key": "mylabel_3",236"value": {237"stringValue": "value_3"238}239}240],241"droppedAttributesCount": 1242},243"scopeLogs": [244{245"scope": {246"name": "name",247"version": "version",248"droppedAttributesCount": 1249},250"logRecords": [251{252"timeUnixNano": "1672827031972869000",253"observedTimeUnixNano": "1672827031972869000",254"severityNumber": 17,255"severityText": "Error",256"body": {257"stringValue": "msg=\"hello world\""258},259"attributes": [260{261"key": "sdkVersion",262"value": {263"stringValue": "1.0.1"264}265},266{267"key": "loki.format",268"value": {269"stringValue": "logfmt"270}271}272],273"droppedAttributesCount": 1,274"traceId": "0102030405060708090a0b0c0d0e0f10",275"spanId": "1112131415161718"276}277],278"schemaUrl": "ScopeLogsSchemaURL"279}280],281"schemaUrl": "testSchemaURL"282}283]284}`,285expectLine: `msg="hello world" traceID=0102030405060708090a0b0c0d0e0f10 spanID=1112131415161718 severity=Error attribute_sdkVersion=1.0.1 resource_host.name=testHost resource_mylabel_3=value_3`,286expectLabels: `{exporter="OTLP", level="ERROR", mylabel_1="value_1", mylabel_2="42"}`,287expectTimestamp: time.Date(2023, time.January, 4, 10, 10, 31, 972869000, time.UTC),288},289{290name: "log attributes converted to labels",291input: `{292"resourceLogs": [293{294"resource": {295"attributes": [296{297"key": "host.name",298"value": {299"stringValue": "testHost"300}301}302],303"droppedAttributesCount": 1304},305"scopeLogs": [306{307"scope": {308"name": "name",309"version": "version",310"droppedAttributesCount": 1311},312"logRecords": [313{314"timeUnixNano": "1672827031972869000",315"observedTimeUnixNano": "1672827031972869000",316"severityNumber": 17,317"severityText": "Error",318"body": {319"stringValue": "msg=\"hello world\""320},321"attributes": [322{323"key": "sdkVersion",324"value": {325"stringValue": "1.0.1"326}327},328{329"key": "loki.format",330"value": {331"stringValue": "logfmt"332}333},334{335"key": "loki.attribute.labels",336"value": {337"stringValue": "mylabel_1,mylabel_2"338}339},340{341"key": "mylabel_1",342"value": {343"stringValue": "value_1"344}345},346{347"key": "mylabel_2",348"value": {349"intValue": "42"350}351},352{353"key": "mylabel_3",354"value": {355"stringValue": "value_3"356}357}358],359"droppedAttributesCount": 1,360"traceId": "0102030405060708090a0b0c0d0e0f10",361"spanId": "1112131415161718"362}363],364"schemaUrl": "ScopeLogsSchemaURL"365}366],367"schemaUrl": "testSchemaURL"368}369]370}`,371expectLine: `msg="hello world" traceID=0102030405060708090a0b0c0d0e0f10 spanID=1112131415161718 severity=Error attribute_sdkVersion=1.0.1 attribute_mylabel_3=value_3 resource_host.name=testHost`,372expectLabels: `{exporter="OTLP", level="ERROR", mylabel_1="value_1", mylabel_2="42"}`,373expectTimestamp: time.Date(2023, time.January, 4, 10, 10, 31, 972869000, time.UTC),374},375{376name: "tenant resource attribute converted to label",377input: `{378"resourceLogs": [379{380"resource": {381"attributes": [382{383"key": "host.name",384"value": {385"stringValue": "testHost"386}387}388],389"droppedAttributesCount": 1390},391"scopeLogs": [392{393"scope": {394"name": "name",395"version": "version",396"droppedAttributesCount": 1397},398"logRecords": [399{400"timeUnixNano": "1672827031972869000",401"observedTimeUnixNano": "1672827031972869000",402"severityNumber": 17,403"severityText": "Error",404"body": {405"stringValue": "hello world"406},407"attributes": [408{409"key": "sdkVersion",410"value": {411"stringValue": "1.0.1"412}413},414{415"key": "loki.format",416"value": {417"stringValue": "json"418}419},420{421"key": "loki.tenant",422"value": {423"stringValue": "tenant.id"424}425},426{427"key": "tenant.id",428"value": {429"stringValue": "tenant_2"430}431}432],433"droppedAttributesCount": 1,434"traceId": "0102030405060708090a0b0c0d0e0f10",435"spanId": "1112131415161718"436}437],438"schemaUrl": "ScopeLogsSchemaURL"439}440],441"schemaUrl": "testSchemaURL"442}443]444}`,445expectLine: `{"body":"hello world","traceid":"0102030405060708090a0b0c0d0e0f10","spanid":"1112131415161718","severity":"Error","attributes":{"sdkVersion":"1.0.1"},"resources":{"host.name":"testHost"}}`,446expectLabels: `{exporter="OTLP", level="ERROR", tenant.id="tenant_2"}`,447expectTimestamp: time.Date(2023, time.January, 4, 10, 10, 31, 972869000, time.UTC),448},449}450451decoder := &plog.JSONUnmarshaler{}452for _, tc := range tt {453t.Run(tc.name, func(t *testing.T) {454payload, err := decoder.UnmarshalLogs([]byte(tc.input))455require.NoError(t, err)456457l := util.TestLogger(t)458ch1, ch2 := make(loki.LogsReceiver), make(loki.LogsReceiver)459conv := convert.New(l, prometheus.NewRegistry(), []loki.LogsReceiver{ch1, ch2})460go func() {461require.NoError(t, conv.ConsumeLogs(context.Background(), payload))462}()463464for i := 0; i < 2; i++ {465select {466case l := <-ch1:467require.Equal(t, tc.expectLine, l.Line)468require.Equal(t, tc.expectLabels, l.Labels.String())469require.Equal(t, tc.expectTimestamp, l.Timestamp.UTC())470case l := <-ch2:471require.Equal(t, tc.expectLine, l.Line)472require.Equal(t, tc.expectLabels, l.Labels.String())473require.Equal(t, tc.expectTimestamp, l.Timestamp.UTC())474case <-time.After(time.Second):475require.FailNow(t, "failed waiting for logs")476}477}478})479}480}481482483