@@ -68,6 +68,8 @@ type tailSamplingSpanProcessor struct {
6868 setPolicyMux sync.Mutex
6969 pendingPolicy []PolicyCfg
7070 sampleOnFirstMatch bool
71+
72+ host component.Host
7173}
7274
7375type traceLimiter interface {
@@ -156,10 +158,7 @@ func newTracesProcessor(ctx context.Context, set processor.Settings, nextConsume
156158 }
157159
158160 if tsp .policies == nil {
159- err := tsp .loadSamplingPolicy (cfg .PolicyCfgs )
160- if err != nil {
161- return nil , err
162- }
161+ tsp .pendingPolicy = cfg .PolicyCfgs
163162 }
164163
165164 if tsp .decisionBatcher == nil {
@@ -217,22 +216,31 @@ func withRecordPolicy() Option {
217216 }
218217}
219218
220- func getPolicyEvaluator (settings component.TelemetrySettings , cfg * PolicyCfg ) (samplingpolicy.Evaluator , error ) {
219+ func getPolicyEvaluator (settings component.TelemetrySettings , cfg * PolicyCfg , policyExtensions map [ string ]samplingpolicy. Extension ) (samplingpolicy.Evaluator , error ) {
221220 switch cfg .Type {
222221 case Composite :
223- return getNewCompositePolicy (settings , & cfg .CompositeCfg )
222+ return getNewCompositePolicy (settings , & cfg .CompositeCfg , policyExtensions )
224223 case And :
225- return getNewAndPolicy (settings , & cfg .AndCfg )
224+ return getNewAndPolicy (settings , & cfg .AndCfg , policyExtensions )
226225 case Drop :
227- return getNewDropPolicy (settings , & cfg .DropCfg )
226+ return getNewDropPolicy (settings , & cfg .DropCfg , policyExtensions )
228227 default :
229- return getSharedPolicyEvaluator (settings , & cfg .sharedPolicyCfg )
228+ return getSharedPolicyEvaluator (settings , & cfg .sharedPolicyCfg , policyExtensions )
230229 }
231230}
232231
233- func getSharedPolicyEvaluator (settings component.TelemetrySettings , cfg * sharedPolicyCfg ) (samplingpolicy.Evaluator , error ) {
232+ func getSharedPolicyEvaluator (settings component.TelemetrySettings , cfg * sharedPolicyCfg , policyExtensions map [ string ]samplingpolicy. Extension ) (samplingpolicy.Evaluator , error ) {
234233 settings .Logger = settings .Logger .With (zap .Any ("policy" , cfg .Type ))
235234
235+ extension , ok := policyExtensions [string (cfg .Type )]
236+ if ok {
237+ evaluator , err := extension .NewEvaluator (cfg .ExtensionCfg )
238+ if err != nil {
239+ return nil , fmt .Errorf ("unable to load extension %s: %w" , string (cfg .Type ), err )
240+ }
241+ return evaluator , nil
242+ }
243+
236244 switch cfg .Type {
237245 case AlwaysSample :
238246 return sampling .NewAlwaysSample (settings ), nil
@@ -325,7 +333,7 @@ func (tsp *tailSamplingSpanProcessor) loadSamplingPolicy(cfgs []PolicyCfg) error
325333 }
326334 policyNames [cfg .Name ] = struct {}{}
327335
328- eval , err := getPolicyEvaluator (telemetrySettings , & cfg )
336+ eval , err := getPolicyEvaluator (telemetrySettings , & cfg , tsp . extensions () )
329337 if err != nil {
330338 return fmt .Errorf ("failed to create policy evaluator for %q: %w" , cfg .Name , err )
331339 }
@@ -364,14 +372,14 @@ func (tsp *tailSamplingSpanProcessor) SetSamplingPolicy(cfgs []PolicyCfg) {
364372 tsp .pendingPolicy = cfgs
365373}
366374
367- func (tsp * tailSamplingSpanProcessor ) loadPendingSamplingPolicy () {
375+ func (tsp * tailSamplingSpanProcessor ) loadPendingSamplingPolicy () error {
368376 tsp .setPolicyMux .Lock ()
369377 defer tsp .setPolicyMux .Unlock ()
370378
371379 // Nothing pending, do nothing.
372380 pLen := len (tsp .pendingPolicy )
373381 if pLen == 0 {
374- return
382+ return nil
375383 }
376384
377385 tsp .logger .Debug ("Loading pending sampling policy" , zap .Int ("pending.len" , pLen ))
@@ -381,17 +389,17 @@ func (tsp *tailSamplingSpanProcessor) loadPendingSamplingPolicy() {
381389 // Empty pending regardless of error. If policy is invalid, it will fail on
382390 // every tick, no need to do extra work and flood the log with errors.
383391 tsp .pendingPolicy = nil
384-
385- if err != nil {
386- tsp .logger .Error ("Failed to load pending sampling policy" , zap .Error (err ))
387- tsp .logger .Debug ("Continuing to use the previously loaded sampling policy" )
388- }
392+ return err
389393}
390394
391395func (tsp * tailSamplingSpanProcessor ) samplingPolicyOnTick () {
392396 tsp .logger .Debug ("Sampling Policy Evaluation ticked" )
393397
394- tsp .loadPendingSamplingPolicy ()
398+ err := tsp .loadPendingSamplingPolicy ()
399+ if err != nil {
400+ tsp .logger .Error ("Failed to load pending sampling policy" , zap .Error (err ))
401+ tsp .logger .Debug ("Continuing to use the previously loaded sampling policy" )
402+ }
395403
396404 ctx := context .Background ()
397405 metrics := newPolicyMetrics (len (tsp .policies ))
@@ -644,11 +652,35 @@ func (*tailSamplingSpanProcessor) Capabilities() consumer.Capabilities {
644652}
645653
646654// Start is invoked during service startup.
647- func (tsp * tailSamplingSpanProcessor ) Start (context.Context , component.Host ) error {
655+ func (tsp * tailSamplingSpanProcessor ) Start (ctx context.Context , host component.Host ) error {
656+ // We need to store the host before loading sampling policies in order to load any extensions.
657+ tsp .host = host
658+ if tsp .policies == nil {
659+ err := tsp .loadPendingSamplingPolicy ()
660+ if err != nil {
661+ tsp .logger .Error ("Failed to load initial sampling policy" , zap .Error (err ))
662+ return err
663+ }
664+ }
648665 tsp .policyTicker .Start (tsp .tickerFrequency )
649666 return nil
650667}
651668
669+ func (tsp * tailSamplingSpanProcessor ) extensions () map [string ]samplingpolicy.Extension {
670+ if tsp .host == nil {
671+ return nil
672+ }
673+ extensions := tsp .host .GetExtensions ()
674+ scoped := map [string ]samplingpolicy.Extension {}
675+ for id , ext := range extensions {
676+ evaluator , ok := ext .(samplingpolicy.Extension )
677+ if ok {
678+ scoped [id .String ()] = evaluator
679+ }
680+ }
681+ return scoped
682+ }
683+
652684// Shutdown is invoked during service shutdown.
653685func (tsp * tailSamplingSpanProcessor ) Shutdown (context.Context ) error {
654686 tsp .decisionBatcher .Stop ()
0 commit comments