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