@@ -54,32 +54,9 @@ func (tr *tracer) Start(
54
54
s := tr .newSpan (ctx , name , & config )
55
55
newCtx := trace .ContextWithSpan (ctx , s )
56
56
if tr .selfObservabilityEnabled {
57
- // Check if the span has a parent span and set the origin attribute accordingly.
58
- var attrParentOrigin attribute.KeyValue
59
- if psc := trace .SpanContextFromContext (ctx ); psc .IsValid () {
60
- if psc .IsRemote () {
61
- attrParentOrigin = tr .spanStartedMetric .AttrSpanParentOrigin (otelconv .SpanParentOriginRemote )
62
- } else {
63
- attrParentOrigin = tr .spanStartedMetric .AttrSpanParentOrigin (otelconv .SpanParentOriginLocal )
64
- }
65
- } else {
66
- attrParentOrigin = tr .spanStartedMetric .AttrSpanParentOrigin (otelconv .SpanParentOriginNone )
67
- }
68
-
69
- // Determine the sampling result and create the corresponding attribute.
70
- var attrSamplingResult attribute.KeyValue
71
- switch {
72
- case s .SpanContext ().IsSampled () && s .IsRecording ():
73
- attrSamplingResult = tr .spanStartedMetric .AttrSpanSamplingResult (
74
- otelconv .SpanSamplingResultRecordAndSample ,
75
- )
76
- case s .IsRecording ():
77
- attrSamplingResult = tr .spanStartedMetric .AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordOnly )
78
- default :
79
- attrSamplingResult = tr .spanStartedMetric .AttrSpanSamplingResult (otelconv .SpanSamplingResultDrop )
80
- }
81
-
82
- tr .spanStartedMetric .Add (newCtx , 1 , attrParentOrigin , attrSamplingResult )
57
+ psc := trace .SpanContextFromContext (ctx )
58
+ set := spanStartedSet (psc , s )
59
+ tr .spanStartedMetric .AddSet (newCtx , 1 , set )
83
60
}
84
61
85
62
if rw , ok := s .(ReadWriteSpan ); ok && s .IsRecording () {
@@ -192,20 +169,11 @@ func (tr *tracer) newRecordingSpan(
192
169
s .SetAttributes (config .Attributes ()... )
193
170
194
171
if tr .selfObservabilityEnabled {
195
- // Determine the sampling result and create the corresponding attribute.
196
- var attrSamplingResult attribute.KeyValue
197
- if s .spanContext .IsSampled () {
198
- attrSamplingResult = tr .spanLiveMetric .AttrSpanSamplingResult (
199
- otelconv .SpanSamplingResultRecordAndSample ,
200
- )
201
- } else {
202
- attrSamplingResult = tr .spanLiveMetric .AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordOnly )
203
- }
204
-
205
172
// Propagate any existing values from the context with the new span to
206
173
// the measurement context.
207
174
ctx = trace .ContextWithSpan (ctx , s )
208
- tr .spanLiveMetric .Add (ctx , 1 , attrSamplingResult )
175
+ set := spanLiveSet (s .spanContext .IsSampled ())
176
+ tr .spanLiveMetric .AddSet (ctx , 1 , set )
209
177
}
210
178
211
179
return s
@@ -215,3 +183,112 @@ func (tr *tracer) newRecordingSpan(
215
183
func (tr * tracer ) newNonRecordingSpan (sc trace.SpanContext ) nonRecordingSpan {
216
184
return nonRecordingSpan {tracer : tr , sc : sc }
217
185
}
186
+
187
+ type parentState int
188
+
189
+ const (
190
+ parentStateNoParent parentState = iota
191
+ parentStateLocalParent
192
+ parentStateRemoteParent
193
+ )
194
+
195
+ type samplingState int
196
+
197
+ const (
198
+ samplingStateDrop samplingState = iota
199
+ samplingStateRecordOnly
200
+ samplingStateRecordAndSample
201
+ )
202
+
203
+ type spanStartedSetKey struct {
204
+ parent parentState
205
+ sampling samplingState
206
+ }
207
+
208
+ var spanStartedSetCache = map [spanStartedSetKey ]attribute.Set {
209
+ {parentStateNoParent , samplingStateDrop }: attribute .NewSet (
210
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginNone ),
211
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultDrop ),
212
+ ),
213
+ {parentStateLocalParent , samplingStateDrop }: attribute .NewSet (
214
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginLocal ),
215
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultDrop ),
216
+ ),
217
+ {parentStateRemoteParent , samplingStateDrop }: attribute .NewSet (
218
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginRemote ),
219
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultDrop ),
220
+ ),
221
+
222
+ {parentStateNoParent , samplingStateRecordOnly }: attribute .NewSet (
223
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginNone ),
224
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordOnly ),
225
+ ),
226
+ {parentStateLocalParent , samplingStateRecordOnly }: attribute .NewSet (
227
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginLocal ),
228
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordOnly ),
229
+ ),
230
+ {parentStateRemoteParent , samplingStateRecordOnly }: attribute .NewSet (
231
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginRemote ),
232
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordOnly ),
233
+ ),
234
+
235
+ {parentStateNoParent , samplingStateRecordAndSample }: attribute .NewSet (
236
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginNone ),
237
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordAndSample ),
238
+ ),
239
+ {parentStateLocalParent , samplingStateRecordAndSample }: attribute .NewSet (
240
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginLocal ),
241
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordAndSample ),
242
+ ),
243
+ {parentStateRemoteParent , samplingStateRecordAndSample }: attribute .NewSet (
244
+ otelconv.SDKSpanStarted {}.AttrSpanParentOrigin (otelconv .SpanParentOriginRemote ),
245
+ otelconv.SDKSpanStarted {}.AttrSpanSamplingResult (otelconv .SpanSamplingResultRecordAndSample ),
246
+ ),
247
+ }
248
+
249
+ func spanStartedSet (psc trace.SpanContext , span trace.Span ) attribute.Set {
250
+ key := spanStartedSetKey {
251
+ parent : parentStateNoParent ,
252
+ sampling : samplingStateDrop ,
253
+ }
254
+
255
+ if psc .IsValid () {
256
+ if psc .IsRemote () {
257
+ key .parent = parentStateRemoteParent
258
+ } else {
259
+ key .parent = parentStateLocalParent
260
+ }
261
+ }
262
+
263
+ if span .IsRecording () {
264
+ if span .SpanContext ().IsSampled () {
265
+ key .sampling = samplingStateRecordAndSample
266
+ } else {
267
+ key .sampling = samplingStateRecordOnly
268
+ }
269
+ }
270
+
271
+ return spanStartedSetCache [key ]
272
+ }
273
+
274
+ type spanLiveSetKey struct {
275
+ sampled bool
276
+ }
277
+
278
+ var spanLiveSetCache = map [spanLiveSetKey ]attribute.Set {
279
+ {true }: attribute .NewSet (
280
+ otelconv.SDKSpanLive {}.AttrSpanSamplingResult (
281
+ otelconv .SpanSamplingResultRecordAndSample ,
282
+ ),
283
+ ),
284
+ {false }: attribute .NewSet (
285
+ otelconv.SDKSpanLive {}.AttrSpanSamplingResult (
286
+ otelconv .SpanSamplingResultRecordOnly ,
287
+ ),
288
+ ),
289
+ }
290
+
291
+ func spanLiveSet (sampled bool ) attribute.Set {
292
+ key := spanLiveSetKey {sampled : sampled }
293
+ return spanLiveSetCache [key ]
294
+ }
0 commit comments