From 1bf980bbc171d6e8aec29d708303d3d4010186f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Fri, 19 Apr 2024 10:51:29 +0200 Subject: [PATCH 01/21] sdk/log/logtest: Add RecordBuilder --- sdk/log/logtest/README.md | 3 + sdk/log/logtest/builder.go | 131 ++++++++++++++++++++++++++++++++ sdk/log/logtest/builder_test.go | 63 +++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 sdk/log/logtest/README.md create mode 100644 sdk/log/logtest/builder.go create mode 100644 sdk/log/logtest/builder_test.go diff --git a/sdk/log/logtest/README.md b/sdk/log/logtest/README.md new file mode 100644 index 00000000000..a2bf2690a5d --- /dev/null +++ b/sdk/log/logtest/README.md @@ -0,0 +1,3 @@ +# Log Test SDK + +[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/sdk/log/logtest)](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/log/logtest) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go new file mode 100644 index 00000000000..87e75c7d7df --- /dev/null +++ b/sdk/log/logtest/builder.go @@ -0,0 +1,131 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package logtest // import "go.opentelemetry.io/otel/sdk/log/logtest" + +import ( + "context" + "slices" + "time" + + "go.opentelemetry.io/otel/log" + "go.opentelemetry.io/otel/sdk/instrumentation" + sdklog "go.opentelemetry.io/otel/sdk/log" + "go.opentelemetry.io/otel/sdk/resource" +) + +// TODO: comment. +type RecordBuilder struct { + timestamp time.Time + // TODO: implement all fields + // observedTimestamp time.Time + // severity log.Severity + // severityText string + // body log.Value + attrs []log.KeyValue + // traceID trace.TraceID + // spanID trace.SpanID + // traceFlags trace.TraceFlags + + resource *resource.Resource + scope instrumentation.Scope + + dropped int +} + +// TODO: comment. +func (b RecordBuilder) Record() sdklog.Record { + var record sdklog.Record + p := processor(func(r sdklog.Record) { + r.SetTimestamp(b.timestamp) + r.SetAttributes(b.attrs...) + + // Generate dropped attributes. + for i := 0; i < b.dropped; i++ { + r.AddAttributes(log.KeyValue{}) + } + + record = r + }) + + attributeCountLimit := -1 + if b.dropped > 0 { + // Make sure that we can generate dropped attributes. + attributeCountLimit = len(b.attrs) + } + + provider := sdklog.NewLoggerProvider( + sdklog.WithResource(b.resource), + sdklog.WithAttributeCountLimit(attributeCountLimit), + sdklog.WithAttributeValueLengthLimit(-1), + sdklog.WithProcessor(p), + ) + + l := provider.Logger(b.scope.Name, + log.WithInstrumentationVersion(b.scope.Version), + log.WithSchemaURL(b.scope.SchemaURL), + ) + l.Emit(context.Background(), log.Record{}) // This executes the processor function. + return record +} + +// TODO: comment. +func (b RecordBuilder) SetTimestamp(t time.Time) RecordBuilder { + b.timestamp = t + return b +} + +// TODO: comment. +func (b RecordBuilder) AddAttributes(attrs ...log.KeyValue) RecordBuilder { + b.attrs = slices.Clone(b.attrs) + b.attrs = append(b.attrs, attrs...) + return b +} + +// TODO: comment. +func (b RecordBuilder) SetAttributes(attrs ...log.KeyValue) RecordBuilder { + b.attrs = slices.Clone(attrs) + return b +} + +// TODO: comment. +func (b RecordBuilder) SetInstrumentationScope(scope instrumentation.Scope) RecordBuilder { + b.scope = scope + return b +} + +// TODO: comment. +func (b RecordBuilder) SetResource(r *resource.Resource) RecordBuilder { + b.resource = r + return b +} + +// TODO: comment. +// +// Notice: The returned record is going to have an attribute count limit. +// Therefore, it will not be possible to add additional attributes on the record +// returned by the builder that has dropped attributes set to a value greater than 0 +// (they will be dropped). +func (b RecordBuilder) SetDroppedAttributes(n int) RecordBuilder { + b.dropped = n + return b +} + +type processor func(r sdklog.Record) + +func (p processor) OnEmit(ctx context.Context, r sdklog.Record) error { + p(r) + return nil +} + +func (processor) Enabled(context.Context, sdklog.Record) bool { + return true +} + +func (processor) Shutdown(ctx context.Context) error { + return nil +} + +func (processor) ForceFlush(context.Context) error { + return nil +} diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go new file mode 100644 index 00000000000..ab4efe6b92f --- /dev/null +++ b/sdk/log/logtest/builder_test.go @@ -0,0 +1,63 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package logtest + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/log" + "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/resource" +) + +func TestRecordBuilder(t *testing.T) { + now := time.Now() + attrs := []log.KeyValue{ + log.Int("int", 1), + log.String("str", "foo"), + log.Float64("flt", 3.14), + } + dropped := 3 + scope := instrumentation.Scope{ + Name: t.Name(), + } + r := resource.NewSchemaless(attribute.Bool("works", true)) + + b := RecordBuilder{}. + SetTimestamp(now). + SetAttributes(attrs...). + SetDroppedAttributes(dropped). + SetInstrumentationScope(scope). + SetResource(r) + + got := b.Record() + var gotAttrs []log.KeyValue + got.WalkAttributes(func(kv log.KeyValue) bool { + gotAttrs = append(gotAttrs, kv) + return true + }) + + assert.Equal(t, now, got.Timestamp()) + assert.Equal(t, attrs, gotAttrs) + assert.Equal(t, dropped, got.DroppedAttributes()) + assert.Equal(t, scope, got.InstrumentationScope()) + assert.Equal(t, *r, got.Resource()) + + got = b.AddAttributes(log.Bool("added", true)).Record() + gotAttrs = nil + got.WalkAttributes(func(kv log.KeyValue) bool { + gotAttrs = append(gotAttrs, kv) + return true + }) + + assert.Equal(t, now, got.Timestamp()) + assert.Equal(t, append(attrs, log.Bool("added", true)), gotAttrs) + assert.Equal(t, dropped, got.DroppedAttributes()) + assert.Equal(t, scope, got.InstrumentationScope()) + assert.Equal(t, *r, got.Resource()) +} From ecb21ad933d886a45074893ca31e286f97cf13c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:09:21 +0200 Subject: [PATCH 02/21] Introduce assertAttributes --- sdk/log/logtest/builder_test.go | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index ab4efe6b92f..bb05ed7b6e1 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -4,6 +4,7 @@ package logtest import ( + "slices" "testing" "time" @@ -12,6 +13,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/log" "go.opentelemetry.io/otel/sdk/instrumentation" + sdklog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/resource" ) @@ -34,30 +36,31 @@ func TestRecordBuilder(t *testing.T) { SetDroppedAttributes(dropped). SetInstrumentationScope(scope). SetResource(r) - got := b.Record() - var gotAttrs []log.KeyValue - got.WalkAttributes(func(kv log.KeyValue) bool { - gotAttrs = append(gotAttrs, kv) - return true - }) assert.Equal(t, now, got.Timestamp()) - assert.Equal(t, attrs, gotAttrs) + assertAttributes(t, attrs, got) assert.Equal(t, dropped, got.DroppedAttributes()) assert.Equal(t, scope, got.InstrumentationScope()) assert.Equal(t, *r, got.Resource()) got = b.AddAttributes(log.Bool("added", true)).Record() - gotAttrs = nil - got.WalkAttributes(func(kv log.KeyValue) bool { - gotAttrs = append(gotAttrs, kv) - return true - }) assert.Equal(t, now, got.Timestamp()) - assert.Equal(t, append(attrs, log.Bool("added", true)), gotAttrs) + assertAttributes(t, append(attrs, log.Bool("added", true)), got) assert.Equal(t, dropped, got.DroppedAttributes()) assert.Equal(t, scope, got.InstrumentationScope()) assert.Equal(t, *r, got.Resource()) } + +func assertAttributes(t *testing.T, want []log.KeyValue, r sdklog.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) + } +} From 24645128eb8ac47aabc669f9122e9da3967375a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:23:27 +0200 Subject: [PATCH 03/21] Add TestRecordBuilderMultiple --- sdk/log/logtest/builder_test.go | 39 ++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index bb05ed7b6e1..923deeefb06 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -43,14 +43,41 @@ func TestRecordBuilder(t *testing.T) { assert.Equal(t, dropped, got.DroppedAttributes()) assert.Equal(t, scope, got.InstrumentationScope()) assert.Equal(t, *r, got.Resource()) +} + +func TestRecordBuilderMultiple(t *testing.T) { + now := time.Now() + attrs := []log.KeyValue{ + log.Int("int", 1), + log.String("str", "foo"), + log.Float64("flt", 3.14), + } + scope := instrumentation.Scope{ + Name: t.Name(), + } - got = b.AddAttributes(log.Bool("added", true)).Record() + b := RecordBuilder{}. + SetTimestamp(now). + AddAttributes(attrs...). + SetDroppedAttributes(1). + SetInstrumentationScope(scope) - assert.Equal(t, now, got.Timestamp()) - assertAttributes(t, append(attrs, log.Bool("added", true)), got) - assert.Equal(t, dropped, got.DroppedAttributes()) - assert.Equal(t, scope, got.InstrumentationScope()) - assert.Equal(t, *r, got.Resource()) + record1 := b.Record() + + record2 := b. + AddAttributes(log.Bool("added", true)). + SetDroppedAttributes(2). + Record() + + assert.Equal(t, now, record1.Timestamp()) + assertAttributes(t, attrs, record1) + assert.Equal(t, 1, record1.DroppedAttributes()) + assert.Equal(t, scope, record1.InstrumentationScope()) + + assert.Equal(t, now, record2.Timestamp()) + assertAttributes(t, append(attrs, log.Bool("added", true)), record2) + assert.Equal(t, 2, record2.DroppedAttributes()) + assert.Equal(t, scope, record2.InstrumentationScope()) } func assertAttributes(t *testing.T, want []log.KeyValue, r sdklog.Record) { From 0faec774327f3f19ae45d392fe771523ef2db90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:29:30 +0200 Subject: [PATCH 04/21] Add SetObservedTimestamp --- sdk/log/logtest/builder.go | 12 +++++++++--- sdk/log/logtest/builder_test.go | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index 87e75c7d7df..bfd20617675 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -16,9 +16,8 @@ import ( // TODO: comment. type RecordBuilder struct { - timestamp time.Time - // TODO: implement all fields - // observedTimestamp time.Time + timestamp time.Time + observedTimestamp time.Time // severity log.Severity // severityText string // body log.Value @@ -38,6 +37,7 @@ func (b RecordBuilder) Record() sdklog.Record { var record sdklog.Record p := processor(func(r sdklog.Record) { r.SetTimestamp(b.timestamp) + r.SetObservedTimestamp(b.observedTimestamp) r.SetAttributes(b.attrs...) // Generate dropped attributes. @@ -75,6 +75,12 @@ func (b RecordBuilder) SetTimestamp(t time.Time) RecordBuilder { return b } +// TODO: comment. +func (b RecordBuilder) SetObservedTimestamp(t time.Time) RecordBuilder { + b.observedTimestamp = t + return b +} + // TODO: comment. func (b RecordBuilder) AddAttributes(attrs ...log.KeyValue) RecordBuilder { b.attrs = slices.Clone(b.attrs) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index 923deeefb06..29f4481366e 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -19,6 +19,7 @@ import ( func TestRecordBuilder(t *testing.T) { now := time.Now() + observed := now.Add(time.Second) attrs := []log.KeyValue{ log.Int("int", 1), log.String("str", "foo"), @@ -32,6 +33,7 @@ func TestRecordBuilder(t *testing.T) { b := RecordBuilder{}. SetTimestamp(now). + SetObservedTimestamp(observed). SetAttributes(attrs...). SetDroppedAttributes(dropped). SetInstrumentationScope(scope). @@ -39,6 +41,7 @@ func TestRecordBuilder(t *testing.T) { got := b.Record() assert.Equal(t, now, got.Timestamp()) + assert.Equal(t, observed, got.ObservedTimestamp()) assertAttributes(t, attrs, got) assert.Equal(t, dropped, got.DroppedAttributes()) assert.Equal(t, scope, got.InstrumentationScope()) From aa422b47a02e1b3043c118949cafbf852d136a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:33:28 +0200 Subject: [PATCH 05/21] Add SetSeverity --- sdk/log/logtest/builder.go | 9 ++++++++- sdk/log/logtest/builder_test.go | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index bfd20617675..93cb3782cfa 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -18,7 +18,7 @@ import ( type RecordBuilder struct { timestamp time.Time observedTimestamp time.Time - // severity log.Severity + severity log.Severity // severityText string // body log.Value attrs []log.KeyValue @@ -38,6 +38,7 @@ func (b RecordBuilder) Record() sdklog.Record { p := processor(func(r sdklog.Record) { r.SetTimestamp(b.timestamp) r.SetObservedTimestamp(b.observedTimestamp) + r.SetSeverity(b.severity) r.SetAttributes(b.attrs...) // Generate dropped attributes. @@ -81,6 +82,12 @@ func (b RecordBuilder) SetObservedTimestamp(t time.Time) RecordBuilder { return b } +// TODO: comment. +func (b RecordBuilder) SetSeverity(severity log.Severity) RecordBuilder { + b.severity = severity + return b +} + // TODO: comment. func (b RecordBuilder) AddAttributes(attrs ...log.KeyValue) RecordBuilder { b.attrs = slices.Clone(b.attrs) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index 29f4481366e..e709c427313 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -20,6 +20,7 @@ import ( func TestRecordBuilder(t *testing.T) { now := time.Now() observed := now.Add(time.Second) + severity := log.SeverityDebug attrs := []log.KeyValue{ log.Int("int", 1), log.String("str", "foo"), @@ -34,6 +35,7 @@ func TestRecordBuilder(t *testing.T) { b := RecordBuilder{}. SetTimestamp(now). SetObservedTimestamp(observed). + SetSeverity(severity). SetAttributes(attrs...). SetDroppedAttributes(dropped). SetInstrumentationScope(scope). @@ -42,6 +44,7 @@ func TestRecordBuilder(t *testing.T) { assert.Equal(t, now, got.Timestamp()) assert.Equal(t, observed, got.ObservedTimestamp()) + assert.Equal(t, severity, got.Severity()) assertAttributes(t, attrs, got) assert.Equal(t, dropped, got.DroppedAttributes()) assert.Equal(t, scope, got.InstrumentationScope()) From a20910e187445078f6db85f128b50343e1c9bee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:34:51 +0200 Subject: [PATCH 06/21] Refactor TestRecordBuilderMultiple --- sdk/log/logtest/builder_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index e709c427313..ddbe22b82be 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -75,15 +75,16 @@ func TestRecordBuilderMultiple(t *testing.T) { SetDroppedAttributes(2). Record() - assert.Equal(t, now, record1.Timestamp()) - assertAttributes(t, attrs, record1) - assert.Equal(t, 1, record1.DroppedAttributes()) - assert.Equal(t, scope, record1.InstrumentationScope()) - assert.Equal(t, now, record2.Timestamp()) assertAttributes(t, append(attrs, log.Bool("added", true)), record2) assert.Equal(t, 2, record2.DroppedAttributes()) assert.Equal(t, scope, record2.InstrumentationScope()) + + // Previously returned record is unharmed by the builder changes. + assert.Equal(t, now, record1.Timestamp()) + assertAttributes(t, attrs, record1) + assert.Equal(t, 1, record1.DroppedAttributes()) + assert.Equal(t, scope, record1.InstrumentationScope()) } func assertAttributes(t *testing.T, want []log.KeyValue, r sdklog.Record) { From c68ebf09994def61a1a5714d0f470f266d8d779b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:42:04 +0200 Subject: [PATCH 07/21] Add SetSeverityText and SetBody --- sdk/log/logtest/builder.go | 20 +++++++++++++++++--- sdk/log/logtest/builder_test.go | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index 93cb3782cfa..da78ca881e0 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -19,9 +19,9 @@ type RecordBuilder struct { timestamp time.Time observedTimestamp time.Time severity log.Severity - // severityText string - // body log.Value - attrs []log.KeyValue + severityText string + body log.Value + attrs []log.KeyValue // traceID trace.TraceID // spanID trace.SpanID // traceFlags trace.TraceFlags @@ -39,6 +39,8 @@ func (b RecordBuilder) Record() sdklog.Record { r.SetTimestamp(b.timestamp) r.SetObservedTimestamp(b.observedTimestamp) r.SetSeverity(b.severity) + r.SetSeverityText(b.severityText) + r.SetBody(b.body) r.SetAttributes(b.attrs...) // Generate dropped attributes. @@ -88,6 +90,18 @@ func (b RecordBuilder) SetSeverity(severity log.Severity) RecordBuilder { return b } +// TODO: comment. +func (b RecordBuilder) SetSeverityText(text string) RecordBuilder { + b.severityText = text + return b +} + +// TODO: comment. +func (b RecordBuilder) SetBody(v log.Value) RecordBuilder { + b.body = v + return b +} + // TODO: comment. func (b RecordBuilder) AddAttributes(attrs ...log.KeyValue) RecordBuilder { b.attrs = slices.Clone(b.attrs) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index ddbe22b82be..af1441780ea 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -21,6 +21,8 @@ func TestRecordBuilder(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"), @@ -36,6 +38,8 @@ func TestRecordBuilder(t *testing.T) { SetTimestamp(now). SetObservedTimestamp(observed). SetSeverity(severity). + SetSeverityText(severityText). + SetBody(body). SetAttributes(attrs...). SetDroppedAttributes(dropped). SetInstrumentationScope(scope). @@ -45,6 +49,8 @@ func TestRecordBuilder(t *testing.T) { 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) assert.Equal(t, dropped, got.DroppedAttributes()) assert.Equal(t, scope, got.InstrumentationScope()) @@ -87,6 +93,14 @@ func TestRecordBuilderMultiple(t *testing.T) { assert.Equal(t, scope, record1.InstrumentationScope()) } +func assertBody(t *testing.T, want log.Value, r sdklog.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 sdklog.Record) { t.Helper() var got []log.KeyValue From 0f44304f28301b3014fd020f423f9a238c82cffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:50:40 +0200 Subject: [PATCH 08/21] Add SetTraceID SetSpanID SetTraceFlags --- sdk/log/logtest/builder.go | 33 ++++++++++++++++++++++++++++----- sdk/log/logtest/builder_test.go | 10 ++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index da78ca881e0..1a91cc01eff 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/otel/sdk/instrumentation" sdklog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/trace" ) // TODO: comment. @@ -22,9 +23,9 @@ type RecordBuilder struct { severityText string body log.Value attrs []log.KeyValue - // traceID trace.TraceID - // spanID trace.SpanID - // traceFlags trace.TraceFlags + traceID trace.TraceID + spanID trace.SpanID + traceFlags trace.TraceFlags resource *resource.Resource scope instrumentation.Scope @@ -48,6 +49,10 @@ func (b RecordBuilder) Record() sdklog.Record { r.AddAttributes(log.KeyValue{}) } + r.SetTraceID(b.traceID) + r.SetSpanID(b.spanID) + r.SetTraceFlags(b.traceFlags) + record = r }) @@ -116,8 +121,20 @@ func (b RecordBuilder) SetAttributes(attrs ...log.KeyValue) RecordBuilder { } // TODO: comment. -func (b RecordBuilder) SetInstrumentationScope(scope instrumentation.Scope) RecordBuilder { - b.scope = scope +func (b RecordBuilder) SetTraceID(traceID trace.TraceID) RecordBuilder { + b.traceID = traceID + return b +} + +// TODO: comment. +func (b RecordBuilder) SetSpanID(spanID trace.SpanID) RecordBuilder { + b.spanID = spanID + return b +} + +// TODO: comment. +func (b RecordBuilder) SetTraceFlags(flags trace.TraceFlags) RecordBuilder { + b.traceFlags = flags return b } @@ -127,6 +144,12 @@ func (b RecordBuilder) SetResource(r *resource.Resource) RecordBuilder { return b } +// TODO: comment. +func (b RecordBuilder) SetInstrumentationScope(scope instrumentation.Scope) RecordBuilder { + b.scope = scope + return b +} + // TODO: comment. // // Notice: The returned record is going to have an attribute count limit. diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index af1441780ea..15a3f818734 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -15,6 +15,7 @@ import ( "go.opentelemetry.io/otel/sdk/instrumentation" sdklog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/trace" ) func TestRecordBuilder(t *testing.T) { @@ -28,6 +29,9 @@ func TestRecordBuilder(t *testing.T) { log.String("str", "foo"), log.Float64("flt", 3.14), } + traceID := trace.TraceID([16]byte{1}) + spanID := trace.SpanID([8]byte{2}) + traceFlags := trace.FlagsSampled dropped := 3 scope := instrumentation.Scope{ Name: t.Name(), @@ -41,6 +45,9 @@ func TestRecordBuilder(t *testing.T) { SetSeverityText(severityText). SetBody(body). SetAttributes(attrs...). + SetTraceID(traceID). + SetSpanID(spanID). + SetTraceFlags(traceFlags). SetDroppedAttributes(dropped). SetInstrumentationScope(scope). SetResource(r) @@ -53,6 +60,9 @@ func TestRecordBuilder(t *testing.T) { assertBody(t, body, got) assertAttributes(t, attrs, got) assert.Equal(t, dropped, got.DroppedAttributes()) + assert.Equal(t, traceID, got.TraceID()) + assert.Equal(t, spanID, got.SpanID()) + assert.Equal(t, traceFlags, got.TraceFlags()) assert.Equal(t, scope, got.InstrumentationScope()) assert.Equal(t, *r, got.Resource()) } From 5c16e95fe5664957fbfab7866a6f74ea754f721e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 11:54:40 +0200 Subject: [PATCH 09/21] Add setters comments --- sdk/log/logtest/builder.go | 39 +++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index 1a91cc01eff..dcc8c4f1fea 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -77,80 +77,93 @@ func (b RecordBuilder) Record() sdklog.Record { return record } -// TODO: comment. +// SetTimestamp sets the timestamp +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetTimestamp(t time.Time) RecordBuilder { b.timestamp = t return b } -// TODO: comment. +// SetObservedTimestamp sets the observed timestamp +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetObservedTimestamp(t time.Time) RecordBuilder { b.observedTimestamp = t return b } -// TODO: comment. +// SetSeverity sets the severity +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetSeverity(severity log.Severity) RecordBuilder { b.severity = severity return b } -// TODO: comment. +// SetSeverityText sets the severity text +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetSeverityText(text string) RecordBuilder { b.severityText = text return b } -// TODO: comment. +// SetBody sets the body +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetBody(v log.Value) RecordBuilder { b.body = v return b } -// TODO: comment. +// AddAttributes adds attributes +// to the record that is going to be returned by the builder. func (b RecordBuilder) AddAttributes(attrs ...log.KeyValue) RecordBuilder { b.attrs = slices.Clone(b.attrs) b.attrs = append(b.attrs, attrs...) return b } -// TODO: comment. +// SetAttributes sets the attributes +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetAttributes(attrs ...log.KeyValue) RecordBuilder { b.attrs = slices.Clone(attrs) return b } -// TODO: comment. +// SetTraceID sets the trace ID +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetTraceID(traceID trace.TraceID) RecordBuilder { b.traceID = traceID return b } -// TODO: comment. +// SetSpanID sets the span ID +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetSpanID(spanID trace.SpanID) RecordBuilder { b.spanID = spanID return b } -// TODO: comment. +// SetTraceFlags sets the trace flags +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetTraceFlags(flags trace.TraceFlags) RecordBuilder { b.traceFlags = flags return b } -// TODO: comment. +// SetResource sets the resource +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetResource(r *resource.Resource) RecordBuilder { b.resource = r return b } -// TODO: comment. +// SetInstrumentationScope sets the instrumentation scope +// of the record that is going to be returned by the builder. func (b RecordBuilder) SetInstrumentationScope(scope instrumentation.Scope) RecordBuilder { b.scope = scope return b } -// TODO: comment. +// SetDroppedAttributes sets the dropped attributes +// of the record that is going to be returned by the builder. // // Notice: The returned record is going to have an attribute count limit. // Therefore, it will not be possible to add additional attributes on the record From f3b40d9b2980ba7c660268dd709f651f54c3939a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:00:54 +0200 Subject: [PATCH 10/21] Document RecordBuilder type and RecordBuilder.Record method --- sdk/log/logtest/builder.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index dcc8c4f1fea..0d6f1b9a4b4 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -15,7 +15,9 @@ import ( "go.opentelemetry.io/otel/trace" ) -// TODO: comment. +// RecordBuilder is used to facilitate unit testing implementations of +// [go.opentelemetry.io/otel/sdk/log.Exporter] +// and [go.opentelemetry.io/otel/sdk/log.Processor]. type RecordBuilder struct { timestamp time.Time observedTimestamp time.Time @@ -33,7 +35,7 @@ type RecordBuilder struct { dropped int } -// TODO: comment. +// Record returns the accumulated log record. func (b RecordBuilder) Record() sdklog.Record { var record sdklog.Record p := processor(func(r sdklog.Record) { From be8e20f608e75b5ef2807e66fb576ada4646e899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:03:42 +0200 Subject: [PATCH 11/21] Add a notice to not use RecordBuilder in production code --- sdk/log/logtest/builder.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index 0d6f1b9a4b4..8745f278be4 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -18,6 +18,8 @@ import ( // RecordBuilder is used to facilitate unit testing implementations of // [go.opentelemetry.io/otel/sdk/log.Exporter] // and [go.opentelemetry.io/otel/sdk/log.Processor]. +// +// Do not use RecordBuilder to create records in production code. type RecordBuilder struct { timestamp time.Time observedTimestamp time.Time From 89858e843a7aa74d3d6783e9ba237f3eb527a9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:07:20 +0200 Subject: [PATCH 12/21] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99b8a28907d..8d68230567b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm This new module contains an exporter prints log records to STDOUT. This module is unstable and breaking changes may be introduced. See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. (#5240) +- Add `RecordBuilder` in `go.opentelemetry.io/otel/log/logtest` to facilitate testing the exporter and processor implementations. (#5234) ### Changed From 2cab9adadfc47cddca4b7c06e4b7418820aa87a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:07:48 +0200 Subject: [PATCH 13/21] Fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d68230567b..79cc76d5d4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm This new module contains an exporter prints log records to STDOUT. This module is unstable and breaking changes may be introduced. See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. (#5240) -- Add `RecordBuilder` in `go.opentelemetry.io/otel/log/logtest` to facilitate testing the exporter and processor implementations. (#5234) +- Add `RecordBuilder` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5234) ### Changed From 7676b8be15d75d074dd3209ea36fb3fd9b9ae99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:15:30 +0200 Subject: [PATCH 14/21] Add package comment --- sdk/log/logtest/builder.go | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index 8745f278be4..07a17c631ee 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +// Package logtest is a testing helper package. package logtest // import "go.opentelemetry.io/otel/sdk/log/logtest" import ( From 4df52f021385253d06dc62f71d03dea0ec589dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:37:31 +0200 Subject: [PATCH 15/21] Add ExampleRecordBuilder --- sdk/log/logtest/example_test.go | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 sdk/log/logtest/example_test.go diff --git a/sdk/log/logtest/example_test.go b/sdk/log/logtest/example_test.go new file mode 100644 index 00000000000..51fb1ee75e6 --- /dev/null +++ b/sdk/log/logtest/example_test.go @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package logtest is a testing helper package. +package logtest_test + +import ( + "context" + "fmt" + "io" + "os" + + logapi "go.opentelemetry.io/otel/log" + "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/log" + "go.opentelemetry.io/otel/sdk/log/logtest" +) + +func ExampleRecordBuilder() { + exp := exporter{os.Stdout} + b := logtest.RecordBuilder{}.SetInstrumentationScope(instrumentation.Scope{Name: "myapp"}) + r1 := b.SetBody(logapi.StringValue("foo")).Record() + r2 := b.SetBody(logapi.StringValue("bar")).Record() + + _ = exp.Export(context.Background(), []log.Record{r1, r2}) + + // Output: + // scope=myapp msg=foo + // scope=myapp msg=bar +} + +// Compile time check exporter implements log.Exporter. +var _ log.Exporter = exporter{} + +type exporter struct{ io.Writer } + +func (e exporter) Export(ctx context.Context, records []log.Record) error { + for i, r := range records { + if i != 0 { + e.Write([]byte("\n")) + } + fmt.Fprintf(e, "scope=%s msg=%s", r.InstrumentationScope().Name, r.Body().String()) + } + return nil +} + +func (e exporter) Shutdown(context.Context) error { + return nil +} + +// appropriate error should be returned in these situations. +func (e exporter) ForceFlush(context.Context) error { + return nil +} From 44794f59585e14ebdfce6c485b8eecf86c802e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Mon, 22 Apr 2024 12:47:02 +0200 Subject: [PATCH 16/21] Add errcheck --- sdk/log/logtest/example_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sdk/log/logtest/example_test.go b/sdk/log/logtest/example_test.go index 51fb1ee75e6..3e5370c12f7 100644 --- a/sdk/log/logtest/example_test.go +++ b/sdk/log/logtest/example_test.go @@ -37,9 +37,13 @@ type exporter struct{ io.Writer } func (e exporter) Export(ctx context.Context, records []log.Record) error { for i, r := range records { if i != 0 { - e.Write([]byte("\n")) + if _, err := e.Write([]byte("\n")); err != nil { + return err + } + } + if _, err := fmt.Fprintf(e, "scope=%s msg=%s", r.InstrumentationScope().Name, r.Body().String()); err != nil { + return err } - fmt.Fprintf(e, "scope=%s msg=%s", r.InstrumentationScope().Name, r.Body().String()) } return nil } From ea8b3198e0f889b174ceba5bed429bf15bc5bae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 23 Apr 2024 19:54:54 +0200 Subject: [PATCH 17/21] sdk/log/logtest: Add RecordFactory --- CHANGELOG.md | 2 +- sdk/log/logtest/builder.go | 171 +++++++------------------------- sdk/log/logtest/builder_test.go | 52 +++++----- sdk/log/logtest/example_test.go | 14 ++- 4 files changed, 74 insertions(+), 165 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79bc3ace35f..d1ba2528e8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. (#5240) - The `go.opentelemetry.io/otel/semconv/v1.25.0` package. The package contains semantic conventions from the `v1.25.0` version of the OpenTelemetry Semantic Conventions. (#5254) -- Add `RecordBuilder` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5234) +- Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5234) ### Changed diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index 07a17c631ee..fd096a626b9 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -16,169 +16,72 @@ import ( "go.opentelemetry.io/otel/trace" ) -// RecordBuilder is used to facilitate unit testing implementations of +// RecordFactory is used to facilitate unit testing implementations of // [go.opentelemetry.io/otel/sdk/log.Exporter] // and [go.opentelemetry.io/otel/sdk/log.Processor]. // -// Do not use RecordBuilder to create records in production code. -type RecordBuilder struct { - timestamp time.Time - observedTimestamp time.Time - severity log.Severity - severityText string - body log.Value - attrs []log.KeyValue - traceID trace.TraceID - spanID trace.SpanID - traceFlags trace.TraceFlags - - resource *resource.Resource - scope instrumentation.Scope - - dropped int -} - -// Record returns the accumulated log record. -func (b RecordBuilder) Record() sdklog.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 + TraceID trace.TraceID + SpanID trace.SpanID + TraceFlags trace.TraceFlags + + Resource *resource.Resource + InstrumentationScope instrumentation.Scope + + DroppedAttributes int +} + +// Record returns a log record. +func (b RecordFactory) Record() sdklog.Record { var record sdklog.Record p := processor(func(r sdklog.Record) { - r.SetTimestamp(b.timestamp) - r.SetObservedTimestamp(b.observedTimestamp) - r.SetSeverity(b.severity) - r.SetSeverityText(b.severityText) - r.SetBody(b.body) - r.SetAttributes(b.attrs...) + r.SetTimestamp(b.Timestamp) + r.SetObservedTimestamp(b.ObservedTimestamp) + r.SetSeverity(b.Severity) + r.SetSeverityText(b.SeverityText) + r.SetBody(b.Body) + r.SetAttributes(slices.Clone(b.Attributes)...) // Generate dropped attributes. - for i := 0; i < b.dropped; i++ { + for i := 0; i < b.DroppedAttributes; i++ { r.AddAttributes(log.KeyValue{}) } - r.SetTraceID(b.traceID) - r.SetSpanID(b.spanID) - r.SetTraceFlags(b.traceFlags) + r.SetTraceID(b.TraceID) + r.SetSpanID(b.SpanID) + r.SetTraceFlags(b.TraceFlags) record = r }) attributeCountLimit := -1 - if b.dropped > 0 { + if b.DroppedAttributes > 0 { // Make sure that we can generate dropped attributes. - attributeCountLimit = len(b.attrs) + attributeCountLimit = len(b.Attributes) } provider := sdklog.NewLoggerProvider( - sdklog.WithResource(b.resource), + sdklog.WithResource(b.Resource), sdklog.WithAttributeCountLimit(attributeCountLimit), sdklog.WithAttributeValueLengthLimit(-1), sdklog.WithProcessor(p), ) - l := provider.Logger(b.scope.Name, - log.WithInstrumentationVersion(b.scope.Version), - log.WithSchemaURL(b.scope.SchemaURL), + l := provider.Logger(b.InstrumentationScope.Name, + log.WithInstrumentationVersion(b.InstrumentationScope.Version), + log.WithSchemaURL(b.InstrumentationScope.SchemaURL), ) l.Emit(context.Background(), log.Record{}) // This executes the processor function. return record } -// SetTimestamp sets the timestamp -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetTimestamp(t time.Time) RecordBuilder { - b.timestamp = t - return b -} - -// SetObservedTimestamp sets the observed timestamp -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetObservedTimestamp(t time.Time) RecordBuilder { - b.observedTimestamp = t - return b -} - -// SetSeverity sets the severity -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetSeverity(severity log.Severity) RecordBuilder { - b.severity = severity - return b -} - -// SetSeverityText sets the severity text -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetSeverityText(text string) RecordBuilder { - b.severityText = text - return b -} - -// SetBody sets the body -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetBody(v log.Value) RecordBuilder { - b.body = v - return b -} - -// AddAttributes adds attributes -// to the record that is going to be returned by the builder. -func (b RecordBuilder) AddAttributes(attrs ...log.KeyValue) RecordBuilder { - b.attrs = slices.Clone(b.attrs) - b.attrs = append(b.attrs, attrs...) - return b -} - -// SetAttributes sets the attributes -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetAttributes(attrs ...log.KeyValue) RecordBuilder { - b.attrs = slices.Clone(attrs) - return b -} - -// SetTraceID sets the trace ID -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetTraceID(traceID trace.TraceID) RecordBuilder { - b.traceID = traceID - return b -} - -// SetSpanID sets the span ID -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetSpanID(spanID trace.SpanID) RecordBuilder { - b.spanID = spanID - return b -} - -// SetTraceFlags sets the trace flags -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetTraceFlags(flags trace.TraceFlags) RecordBuilder { - b.traceFlags = flags - return b -} - -// SetResource sets the resource -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetResource(r *resource.Resource) RecordBuilder { - b.resource = r - return b -} - -// SetInstrumentationScope sets the instrumentation scope -// of the record that is going to be returned by the builder. -func (b RecordBuilder) SetInstrumentationScope(scope instrumentation.Scope) RecordBuilder { - b.scope = scope - return b -} - -// SetDroppedAttributes sets the dropped attributes -// of the record that is going to be returned by the builder. -// -// Notice: The returned record is going to have an attribute count limit. -// Therefore, it will not be possible to add additional attributes on the record -// returned by the builder that has dropped attributes set to a value greater than 0 -// (they will be dropped). -func (b RecordBuilder) SetDroppedAttributes(n int) RecordBuilder { - b.dropped = n - return b -} - type processor func(r sdklog.Record) func (p processor) OnEmit(ctx context.Context, r sdklog.Record) error { diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index 15a3f818734..2ef27c1f619 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -18,7 +18,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -func TestRecordBuilder(t *testing.T) { +func TestRecordFactory(t *testing.T) { now := time.Now() observed := now.Add(time.Second) severity := log.SeverityDebug @@ -38,20 +38,20 @@ func TestRecordBuilder(t *testing.T) { } r := resource.NewSchemaless(attribute.Bool("works", true)) - b := RecordBuilder{}. - SetTimestamp(now). - SetObservedTimestamp(observed). - SetSeverity(severity). - SetSeverityText(severityText). - SetBody(body). - SetAttributes(attrs...). - SetTraceID(traceID). - SetSpanID(spanID). - SetTraceFlags(traceFlags). - SetDroppedAttributes(dropped). - SetInstrumentationScope(scope). - SetResource(r) - got := b.Record() + got := RecordFactory{ + Timestamp: now, + ObservedTimestamp: observed, + Severity: severity, + SeverityText: severityText, + Body: body, + Attributes: attrs, + TraceID: traceID, + SpanID: spanID, + TraceFlags: traceFlags, + DroppedAttributes: dropped, + InstrumentationScope: scope, + Resource: r, + }.Record() assert.Equal(t, now, got.Timestamp()) assert.Equal(t, observed, got.ObservedTimestamp()) @@ -67,7 +67,7 @@ func TestRecordBuilder(t *testing.T) { assert.Equal(t, *r, got.Resource()) } -func TestRecordBuilderMultiple(t *testing.T) { +func TestRecordFactoryMultiple(t *testing.T) { now := time.Now() attrs := []log.KeyValue{ log.Int("int", 1), @@ -78,18 +78,18 @@ func TestRecordBuilderMultiple(t *testing.T) { Name: t.Name(), } - b := RecordBuilder{}. - SetTimestamp(now). - AddAttributes(attrs...). - SetDroppedAttributes(1). - SetInstrumentationScope(scope) + f := RecordFactory{ + Timestamp: now, + Attributes: attrs, + DroppedAttributes: 1, + InstrumentationScope: scope, + } - record1 := b.Record() + record1 := f.Record() - record2 := b. - AddAttributes(log.Bool("added", true)). - SetDroppedAttributes(2). - Record() + f.Attributes = append(f.Attributes, log.Bool("added", true)) + f.DroppedAttributes = 2 + record2 := f.Record() assert.Equal(t, now, record2.Timestamp()) assertAttributes(t, append(attrs, log.Bool("added", true)), record2) diff --git a/sdk/log/logtest/example_test.go b/sdk/log/logtest/example_test.go index 3e5370c12f7..2be86a5715b 100644 --- a/sdk/log/logtest/example_test.go +++ b/sdk/log/logtest/example_test.go @@ -16,11 +16,17 @@ import ( "go.opentelemetry.io/otel/sdk/log/logtest" ) -func ExampleRecordBuilder() { +func ExampleRecordFactory() { exp := exporter{os.Stdout} - b := logtest.RecordBuilder{}.SetInstrumentationScope(instrumentation.Scope{Name: "myapp"}) - r1 := b.SetBody(logapi.StringValue("foo")).Record() - r2 := b.SetBody(logapi.StringValue("bar")).Record() + rf := logtest.RecordFactory{ + InstrumentationScope: instrumentation.Scope{Name: "myapp"}, + } + + rf.Body = logapi.StringValue("foo") + r1 := rf.Record() + + rf.Body = logapi.StringValue("bar") + r2 := rf.Record() _ = exp.Export(context.Background(), []log.Record{r1, r2}) From 2bb62ff22f29e2894b3f8aea0e186c4084b3e7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 23 Apr 2024 20:11:32 +0200 Subject: [PATCH 18/21] Rename Record to NewRecord --- sdk/log/logtest/builder.go | 4 ++-- sdk/log/logtest/builder_test.go | 6 +++--- sdk/log/logtest/example_test.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/builder.go index fd096a626b9..850869141d5 100644 --- a/sdk/log/logtest/builder.go +++ b/sdk/log/logtest/builder.go @@ -38,8 +38,8 @@ type RecordFactory struct { DroppedAttributes int } -// Record returns a log record. -func (b RecordFactory) Record() sdklog.Record { +// NewRecord returns a log record. +func (b RecordFactory) NewRecord() sdklog.Record { var record sdklog.Record p := processor(func(r sdklog.Record) { r.SetTimestamp(b.Timestamp) diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/builder_test.go index 2ef27c1f619..dc9662cd633 100644 --- a/sdk/log/logtest/builder_test.go +++ b/sdk/log/logtest/builder_test.go @@ -51,7 +51,7 @@ func TestRecordFactory(t *testing.T) { DroppedAttributes: dropped, InstrumentationScope: scope, Resource: r, - }.Record() + }.NewRecord() assert.Equal(t, now, got.Timestamp()) assert.Equal(t, observed, got.ObservedTimestamp()) @@ -85,11 +85,11 @@ func TestRecordFactoryMultiple(t *testing.T) { InstrumentationScope: scope, } - record1 := f.Record() + record1 := f.NewRecord() f.Attributes = append(f.Attributes, log.Bool("added", true)) f.DroppedAttributes = 2 - record2 := f.Record() + record2 := f.NewRecord() assert.Equal(t, now, record2.Timestamp()) assertAttributes(t, append(attrs, log.Bool("added", true)), record2) diff --git a/sdk/log/logtest/example_test.go b/sdk/log/logtest/example_test.go index 2be86a5715b..68376a726c1 100644 --- a/sdk/log/logtest/example_test.go +++ b/sdk/log/logtest/example_test.go @@ -23,10 +23,10 @@ func ExampleRecordFactory() { } rf.Body = logapi.StringValue("foo") - r1 := rf.Record() + r1 := rf.NewRecord() rf.Body = logapi.StringValue("bar") - r2 := rf.Record() + r2 := rf.NewRecord() _ = exp.Export(context.Background(), []log.Record{r1, r2}) From 6e2ff4e5978bb0c6bc04759986726b5281d8c671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Tue, 23 Apr 2024 20:12:22 +0200 Subject: [PATCH 19/21] Rename files --- sdk/log/logtest/{builder.go => factory.go} | 0 sdk/log/logtest/{builder_test.go => factory_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename sdk/log/logtest/{builder.go => factory.go} (100%) rename sdk/log/logtest/{builder_test.go => factory_test.go} (100%) diff --git a/sdk/log/logtest/builder.go b/sdk/log/logtest/factory.go similarity index 100% rename from sdk/log/logtest/builder.go rename to sdk/log/logtest/factory.go diff --git a/sdk/log/logtest/builder_test.go b/sdk/log/logtest/factory_test.go similarity index 100% rename from sdk/log/logtest/builder_test.go rename to sdk/log/logtest/factory_test.go From 59f0956d18e9392b358f6117b6c8f05ee3f45e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Wed, 24 Apr 2024 09:51:55 +0200 Subject: [PATCH 20/21] Update CHANGELOG.md Co-authored-by: Damien Mathieu <42@dmathieu.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1ba2528e8a..2bac75bb9ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. (#5240) - The `go.opentelemetry.io/otel/semconv/v1.25.0` package. The package contains semantic conventions from the `v1.25.0` version of the OpenTelemetry Semantic Conventions. (#5254) -- Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5234) +- Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5258) ### Changed From fff83e79b52b2a4c917ae61df727b1b5732b9538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Paj=C4=85k?= Date: Wed, 24 Apr 2024 18:51:55 +0200 Subject: [PATCH 21/21] Update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fcd4238884..56ad295a572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Added + +- 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 ### Added @@ -28,7 +32,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. (#5240) - The `go.opentelemetry.io/otel/semconv/v1.25.0` package. The package contains semantic conventions from the `v1.25.0` version of the OpenTelemetry Semantic Conventions. (#5254) -- Add `RecordFactory` in `go.opentelemetry.io/otel/sdk/log/logtest` to facilitate testing the exporter and processor implementations. (#5258) ### Changed