Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ The next release will require at least [Go 1.24].
### Fixed

- Fix `go.opentelemetry.io/otel/exporters/prometheus` to deduplicate suffixes if already present in metric name when UTF8 is enabled. (#7088)
- Fix partial export count metric in `go.opentelemetry.io/otel/exporters/stdout/stdouttrace`. (#7199)

<!-- Released section -->
<!-- Don't change this section unless doing release -->
Expand Down
37 changes: 26 additions & 11 deletions exporters/stdout/stdouttrace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package stdouttrace // import "go.opentelemetry.io/otel/exporters/stdout/stdoutt
import (
"context"
"encoding/json"
"errors"
"fmt"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -95,22 +96,34 @@ func (e *Exporter) initSelfObservability() {

// ExportSpans writes spans in json format to stdout.
func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) (err error) {
var success int64
if e.selfObservabilityEnabled {
count := int64(len(spans))

e.spanInflightMetric.Add(context.Background(), count, e.selfObservabilityAttrs...)
defer func(starting time.Time) {
// additional attributes for self-observability,
// only spanExportedMetric and operationDurationMetric are supported
addAttrs := make([]attribute.KeyValue, len(e.selfObservabilityAttrs), len(e.selfObservabilityAttrs)+1)
copy(addAttrs, e.selfObservabilityAttrs)
e.spanInflightMetric.Add(context.Background(), -count, e.selfObservabilityAttrs...)

// Record the success and duration of the operation.
//
// Do not exclude 0 values, as they are valid and indicate no spans
// were exported which is meaningful for certain aggregations.
e.spanExportedMetric.Add(context.Background(), success, e.selfObservabilityAttrs...)

attr := e.selfObservabilityAttrs
if err != nil {
addAttrs = append(addAttrs, semconv.ErrorType(err))
// additional attributes for self-observability,
// only spanExportedMetric and operationDurationMetric are supported.
//
// TODO: use a pool to amortize allocations.
attr = make([]attribute.KeyValue, len(e.selfObservabilityAttrs), len(e.selfObservabilityAttrs)+1)
copy(attr, e.selfObservabilityAttrs)
attr = append(attr, semconv.ErrorType(err))

e.spanExportedMetric.Add(context.Background(), count-success, attr...)
}

e.spanInflightMetric.Add(context.Background(), -count, e.selfObservabilityAttrs...)
e.spanExportedMetric.Add(context.Background(), count, addAttrs...)
e.operationDurationMetric.Record(context.Background(), time.Since(starting).Seconds(), addAttrs...)
e.operationDurationMetric.Record(context.Background(), time.Since(starting).Seconds(), attr...)
}(time.Now())
}

Expand Down Expand Up @@ -145,11 +158,13 @@ func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan)
}

// Encode span stubs, one by one
if err := e.encoder.Encode(stub); err != nil {
return err
if e := e.encoder.Encode(stub); e != nil {
err = errors.Join(err, fmt.Errorf("failed to encode span %d: %w", i, e))
continue
}
success++
}
return nil
return err
}

// Shutdown is called to stop the exporter, it performs no action.
Expand Down
7 changes: 7 additions & 0 deletions exporters/stdout/stdouttrace/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,13 @@ func TestSelfObservability(t *testing.T) {
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
DataPoints: []metricdata.DataPoint[int64]{
{
Attributes: attribute.NewSet(
semconv.OTelComponentName("stdout_trace_exporter/1"),
semconv.OTelComponentTypeKey.String("stdout_trace_exporter"),
),
Value: 0,
},
{
Attributes: attribute.NewSet(
semconv.OTelComponentName("stdout_trace_exporter/1"),
Expand Down
Loading