Skip to content

Commit

Permalink
[exporter/debug] change normal verbosity behavior for logs
Browse files Browse the repository at this point in the history
  • Loading branch information
andrzej-stencel committed Apr 22, 2024
1 parent 6611edf commit d32c443
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 2 deletions.
25 changes: 25 additions & 0 deletions .chloggen/debug-exporter-normal-verbosity-logs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: breaking

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: exporter/debug

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: In `normal` verbosity, display one line of text for each log record

# One or more tracking issues or pull requests related to the change
issues: [7806]

# (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:

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
12 changes: 10 additions & 2 deletions exporter/debugexporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"go.uber.org/zap"

"go.opentelemetry.io/collector/config/configtelemetry"
"go.opentelemetry.io/collector/exporter/debugexporter/internal/normal"
"go.opentelemetry.io/collector/exporter/internal/otlptext"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
Expand All @@ -28,10 +29,16 @@ type debugExporter struct {
}

func newDebugExporter(logger *zap.Logger, verbosity configtelemetry.Level) *debugExporter {
var logsMarshaler plog.Marshaler
if verbosity == configtelemetry.LevelDetailed {
logsMarshaler = otlptext.NewTextLogsMarshaler()
} else {
logsMarshaler = normal.NewNormalLogsMarshaler()
}
return &debugExporter{
verbosity: verbosity,
logger: logger,
logsMarshaler: otlptext.NewTextLogsMarshaler(),
logsMarshaler: logsMarshaler,
metricsMarshaler: otlptext.NewTextMetricsMarshaler(),
tracesMarshaler: otlptext.NewTextTracesMarshaler(),
}
Expand Down Expand Up @@ -74,7 +81,8 @@ func (s *debugExporter) pushLogs(_ context.Context, ld plog.Logs) error {
s.logger.Info("LogsExporter",
zap.Int("resource logs", ld.ResourceLogs().Len()),
zap.Int("log records", ld.LogRecordCount()))
if s.verbosity != configtelemetry.LevelDetailed {

if s.verbosity == configtelemetry.LevelBasic {
return nil
}

Expand Down
52 changes: 52 additions & 0 deletions exporter/debugexporter/internal/normal/logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package normal

import (
"bytes"
"fmt"
"strings"

"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
)

type normalLogsMarshaler struct{}

// Ensure normalLogsMarshaller implements interface plog.Marshaler
var _ plog.Marshaler = normalLogsMarshaler{}

// NewNormalLogsMarshaler returns a plog.Marshaler for normal verbosity. It writes one line of text per log record
func NewNormalLogsMarshaler() plog.Marshaler {
return normalLogsMarshaler{}
}

func (normalLogsMarshaler) MarshalLogs(ld plog.Logs) ([]byte, error) {
var buffer bytes.Buffer
for i := 0; i < ld.ResourceLogs().Len(); i++ {
resourceLog := ld.ResourceLogs().At(i)
for j := 0; j < resourceLog.ScopeLogs().Len(); j++ {
scopeLog := resourceLog.ScopeLogs().At(j)
for k := 0; k < scopeLog.LogRecords().Len(); k++ {
logRecord := scopeLog.LogRecords().At(k)
logAttributes := writeAttributes(logRecord.Attributes())

logString := fmt.Sprintf("%s %s", logRecord.Body().AsString(), strings.Join(logAttributes, " "))
buffer.WriteString(logString)
buffer.WriteString("\n")
}
}
}
return buffer.Bytes(), nil
}

// writeAttributes returns a slice of strings in the form "attrKey=attrValue"
func writeAttributes(attributes pcommon.Map) (attributeStrings []string) {
attributes.Range(func(k string, v pcommon.Value) bool {
attribute := fmt.Sprintf("%s=%s", k, v.AsString())
attributeStrings = append(attributeStrings, attribute)
return true
})
return attributeStrings
}
101 changes: 101 additions & 0 deletions exporter/debugexporter/internal/normal/logs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package normal

import (
"testing"
"time"

"github.com/stretchr/testify/assert"

"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
)

func TestMarshalLogs(t *testing.T) {
tests := []struct {
name string
input plog.Logs
expected string
}{
{
name: "empty logs",
input: plog.NewLogs(),
expected: "",
},
{
name: "one log record",
input: func() plog.Logs {
logs := plog.NewLogs()
logRecord := logs.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty()
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(time.Date(2024, 1, 23, 17, 54, 41, 153, time.UTC)))
logRecord.SetSeverityNumber(plog.SeverityNumberInfo)
logRecord.SetSeverityText("INFO")
logRecord.Body().SetStr("Single line log message")
logRecord.Attributes().PutStr("key1", "value1")
logRecord.Attributes().PutStr("key2", "value2")
return logs
}(),
expected: `Single line log message key1=value1 key2=value2
`,
},
{
name: "two log records",
input: func() plog.Logs {
logs := plog.NewLogs()
logRecords := logs.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords()

logRecord := logRecords.AppendEmpty()
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(time.Date(2024, 1, 23, 17, 54, 41, 153, time.UTC)))
logRecord.SetSeverityNumber(plog.SeverityNumberInfo)
logRecord.SetSeverityText("INFO")
logRecord.Body().SetStr("Single line log message")
logRecord.Attributes().PutStr("key1", "value1")
logRecord.Attributes().PutStr("key2", "value2")

logRecord = logRecords.AppendEmpty()
logRecord.Body().SetStr("Multi-line\nlog message")
logRecord.Attributes().PutStr("mykey2", "myvalue2")
logRecord.Attributes().PutStr("mykey1", "myvalue1")
return logs
}(),
expected: `Single line log message key1=value1 key2=value2
Multi-line
log message mykey2=myvalue2 mykey1=myvalue1
`,
},
{
name: "log with maps in body and attributes",
input: func() plog.Logs {
logs := plog.NewLogs()
logRecord := logs.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty()
logRecord.SetTimestamp(pcommon.NewTimestampFromTime(time.Date(2020, 2, 11, 20, 26, 13, 789, time.UTC)))
logRecord.SetSeverityNumber(plog.SeverityNumberInfo)
logRecord.SetSeverityText("INFO")
body := logRecord.Body().SetEmptyMap()
body.PutStr("app", "CurrencyConverter")
bodyEvent := body.PutEmptyMap("event")
bodyEvent.PutStr("operation", "convert")
bodyEvent.PutStr("result", "success")
conversionAttr := logRecord.Attributes().PutEmptyMap("conversion")
conversionSourceAttr := conversionAttr.PutEmptyMap("source")
conversionSourceAttr.PutStr("currency", "USD")
conversionSourceAttr.PutDouble("amount", 34.22)
conversionDestinationAttr := conversionAttr.PutEmptyMap("destination")
conversionDestinationAttr.PutStr("currency", "EUR")
logRecord.Attributes().PutStr("service", "payments")
return logs
}(),
expected: `{"app":"CurrencyConverter","event":{"operation":"convert","result":"success"}} conversion={"destination":{"currency":"EUR"},"source":{"amount":34.22,"currency":"USD"}} service=payments
`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
output, err := NewNormalLogsMarshaler().MarshalLogs(tt.input)
assert.NoError(t, err)
assert.Equal(t, tt.expected, string(output))
})
}
}

0 comments on commit d32c443

Please sign in to comment.