diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ad295a572..da02f0fe843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added +- Add `RecordFactory` in `go.opentelemetry.io/otel/log/logtest` to facilitate testing the bridge implementations. (#5263) - Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5258) ## [1.26.0/0.48.0/0.2.0-alpha] 2024-04-24 diff --git a/log/logtest/doc.go b/log/logtest/doc.go new file mode 100644 index 00000000000..a0a8cf61ae4 --- /dev/null +++ b/log/logtest/doc.go @@ -0,0 +1,5 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package logtest is a testing helper package. +package logtest // import "go.opentelemetry.io/otel/log/logtest" diff --git a/log/logtest/factory.go b/log/logtest/factory.go new file mode 100644 index 00000000000..afa97d412ea --- /dev/null +++ b/log/logtest/factory.go @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package logtest // import "go.opentelemetry.io/otel/log/logtest" + +import ( + "time" + + "go.opentelemetry.io/otel/log" +) + +// RecordFactory is used to facilitate unit testing bridge implementations that +// make use of a [go.opentelemetry.io/otel/log.Record] +// +// Do not use RecordFactory to create records in production code. +type RecordFactory struct { + Timestamp time.Time + ObservedTimestamp time.Time + Severity log.Severity + SeverityText string + Body log.Value + Attributes []log.KeyValue +} + +// NewRecord returns a log record. +func (b RecordFactory) NewRecord() log.Record { + var record log.Record + record.SetTimestamp(b.Timestamp) + record.SetObservedTimestamp(b.ObservedTimestamp) + record.SetSeverity(b.Severity) + record.SetSeverityText(b.SeverityText) + record.SetBody(b.Body) + record.AddAttributes(b.Attributes...) + + return record +} diff --git a/log/logtest/factory_test.go b/log/logtest/factory_test.go new file mode 100644 index 00000000000..358087028a9 --- /dev/null +++ b/log/logtest/factory_test.go @@ -0,0 +1,88 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package logtest + +import ( + "slices" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/log" +) + +func TestRecordFactory(t *testing.T) { + now := time.Now() + observed := now.Add(time.Second) + severity := log.SeverityDebug + severityText := "DBG" + body := log.StringValue("Message") + attrs := []log.KeyValue{ + log.Int("int", 1), + log.String("str", "foo"), + log.Float64("flt", 3.14), + } + + got := RecordFactory{ + Timestamp: now, + ObservedTimestamp: observed, + Severity: severity, + SeverityText: severityText, + Body: body, + Attributes: attrs, + }.NewRecord() + + assert.Equal(t, now, got.Timestamp()) + assert.Equal(t, observed, got.ObservedTimestamp()) + assert.Equal(t, severity, got.Severity()) + assert.Equal(t, severityText, got.SeverityText()) + assertBody(t, body, got) + assertAttributes(t, attrs, got) +} + +func TestRecordFactoryMultiple(t *testing.T) { + now := time.Now() + attrs := []log.KeyValue{ + log.Int("int", 1), + log.String("str", "foo"), + log.Float64("flt", 3.14), + } + + f := RecordFactory{ + Timestamp: now, + Attributes: attrs, + } + + record1 := f.NewRecord() + f.Attributes = append(f.Attributes, log.Bool("added", true)) + + record2 := f.NewRecord() + assert.Equal(t, now, record2.Timestamp()) + assertAttributes(t, append(attrs, log.Bool("added", true)), record2) + + // Previously returned record is unharmed by the builder changes. + assert.Equal(t, now, record1.Timestamp()) + assertAttributes(t, attrs, record1) +} + +func assertBody(t *testing.T, want log.Value, r log.Record) { + t.Helper() + got := r.Body() + if !got.Equal(want) { + t.Errorf("Body value is not equal:\nwant: %v\ngot: %v", want, got) + } +} + +func assertAttributes(t *testing.T, want []log.KeyValue, r log.Record) { + t.Helper() + var got []log.KeyValue + r.WalkAttributes(func(kv log.KeyValue) bool { + got = append(got, kv) + return true + }) + if !slices.EqualFunc(want, got, log.KeyValue.Equal) { + t.Errorf("Attributes are not equal:\nwant: %v\ngot: %v", want, got) + } +} diff --git a/log/logtest/recorder.go b/log/logtest/recorder.go index 746527411ce..62c3eaf607e 100644 --- a/log/logtest/recorder.go +++ b/log/logtest/recorder.go @@ -1,8 +1,6 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -// Package logtest is a testing helper package. Users can retrieve an in-memory -// logger to verify the behavior of their integrations. package logtest // import "go.opentelemetry.io/otel/log/logtest" import (