24
24
import static java .util .concurrent .TimeUnit .MILLISECONDS ;
25
25
import static java .util .concurrent .TimeUnit .SECONDS ;
26
26
27
- import com .azure .monitor .opentelemetry .exporter .implementation .AiOperationNameSpanProcessor ;
27
+ import com .azure .monitor .opentelemetry .exporter .implementation .AiSemanticAttributes ;
28
+ import com .azure .monitor .opentelemetry .exporter .implementation .OperationNames ;
29
+ import com .azure .monitor .opentelemetry .exporter .implementation .SamplingScoreGeneratorV2 ;
28
30
import com .azure .monitor .opentelemetry .exporter .implementation .builders .AbstractTelemetryBuilder ;
29
31
import com .azure .monitor .opentelemetry .exporter .implementation .builders .AvailabilityTelemetryBuilder ;
30
32
import com .azure .monitor .opentelemetry .exporter .implementation .builders .EventTelemetryBuilder ;
40
42
import com .azure .monitor .opentelemetry .exporter .implementation .utils .FormattedDuration ;
41
43
import com .azure .monitor .opentelemetry .exporter .implementation .utils .FormattedTime ;
42
44
import com .azure .monitor .opentelemetry .exporter .implementation .utils .Strings ;
43
- import com .azure .monitor .opentelemetry .exporter .implementation .utils .TelemetryUtil ;
44
45
import com .microsoft .applicationinsights .agent .bootstrap .BytecodeUtil .BytecodeUtilDelegate ;
45
46
import com .microsoft .applicationinsights .agent .internal .legacyheaders .AiLegacyPropagator ;
46
- import com .microsoft .applicationinsights .agent .internal .sampling .SamplingScoreGeneratorV2 ;
47
47
import com .microsoft .applicationinsights .agent .internal .statsbeat .FeatureStatsbeat ;
48
48
import com .microsoft .applicationinsights .agent .internal .telemetry .TelemetryClient ;
49
49
import io .opentelemetry .api .trace .Span ;
50
50
import io .opentelemetry .api .trace .SpanContext ;
51
- import io .opentelemetry .context .Context ;
52
- import io .opentelemetry .instrumentation .api .instrumenter .LocalRootSpan ;
53
51
import io .opentelemetry .sdk .trace .ReadableSpan ;
54
52
import java .net .URI ;
55
53
import java .net .URL ;
@@ -472,78 +470,37 @@ public void logErrorOnce(Throwable t) {
472
470
private static void track (
473
471
AbstractTelemetryBuilder telemetryBuilder , Map <String , String > tags , boolean applySampling ) {
474
472
475
- String operationId = tags .get (ContextTagKeys .AI_OPERATION_ID .toString ());
473
+ String existingOperationId = tags .get (ContextTagKeys .AI_OPERATION_ID .toString ());
476
474
477
- SpanContext context = Span .current ().getSpanContext ();
478
- if (context .isValid ()) {
479
- String operationParentId = tags .get (ContextTagKeys .AI_OPERATION_PARENT_ID .toString ());
480
- String operationName = tags .get (ContextTagKeys .AI_OPERATION_NAME .toString ());
475
+ Span span = Span .current ();
476
+ SpanContext spanContext = span .getSpanContext ();
481
477
482
- trackInsideValidSpanContext (
483
- telemetryBuilder , operationId , operationParentId , operationName , context , applySampling );
484
- } else {
485
- trackAsStandalone (telemetryBuilder , operationId , applySampling );
486
- }
478
+ boolean isPartOfTheCurrentTrace =
479
+ spanContext .isValid ()
480
+ && (existingOperationId == null
481
+ || existingOperationId .equals (spanContext .getTraceId ()));
487
482
488
- if (featureStatsbeat != null ) {
489
- featureStatsbeat .track2xBridgeUsage ();
490
- }
491
- }
492
-
493
- private static void trackInsideValidSpanContext (
494
- AbstractTelemetryBuilder telemetryBuilder ,
495
- @ Nullable String operationId ,
496
- @ Nullable String operationParentId ,
497
- @ Nullable String operationName ,
498
- SpanContext spanContext ,
499
- boolean applySampling ) {
500
-
501
- if (operationId != null && !operationId .equals (spanContext .getTraceId ())) {
502
- trackAsStandalone (telemetryBuilder , operationId , applySampling );
483
+ if (isPartOfTheCurrentTrace && applySampling && !spanContext .isSampled ()) {
484
+ // no need to do anything more, sampled out
503
485
return ;
504
486
}
505
487
506
- if (! spanContext . isSampled () ) {
507
- // sampled out
508
- return ;
488
+ if (isPartOfTheCurrentTrace ) {
489
+ setOperationTagsFromTheCurrentSpan (
490
+ telemetryBuilder , tags , existingOperationId , spanContext , span ) ;
509
491
}
510
492
511
- telemetryBuilder .addTag (ContextTagKeys .AI_OPERATION_ID .toString (), spanContext .getTraceId ());
512
-
513
- if (operationParentId == null ) {
514
- telemetryBuilder .addTag (
515
- ContextTagKeys .AI_OPERATION_PARENT_ID .toString (), spanContext .getSpanId ());
516
- }
517
-
518
- if (operationName == null ) {
519
- Span localRootSpan = LocalRootSpan .fromContextOrNull (Context .current ());
520
- if (localRootSpan instanceof ReadableSpan ) {
521
- telemetryBuilder .addTag (
522
- ContextTagKeys .AI_OPERATION_NAME .toString (),
523
- AiOperationNameSpanProcessor .getOperationName ((ReadableSpan ) localRootSpan ));
524
- }
525
- }
526
-
527
- if (applySampling ) {
528
- float samplingPercentage =
529
- TelemetryUtil .getSamplingPercentage (
530
- spanContext .getTraceState (), BytecodeUtilImpl .samplingPercentage , false );
531
-
532
- if (samplingPercentage != 100 ) {
533
- telemetryBuilder .setSampleRate (samplingPercentage );
493
+ if (isPartOfTheCurrentTrace && applySampling && span instanceof ReadableSpan ) {
494
+ Long itemCount = ((ReadableSpan ) span ).getAttribute (AiSemanticAttributes .ITEM_COUNT );
495
+ if (itemCount != null && itemCount != 1 ) {
496
+ telemetryBuilder .setSampleRate (100.0f / itemCount );
534
497
}
535
498
}
536
- // this is not null because sdk instrumentation is not added until TelemetryClient.setActive()
537
- // is called
538
- TelemetryClient .getActive ().trackAsync (telemetryBuilder .build ());
539
- }
540
499
541
- private static void trackAsStandalone (
542
- AbstractTelemetryBuilder telemetryBuilder , String operationId , boolean applySampling ) {
543
- if (applySampling ) {
544
- // sampling is done using the configured sampling percentage
500
+ if (!isPartOfTheCurrentTrace && applySampling ) {
501
+ // standalone sampling is done using the configured sampling percentage
545
502
float samplingPercentage = BytecodeUtilImpl .samplingPercentage ;
546
- if (!sample (operationId , samplingPercentage )) {
503
+ if (!sample (existingOperationId , samplingPercentage )) {
547
504
logger .debug ("Item {} sampled out" , telemetryBuilder .getClass ().getSimpleName ());
548
505
// sampled out
549
506
return ;
@@ -558,6 +515,33 @@ private static void trackAsStandalone(
558
515
// this is not null because sdk instrumentation is not added until TelemetryClient.setActive()
559
516
// is called
560
517
TelemetryClient .getActive ().trackAsync (telemetryBuilder .build ());
518
+
519
+ if (featureStatsbeat != null ) {
520
+ featureStatsbeat .track2xBridgeUsage ();
521
+ }
522
+ }
523
+
524
+ private static void setOperationTagsFromTheCurrentSpan (
525
+ AbstractTelemetryBuilder telemetryBuilder ,
526
+ Map <String , String > tags ,
527
+ String existingOperationId ,
528
+ SpanContext spanContext ,
529
+ Span span ) {
530
+
531
+ if (existingOperationId == null ) {
532
+ telemetryBuilder .addTag (ContextTagKeys .AI_OPERATION_ID .toString (), spanContext .getTraceId ());
533
+ }
534
+ String existingOperationParentId = tags .get (ContextTagKeys .AI_OPERATION_PARENT_ID .toString ());
535
+ if (existingOperationParentId == null ) {
536
+ telemetryBuilder .addTag (
537
+ ContextTagKeys .AI_OPERATION_PARENT_ID .toString (), spanContext .getSpanId ());
538
+ }
539
+ String existingOperationName = tags .get (ContextTagKeys .AI_OPERATION_NAME .toString ());
540
+ if (existingOperationName == null && span instanceof ReadableSpan ) {
541
+ telemetryBuilder .addTag (
542
+ ContextTagKeys .AI_OPERATION_NAME .toString (),
543
+ OperationNames .getOperationName ((ReadableSpan ) span ));
544
+ }
561
545
}
562
546
563
547
private static boolean sample (String operationId , double samplingPercentage ) {
0 commit comments