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 15package trace 16 17import ( 18 "context" 19 "fmt" 20 21 "go.opentelemetry.io/otel/attribute" 22) 23 24/* 25Sometimes information about a runtime environment can change dynamically or be 26delayed from startup. Instead of continuously recreating and distributing a 27TracerProvider with an immutable Resource or delaying the startup of your 28application on a slow-loading piece of information, annotate the created spans 29dynamically using a SpanProcessor. 30*/ 31 32var ( 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. 41type 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 47func (a Annotator) OnStart(_ context.Context, s ReadWriteSpan) { s.SetAttributes(a.AttrsFunc()...) } 48func (a Annotator) Shutdown(context.Context) error { return nil } 49func (a Annotator) ForceFlush(context.Context) error { return nil } 50func (a Annotator) OnEnd(s ReadOnlySpan) { 51 attr := s.Attributes()[0] 52 fmt.Printf("%s: %s\n", attr.Key, attr.Value.AsString()) 53} 54 55func 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} 83