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 "time" 20 21 "go.opentelemetry.io/otel/sdk/export/trace/tracetest" 22) 23 24// DurationFilter is a SpanProcessor that filters spans that have lifetimes 25// outside of a defined range. 26type DurationFilter struct { 27 // Next is the next SpanProcessor in the chain. 28 Next SpanProcessor 29 30 // Min is the duration under which spans are dropped. 31 Min time.Duration 32 // Max is the duration over which spans are dropped. 33 Max time.Duration 34} 35 36func (f DurationFilter) OnStart(parent context.Context, s ReadWriteSpan) { 37 f.Next.OnStart(parent, s) 38} 39func (f DurationFilter) Shutdown(ctx context.Context) error { return f.Next.Shutdown(ctx) } 40func (f DurationFilter) ForceFlush() { f.Next.ForceFlush() } 41func (f DurationFilter) OnEnd(s ReadOnlySpan) { 42 if f.Min > 0 && s.EndTime().Sub(s.StartTime()) < f.Min { 43 // Drop short lived spans. 44 return 45 } 46 if f.Max > 0 && s.EndTime().Sub(s.StartTime()) > f.Max { 47 // Drop long lived spans. 48 return 49 } 50 f.Next.OnEnd(s) 51} 52 53// InstrumentationBlacklist is a SpanProcessor that drops all spans from 54// certain instrumentation. 55type InstrumentationBlacklist struct { 56 // Next is the next SpanProcessor in the chain. 57 Next SpanProcessor 58 59 // Blacklist is the set of instrumentation names for which spans will be 60 // dropped. 61 Blacklist map[string]bool 62} 63 64func (f InstrumentationBlacklist) OnStart(parent context.Context, s ReadWriteSpan) { 65 f.Next.OnStart(parent, s) 66} 67func (f InstrumentationBlacklist) Shutdown(ctx context.Context) error { return f.Next.Shutdown(ctx) } 68func (f InstrumentationBlacklist) ForceFlush() { f.Next.ForceFlush() } 69func (f InstrumentationBlacklist) OnEnd(s ReadOnlySpan) { 70 if f.Blacklist != nil && f.Blacklist[s.InstrumentationLibrary().Name] { 71 // Drop spans from this instrumentation 72 return 73 } 74 f.Next.OnEnd(s) 75} 76 77func ExampleSpanProcessor() { 78 exportSP := NewSimpleSpanProcessor(tracetest.NewNoopExporter()) 79 80 // Build a SpanProcessor chain to filter out all spans from the pernicious 81 // "naughty-instrumentation" dependency and only allow spans shorter than 82 // an minute and longer than a second to be exported with the exportSP. 83 filter := DurationFilter{ 84 Next: InstrumentationBlacklist{ 85 Next: exportSP, 86 Blacklist: map[string]bool{ 87 "naughty-instrumentation": true, 88 }, 89 }, 90 Min: time.Second, 91 Max: time.Minute, 92 } 93 94 _ = NewTracerProvider(WithSpanProcessor(filter)) 95 // ... 96} 97