Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions sdk/log/internal/counter/counter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions sdk/log/internal/counter/counter_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions sdk/log/internal/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
// Package internal provides internal functionality for the sdk/log package.
package internal // import "go.opentelemetry.io/otel/sdk/log/internal"

//go:generate gotmpl --body=../../../internal/shared/counter/counter.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/otel/sdk/log/internal/counter\" }" --out=counter/counter.go
//go:generate gotmpl --body=../../../internal/shared/counter/counter_test.go.tmpl "--data={}" --out=counter/counter_test.go

//go:generate gotmpl --body=../../../internal/shared/x/x.go.tmpl "--data={ \"pkg\": \"go.opentelemetry.io/otel/sdk/log\" }" --out=x/x.go
//go:generate gotmpl --body=../../../internal/shared/x/x_test.go.tmpl "--data={}" --out=x/x_test.go
25 changes: 21 additions & 4 deletions sdk/log/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ package log // import "go.opentelemetry.io/otel/sdk/log"
import (
"context"
"sync"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/log/internal/counter"
"go.opentelemetry.io/otel/sdk/log/internal/observ"
)

// Compile-time check SimpleProcessor implements Processor.
Expand All @@ -17,8 +21,8 @@ var _ Processor = (*SimpleProcessor)(nil)
type SimpleProcessor struct {
mu sync.Mutex
exporter Exporter

noCmp [0]func() //nolint: unused // This is indeed used.
inst *observ.SLP
noCmp [0]func() //nolint: unused // This is indeed used.
}

// NewSimpleProcessor is a simple Processor adapter.
Expand All @@ -30,7 +34,15 @@ type SimpleProcessor struct {
// [NewBatchProcessor] instead. However, there may be exceptions where certain
// [Exporter] implementations perform better with this Processor.
func NewSimpleProcessor(exporter Exporter, _ ...SimpleProcessorOption) *SimpleProcessor {
return &SimpleProcessor{exporter: exporter}
slp := &SimpleProcessor{
exporter: exporter,
}
var err error
slp.inst, err = observ.NewSLP(counter.NextExporterID())
if err != nil {
otel.Handle(err)
}
return slp
}

var simpleProcRecordsPool = sync.Pool{
Expand All @@ -41,7 +53,7 @@ var simpleProcRecordsPool = sync.Pool{
}

// OnEmit batches provided log record.
func (s *SimpleProcessor) OnEmit(ctx context.Context, r *Record) error {
func (s *SimpleProcessor) OnEmit(ctx context.Context, r *Record) (err error) {
if s.exporter == nil {
return nil
}
Expand All @@ -55,6 +67,11 @@ func (s *SimpleProcessor) OnEmit(ctx context.Context, r *Record) error {
simpleProcRecordsPool.Put(records)
}()

if s.inst != nil {
defer func() {
s.inst.LogProcessed(ctx, err)
}()
}
return s.exporter.Export(ctx, *records)
}

Expand Down
151 changes: 151 additions & 0 deletions sdk/log/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ package log_test
import (
"context"
"io"
"strconv"
"strings"
"sync"
"testing"

"go.opentelemetry.io/otel/sdk/log/internal/counter"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/log"
"go.opentelemetry.io/otel/sdk/log/internal/observ"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/semconv/v1.37.0/otelconv"
)

type exporter struct {
Expand Down Expand Up @@ -138,3 +151,141 @@ func BenchmarkSimpleProcessorOnEmit(b *testing.B) {
_ = out
})
}

func TestSimpleLogProcessorObservability(t *testing.T) {
testcases := []struct {
name string
enabled bool
assertMetrics func(t *testing.T, rm metricdata.ResourceMetrics)
}{
{
name: "disabled",
enabled: false,
assertMetrics: func(t *testing.T, rm metricdata.ResourceMetrics) {
assert.Empty(t, rm.ScopeMetrics)
},
},
{
name: "enabled",
enabled: true,
assertMetrics: func(t *testing.T, rm metricdata.ResourceMetrics) {
assert.Len(t, rm.ScopeMetrics, 1)
sm := rm.ScopeMetrics[0]

p := otelconv.SDKProcessorLogProcessed{}

want := metricdata.ScopeMetrics{
Scope: instrumentation.Scope{
Name: observ.ScopeName,
Version: sdk.Version(),
SchemaURL: semconv.SchemaURL,
},
Metrics: []metricdata.Metrics{
{
Name: p.Name(),
Description: p.Description(),
Unit: p.Unit(),
Data: metricdata.Sum[int64]{
DataPoints: []metricdata.DataPoint[int64]{
{
Value: 1,
Attributes: attribute.NewSet(
observ.GetSLPComponentName(0),
semconv.OTelComponentTypeKey.String(
string(otelconv.ComponentTypeSimpleLogProcessor),
),
),
},
},
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
},
},
},
}

metricdatatest.AssertEqual(
t,
want,
sm,
metricdatatest.IgnoreExemplars(),
metricdatatest.IgnoreTimestamp(),
)
},
},
{
name: "Enable Exporter error",
enabled: true,
assertMetrics: func(t *testing.T, rm metricdata.ResourceMetrics) {
assert.Len(t, rm.ScopeMetrics, 1)
sm := rm.ScopeMetrics[0]
p := otelconv.SDKProcessorLogProcessed{}

want := metricdata.ScopeMetrics{
Scope: instrumentation.Scope{
Name: "go.opentelemetry.io/otel/sdk/log/internal/observ",
Version: sdk.Version(),
SchemaURL: semconv.SchemaURL,
},
Metrics: []metricdata.Metrics{
{
Name: p.Name(),
Description: p.Description(),
Unit: p.Unit(),
Data: metricdata.Sum[int64]{
DataPoints: []metricdata.DataPoint[int64]{
{
Value: 1,
Attributes: attribute.NewSet(
observ.GetSLPComponentName(0),
semconv.OTelComponentTypeKey.String(
string(otelconv.ComponentTypeSimpleLogProcessor),
),
),
},
},
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
},
},
},
}

metricdatatest.AssertEqual(
t,
want,
sm,
metricdatatest.IgnoreTimestamp(),
metricdatatest.IgnoreExemplars(),
)
},
},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
t.Setenv("OTEL_GO_X_OBSERVABILITY", strconv.FormatBool(tc.enabled))

original := otel.GetMeterProvider()
t.Cleanup(func() {
otel.SetMeterProvider(original)
})

r := metric.NewManualReader()
mp := metric.NewMeterProvider(metric.WithReader(r))
otel.SetMeterProvider(mp)

e := new(exporter)
slp := log.NewSimpleProcessor(e)
record := new(log.Record)
record.SetSeverityText("test")
err := slp.OnEmit(t.Context(), record)
require.NoError(t, err)

var rm metricdata.ResourceMetrics
require.NoError(t, r.Collect(t.Context(), &rm))
tc.assertMetrics(t, rm)
counter.SetExporterID(0)
})
}
}
Loading