Skip to content

Commit e72bf43

Browse files
committed
Bind stdouttrace self-observability inst
1 parent 3f1aae2 commit e72bf43

File tree

3 files changed

+47
-78
lines changed

3 files changed

+47
-78
lines changed

exporters/stdout/stdouttrace/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ replace (
88
)
99

1010
require (
11+
github.com/MrAlias/bind v0.1.1
1112
github.com/stretchr/testify v1.11.0
1213
go.opentelemetry.io/otel v1.37.0
1314
go.opentelemetry.io/otel/metric v1.37.0

exporters/stdout/stdouttrace/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/MrAlias/bind v0.1.1 h1:y7FRVkD4HK3ut0eJ768ZQsqBUUgD7+/oEwVYjrULgO8=
2+
github.com/MrAlias/bind v0.1.1/go.mod h1:5B4HdQ8kUm9kZ4pVdE7a/HJAPzPz6CWKh7Hd40CYWZw=
13
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
24
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
35
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=

exporters/stdout/stdouttrace/trace.go

Lines changed: 44 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"sync"
1212
"time"
1313

14+
"github.com/MrAlias/bind"
15+
1416
"go.opentelemetry.io/otel"
1517
"go.opentelemetry.io/otel/attribute"
1618
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace/internal/counter"
@@ -51,12 +53,10 @@ func New(options ...Option) (*Exporter, error) {
5153
}
5254

5355
exporter.selfObservabilityEnabled = true
54-
exporter.selfObservabilityAttrs = []attribute.KeyValue{
55-
semconv.OTelComponentName(fmt.Sprintf("%s/%d", otelComponentType, counter.NextExporterID())),
56-
semconv.OTelComponentTypeKey.String(otelComponentType),
57-
}
58-
s := attribute.NewSet(exporter.selfObservabilityAttrs...)
59-
exporter.selfObservabilitySetOpt = metric.WithAttributeSet(s)
56+
57+
name := fmt.Sprintf("%s/%d", otelComponentType, counter.NextExporterID())
58+
cmpnt := semconv.OTelComponentName(name)
59+
cmpntT := semconv.OTelComponentTypeKey.String(otelComponentType)
6060

6161
mp := otel.GetMeterProvider()
6262
m := mp.Meter(
@@ -65,18 +65,35 @@ func New(options ...Option) (*Exporter, error) {
6565
metric.WithSchemaURL(semconv.SchemaURL),
6666
)
6767

68-
var err, e error
69-
if exporter.spanInflightMetric, e = otelconv.NewSDKExporterSpanInflight(m); e != nil {
68+
var err error
69+
if i, e := otelconv.NewSDKExporterSpanInflight(m); e != nil {
7070
e = fmt.Errorf("failed to create span inflight metric: %w", e)
7171
err = errors.Join(err, e)
72+
} else {
73+
bound := bind.Int64UpDownCounter(i.Inst(), cmpnt, cmpntT)
74+
exporter.spanInflightMetric = otelconv.SDKExporterSpanInflight{
75+
Int64UpDownCounter: bound,
76+
}
7277
}
73-
if exporter.spanExportedMetric, e = otelconv.NewSDKExporterSpanExported(m); e != nil {
78+
79+
if i, e := otelconv.NewSDKExporterSpanExported(m); e != nil {
7480
e = fmt.Errorf("failed to create span exported metric: %w", e)
7581
err = errors.Join(err, e)
82+
} else {
83+
bound := bind.Int64Counter(i.Inst(), cmpnt, cmpntT)
84+
exporter.spanExportedMetric = otelconv.SDKExporterSpanExported{
85+
Int64Counter: bound,
86+
}
7687
}
77-
if exporter.operationDurationMetric, e = otelconv.NewSDKExporterOperationDuration(m); e != nil {
88+
89+
if i, e := otelconv.NewSDKExporterOperationDuration(m); e != nil {
7890
e = fmt.Errorf("failed to create operation duration metric: %w", e)
7991
err = errors.Join(err, e)
92+
} else {
93+
bound := bind.Float64Histogram(i.Inst(), cmpnt, cmpntT)
94+
exporter.operationDurationMetric = otelconv.SDKExporterOperationDuration{
95+
Float64Histogram: bound,
96+
}
8097
}
8198

8299
return exporter, err
@@ -92,67 +109,39 @@ type Exporter struct {
92109
stopped bool
93110

94111
selfObservabilityEnabled bool
95-
selfObservabilityAttrs []attribute.KeyValue // selfObservability common attributes
96-
selfObservabilitySetOpt metric.MeasurementOption
97112
spanInflightMetric otelconv.SDKExporterSpanInflight
98113
spanExportedMetric otelconv.SDKExporterSpanExported
99114
operationDurationMetric otelconv.SDKExporterOperationDuration
100115
}
101116

102-
var (
103-
measureAttrsPool = sync.Pool{
104-
New: func() any {
105-
// "component.name" + "component.type" + "error.type"
106-
const n = 1 + 1 + 1
107-
s := make([]attribute.KeyValue, 0, n)
108-
// Return a pointer to a slice instead of a slice itself
109-
// to avoid allocations on every call.
110-
return &s
111-
},
112-
}
113-
114-
addOptPool = &sync.Pool{
115-
New: func() any {
116-
const n = 1 // WithAttributeSet
117-
o := make([]metric.AddOption, 0, n)
118-
return &o
119-
},
120-
}
121-
122-
recordOptPool = &sync.Pool{
123-
New: func() any {
124-
const n = 1 // WithAttributeSet
125-
o := make([]metric.RecordOption, 0, n)
126-
return &o
127-
},
128-
}
129-
)
117+
var measureAttrsPool = sync.Pool{
118+
New: func() any {
119+
// "error.type"
120+
const n = 1
121+
s := make([]attribute.KeyValue, 0, n)
122+
// Return a pointer to a slice instead of a slice itself
123+
// to avoid allocations on every call.
124+
return &s
125+
},
126+
}
130127

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

137-
addOpt := addOptPool.Get().(*[]metric.AddOption)
138-
defer func() {
139-
*addOpt = (*addOpt)[:0]
140-
addOptPool.Put(addOpt)
141-
}()
142-
143-
*addOpt = append(*addOpt, e.selfObservabilitySetOpt)
144-
145-
e.spanInflightMetric.Inst().Add(ctx, count, *addOpt...)
134+
e.spanInflightMetric.Add(ctx, count)
146135
defer func(starting time.Time) {
147-
e.spanInflightMetric.Inst().Add(ctx, -count, *addOpt...)
136+
e.spanInflightMetric.Add(ctx, -count)
148137

149138
// Record the success and duration of the operation.
150139
//
151140
// Do not exclude 0 values, as they are valid and indicate no spans
152141
// were exported which is meaningful for certain aggregations.
153-
e.spanExportedMetric.Inst().Add(ctx, success, *addOpt...)
142+
e.spanExportedMetric.Add(ctx, success)
154143

155-
mOpt := e.selfObservabilitySetOpt
144+
set := *attribute.EmptySet()
156145
if err != nil {
157146
// additional attributes for self-observability,
158147
// only spanExportedMetric and operationDurationMetric are supported.
@@ -161,36 +150,13 @@ func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan)
161150
*attrs = (*attrs)[:0] // reset the slice for reuse
162151
measureAttrsPool.Put(attrs)
163152
}()
164-
*attrs = append(*attrs, e.selfObservabilityAttrs...)
165153
*attrs = append(*attrs, semconv.ErrorType(err))
154+
set = attribute.NewSet(*attrs...)
166155

167-
// Do not inefficiently make a copy of attrs by using
168-
// WithAttributes instead of WithAttributeSet.
169-
set := attribute.NewSet(*attrs...)
170-
mOpt = metric.WithAttributeSet(set)
171-
172-
// Reset addOpt with new attribute set.
173-
*addOpt = append((*addOpt)[:0], mOpt)
174-
175-
e.spanExportedMetric.Inst().Add(
176-
ctx,
177-
count-success,
178-
*addOpt...,
179-
)
156+
e.spanExportedMetric.AddSet(ctx, count-success, set)
180157
}
181158

182-
recordOpt := recordOptPool.Get().(*[]metric.RecordOption)
183-
defer func() {
184-
*recordOpt = (*recordOpt)[:0]
185-
recordOptPool.Put(recordOpt)
186-
}()
187-
188-
*recordOpt = append(*recordOpt, mOpt)
189-
e.operationDurationMetric.Inst().Record(
190-
ctx,
191-
time.Since(starting).Seconds(),
192-
*recordOpt...,
193-
)
159+
e.operationDurationMetric.RecordSet(ctx, time.Since(starting).Seconds(), set)
194160
}(time.Now())
195161
}
196162

0 commit comments

Comments
 (0)