Skip to content

Commit 96c5e4b

Browse files
authored
Add SpanProcessor example for Span annotation on start (open-telemetry#1733)
* Add SpanProcessor example for Span annotation on start * Remove New* func to make more concise * Add doc for AttrsFunc * Move overview comment to top * Update based on feedback * Remove AttrsFunc type * Use OnEnd to print instead of separate exporter * Move the tracer declaration
1 parent 543c814 commit 96c5e4b

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

Diff for: sdk/trace/span_processor_annotator_example_test.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package trace
16+
17+
import (
18+
"context"
19+
"fmt"
20+
21+
"go.opentelemetry.io/otel/attribute"
22+
)
23+
24+
/*
25+
Sometimes information about a runtime environment can change dynamically or be
26+
delayed from startup. Instead of continuously recreating and distributing a
27+
TracerProvider with an immutable Resource or delaying the startup of your
28+
application on a slow-loading piece of information, annotate the created spans
29+
dynamically using a SpanProcessor.
30+
*/
31+
32+
var (
33+
// owner represents the owner of the application. In this example it is
34+
// stored as a simple string, but in real-world use this may be the
35+
// response to an asynchronous request.
36+
owner = "unknown"
37+
ownerKey = attribute.Key("owner")
38+
)
39+
40+
// Annotator is a SpanProcessor that adds attributes to all started spans.
41+
type Annotator struct {
42+
// AttrsFunc is called when a span is started. The attributes it returns
43+
// are set on the Span being started.
44+
AttrsFunc func() []attribute.KeyValue
45+
}
46+
47+
func (a Annotator) OnStart(_ context.Context, s ReadWriteSpan) { s.SetAttributes(a.AttrsFunc()...) }
48+
func (a Annotator) Shutdown(context.Context) error { return nil }
49+
func (a Annotator) ForceFlush(context.Context) error { return nil }
50+
func (a Annotator) OnEnd(s ReadOnlySpan) {
51+
attr := s.Attributes()[0]
52+
fmt.Printf("%s: %s\n", attr.Key, attr.Value.AsString())
53+
}
54+
55+
func ExampleSpanProcessor_annotated() {
56+
a := Annotator{
57+
AttrsFunc: func() []attribute.KeyValue {
58+
return []attribute.KeyValue{ownerKey.String(owner)}
59+
},
60+
}
61+
tracer := NewTracerProvider(WithSpanProcessor(a)).Tracer("annotated")
62+
63+
// Simulate the situation where we want to annotate spans with an owner,
64+
// but at startup we do not now this information. Instead of waiting for
65+
// the owner to be known before starting and blocking here, start doing
66+
// work and update when the information becomes available.
67+
ctx := context.Background()
68+
_, s0 := tracer.Start(ctx, "span0")
69+
70+
// Simulate an asynchronous call to determine the owner succeeding. We now
71+
// know that the owner of this application has been determined to be
72+
// Alice. Make sure all subsequent spans are annotated appropriately.
73+
owner = "alice"
74+
75+
_, s1 := tracer.Start(ctx, "span1")
76+
s0.End()
77+
s1.End()
78+
79+
// Output:
80+
// owner: unknown
81+
// owner: alice
82+
}

Diff for: sdk/trace/span_processor_example_test.go renamed to sdk/trace/span_processor_filter_example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ type noopExporter struct{}
7979
func (noopExporter) ExportSpans(context.Context, []*SpanSnapshot) error { return nil }
8080
func (noopExporter) Shutdown(context.Context) error { return nil }
8181

82-
func ExampleSpanProcessor() {
82+
func ExampleSpanProcessor_filtered() {
8383
exportSP := NewSimpleSpanProcessor(noopExporter{})
8484

8585
// Build a SpanProcessor chain to filter out all spans from the pernicious

0 commit comments

Comments
 (0)