Skip to content

Commit

Permalink
[issue-14288] Fix converting log resources to loki labels for multipl…
Browse files Browse the repository at this point in the history
…e log records.
  • Loading branch information
rogeriospinaintelipost committed Sep 20, 2022
1 parent 40e0533 commit e2a42e4
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 12 deletions.
9 changes: 4 additions & 5 deletions pkg/translator/loki/logs_to_loki.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package loki // import "github.com/open-telemetry/opentelemetry-collector-contri

import (
"fmt"

"github.com/grafana/loki/pkg/logproto"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
Expand Down Expand Up @@ -51,10 +50,6 @@ func LogsToLoki(ld plog.Logs) (*logproto.PushRequest, *PushReport) {
for i := 0; i < rls.Len(); i++ {
ills := rls.At(i).ScopeLogs()

// we may remove attributes, so we make a copy and change our version
resource := pcommon.NewResource()
rls.At(i).Resource().CopyTo(resource)

for j := 0; j < ills.Len(); j++ {
logs := ills.At(j).LogRecords()
for k := 0; k < logs.Len(); k++ {
Expand All @@ -63,6 +58,10 @@ func LogsToLoki(ld plog.Logs) (*logproto.PushRequest, *PushReport) {
log := plog.NewLogRecord()
logs.At(k).CopyTo(log)

// we may remove attributes, so we make a copy and change our version
resource := pcommon.NewResource()
rls.At(i).Resource().CopyTo(resource)

mergedLabels := convertAttributesAndMerge(log.Attributes(), resource.Attributes())
// remove the attributes that were promoted to labels
removeAttributes(log.Attributes(), mergedLabels)
Expand Down
35 changes: 28 additions & 7 deletions pkg/translator/loki/logs_to_loki_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestLogsToLoki(t *testing.T) {
attrs map[string]interface{}
res map[string]interface{}
expectedLabel string
expectedLine string
expectedLines []string
}{
{
desc: "with attribute to label and regular attribute",
Expand All @@ -42,7 +42,11 @@ func TestLogsToLoki(t *testing.T) {
hintAttributes: "host.name",
},
expectedLabel: `{exporter="OTLP", host.name="guarana"}`,
expectedLine: `{"traceid":"01020304000000000000000000000000","attributes":{"http.status":200}}`,
expectedLines: []string{
`{"traceid":"01020304000000000000000000000000","attributes":{"http.status":200}}`,
`{"traceid":"01020304050000000000000000000000","attributes":{"http.status":200}}`,
`{"traceid":"01020304050600000000000000000000","attributes":{"http.status":200}}`,
},
},
{
desc: "with resource to label and regular resource",
Expand All @@ -54,7 +58,11 @@ func TestLogsToLoki(t *testing.T) {
hintResources: "host.name",
},
expectedLabel: `{exporter="OTLP", host.name="guarana"}`,
expectedLine: `{"traceid":"01020304000000000000000000000000","resources":{"region.az":"eu-west-1a"}}`,
expectedLines: []string{
`{"traceid":"01020304000000000000000000000000","resources":{"region.az":"eu-west-1a"}}`,
`{"traceid":"01020304050000000000000000000000","resources":{"region.az":"eu-west-1a"}}`,
`{"traceid":"01020304050600000000000000000000","resources":{"region.az":"eu-west-1a"}}`,
},
},
}
for _, tC := range testCases {
Expand All @@ -64,11 +72,17 @@ func TestLogsToLoki(t *testing.T) {
ld.ResourceLogs().AppendEmpty()
ld.ResourceLogs().At(0).ScopeLogs().AppendEmpty()
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().AppendEmpty()
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().AppendEmpty()
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().AppendEmpty()
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(0).SetTraceID(pcommon.TraceID([16]byte{1, 2, 3, 4}))
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(1).SetTraceID(pcommon.TraceID([16]byte{1, 2, 3, 4, 5}))
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(2).SetTraceID(pcommon.TraceID([16]byte{1, 2, 3, 4, 5, 6}))

// copy the attributes from the test case to the log entry
if len(tC.attrs) > 0 {
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(0).Attributes().FromRaw(tC.attrs)
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(1).Attributes().FromRaw(tC.attrs)
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(2).Attributes().FromRaw(tC.attrs)
}
if len(tC.res) > 0 {
ld.ResourceLogs().At(0).Resource().Attributes().FromRaw(tC.res)
Expand All @@ -77,21 +91,28 @@ func TestLogsToLoki(t *testing.T) {
// we can't use copy here, as the value (Value) will be used as string lookup later, so, we need to convert it to string now
for k, v := range tC.hints {
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(0).Attributes().PutString(k, fmt.Sprintf("%v", v))
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(1).Attributes().PutString(k, fmt.Sprintf("%v", v))
ld.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(2).Attributes().PutString(k, fmt.Sprintf("%v", v))
}

// test
pushRequest, report := LogsToLoki(ld)
entries := pushRequest.Streams[0].Entries

var entriesLines []string
for i := 0; i < len(entries); i++ {
entriesLines = append(entriesLines, entries[i].Line)
}

// actualPushRequest is populated within the test http server, we check it here as assertions are better done at the
// end of the test function
assert.Empty(t, report.Errors)
assert.Equal(t, 0, report.NumDropped)
assert.Equal(t, 1, report.NumSubmitted)
assert.Equal(t, ld.LogRecordCount(), report.NumSubmitted)
assert.Len(t, pushRequest.Streams, 1)
assert.Equal(t, tC.expectedLabel, pushRequest.Streams[0].Labels)

assert.Len(t, pushRequest.Streams[0].Entries, 1)
assert.Equal(t, tC.expectedLine, pushRequest.Streams[0].Entries[0].Line)
assert.Len(t, entries, ld.LogRecordCount())
assert.ElementsMatch(t, tC.expectedLines, entriesLines)
})
}
}
16 changes: 16 additions & 0 deletions unreleased/issue-14288-loki-exporter-resource-attr-bug.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: loki

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Fix converting log resources to loki labels for more than one log record.

# One or more tracking issues related to the change
issues: [14288]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

0 comments on commit e2a42e4

Please sign in to comment.