1919import static com .google .common .base .Preconditions .checkNotNull ;
2020import static io .grpc .opentelemetry .internal .OpenTelemetryConstants .BACKEND_SERVICE_KEY ;
2121import static io .grpc .opentelemetry .internal .OpenTelemetryConstants .BAGGAGE_KEY ;
22+ import static io .grpc .opentelemetry .internal .OpenTelemetryConstants .CUSTOM_LABEL_KEY ;
2223import static io .grpc .opentelemetry .internal .OpenTelemetryConstants .LOCALITY_KEY ;
2324import static io .grpc .opentelemetry .internal .OpenTelemetryConstants .METHOD_KEY ;
2425import static io .grpc .opentelemetry .internal .OpenTelemetryConstants .STATUS_KEY ;
3940import io .grpc .Deadline ;
4041import io .grpc .ForwardingClientCall .SimpleForwardingClientCall ;
4142import io .grpc .ForwardingClientCallListener .SimpleForwardingClientCallListener ;
43+ import io .grpc .Grpc ;
4244import io .grpc .Metadata ;
4345import io .grpc .MethodDescriptor ;
4446import io .grpc .ServerStreamTracer ;
@@ -99,6 +101,7 @@ final class OpenTelemetryMetricsModule {
99101 private final Supplier <Stopwatch > stopwatchSupplier ;
100102 private final boolean localityEnabled ;
101103 private final boolean backendServiceEnabled ;
104+ private final boolean customLabelEnabled ;
102105 private final ImmutableList <OpenTelemetryPlugin > plugins ;
103106 @ Nullable
104107 private final TargetFilter targetAttributeFilter ;
@@ -117,6 +120,7 @@ final class OpenTelemetryMetricsModule {
117120 this .stopwatchSupplier = checkNotNull (stopwatchSupplier , "stopwatchSupplier" );
118121 this .localityEnabled = optionalLabels .contains (LOCALITY_KEY .getKey ());
119122 this .backendServiceEnabled = optionalLabels .contains (BACKEND_SERVICE_KEY .getKey ());
123+ this .customLabelEnabled = optionalLabels .contains (CUSTOM_LABEL_KEY .getKey ());
120124 this .plugins = ImmutableList .copyOf (plugins );
121125 this .targetAttributeFilter = targetAttributeFilter ;
122126 }
@@ -277,7 +281,7 @@ public void streamClosed(Status status) {
277281 statusCode = Code .DEADLINE_EXCEEDED ;
278282 }
279283 }
280- attemptsState .attemptEnded ();
284+ attemptsState .attemptEnded (info . getCallOptions () );
281285 recordFinishedAttempt ();
282286 }
283287
@@ -301,6 +305,10 @@ void recordFinishedAttempt() {
301305 }
302306 builder .put (BACKEND_SERVICE_KEY , savedBackendService );
303307 }
308+ if (module .customLabelEnabled ) {
309+ builder .put (
310+ CUSTOM_LABEL_KEY , info .getCallOptions ().getOption (Grpc .CALL_OPTION_CUSTOM_LABEL ));
311+ }
304312 for (OpenTelemetryPlugin .ClientStreamPlugin plugin : streamPlugins ) {
305313 plugin .addLabels (builder );
306314 }
@@ -346,6 +354,7 @@ static final class CallAttemptsTracerFactory extends ClientStreamTracer.Factory
346354 CallAttemptsTracerFactory (
347355 OpenTelemetryMetricsModule module ,
348356 String target ,
357+ CallOptions callOptions ,
349358 String fullMethodName ,
350359 List <OpenTelemetryPlugin .ClientCallPlugin > callPlugins ) {
351360 this .module = checkNotNull (module , "module" );
@@ -355,9 +364,14 @@ static final class CallAttemptsTracerFactory extends ClientStreamTracer.Factory
355364 this .attemptDelayStopwatch = module .stopwatchSupplier .get ();
356365 this .callStopWatch = module .stopwatchSupplier .get ().start ();
357366
358- io .opentelemetry .api .common .Attributes attribute = io .opentelemetry .api .common .Attributes .of (
359- METHOD_KEY , fullMethodName ,
360- TARGET_KEY , target );
367+ AttributesBuilder builder = io .opentelemetry .api .common .Attributes .builder ()
368+ .put (METHOD_KEY , fullMethodName )
369+ .put (TARGET_KEY , target );
370+ if (module .customLabelEnabled ) {
371+ builder .put (
372+ CUSTOM_LABEL_KEY , callOptions .getOption (Grpc .CALL_OPTION_CUSTOM_LABEL ));
373+ }
374+ io .opentelemetry .api .common .Attributes attribute = builder .build ();
361375
362376 // Record here in case mewClientStreamTracer() would never be called.
363377 if (module .resource .clientAttemptCountCounter () != null ) {
@@ -381,9 +395,14 @@ public ClientStreamTracer newClientStreamTracer(StreamInfo info, Metadata metada
381395 // CallAttemptsTracerFactory constructor. attemptsPerCall will be non-zero after the first
382396 // attempt, as first attempt cannot be a transparent retry.
383397 if (attemptsPerCall .get () > 0 ) {
384- io .opentelemetry .api .common .Attributes attribute =
385- io .opentelemetry .api .common .Attributes .of (METHOD_KEY , fullMethodName ,
386- TARGET_KEY , target );
398+ AttributesBuilder builder = io .opentelemetry .api .common .Attributes .builder ()
399+ .put (METHOD_KEY , fullMethodName )
400+ .put (TARGET_KEY , target );
401+ if (module .customLabelEnabled ) {
402+ builder .put (
403+ CUSTOM_LABEL_KEY , info .getCallOptions ().getOption (Grpc .CALL_OPTION_CUSTOM_LABEL ));
404+ }
405+ io .opentelemetry .api .common .Attributes attribute = builder .build ();
387406 if (module .resource .clientAttemptCountCounter () != null ) {
388407 module .resource .clientAttemptCountCounter ().add (1 , attribute );
389408 }
@@ -411,7 +430,7 @@ private ClientTracer newClientTracer(StreamInfo info) {
411430 }
412431
413432 // Called whenever each attempt is ended.
414- void attemptEnded () {
433+ void attemptEnded (CallOptions callOptions ) {
415434 boolean shouldRecordFinishedCall = false ;
416435 synchronized (lock ) {
417436 if (--activeStreams == 0 ) {
@@ -423,11 +442,11 @@ void attemptEnded() {
423442 }
424443 }
425444 if (shouldRecordFinishedCall ) {
426- recordFinishedCall ();
445+ recordFinishedCall (callOptions );
427446 }
428447 }
429448
430- void callEnded (Status status ) {
449+ void callEnded (Status status , CallOptions callOptions ) {
431450 callStopWatch .stop ();
432451 this .status = status ;
433452 boolean shouldRecordFinishedCall = false ;
@@ -443,11 +462,11 @@ void callEnded(Status status) {
443462 }
444463 }
445464 if (shouldRecordFinishedCall ) {
446- recordFinishedCall ();
465+ recordFinishedCall (callOptions );
447466 }
448467 }
449468
450- void recordFinishedCall () {
469+ void recordFinishedCall (CallOptions callOptions ) {
451470 Context otelContext = otelContextWithBaggage ();
452471 if (attemptsPerCall .get () == 0 ) {
453472 ClientTracer tracer = newClientTracer (null );
@@ -458,11 +477,13 @@ void recordFinishedCall() {
458477 callLatencyNanos = callStopWatch .elapsed (TimeUnit .NANOSECONDS );
459478
460479 // Base attributes
461- io .opentelemetry .api .common .Attributes baseAttributes =
462- io .opentelemetry .api .common .Attributes .of (
463- METHOD_KEY , fullMethodName ,
464- TARGET_KEY , target
465- );
480+ AttributesBuilder builder = io .opentelemetry .api .common .Attributes .builder ()
481+ .put (METHOD_KEY , fullMethodName )
482+ .put (TARGET_KEY , target );
483+ if (module .customLabelEnabled ) {
484+ builder .put (CUSTOM_LABEL_KEY , callOptions .getOption (Grpc .CALL_OPTION_CUSTOM_LABEL ));
485+ }
486+ io .opentelemetry .api .common .Attributes baseAttributes = builder .build ();
466487
467488 // Duration
468489 if (module .resource .clientCallDurationCounter () != null ) {
@@ -688,11 +709,12 @@ public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
688709 callOptions = plugin .filterCallOptions (callOptions );
689710 }
690711 }
712+ final CallOptions finalCallOptions = callOptions ;
691713 // Only record method name as an attribute if isSampledToLocalTracing is set to true,
692714 // which is true for all generated methods. Otherwise, programatically
693715 // created methods result in high cardinality metrics.
694716 final CallAttemptsTracerFactory tracerFactory = new CallAttemptsTracerFactory (
695- OpenTelemetryMetricsModule .this , target ,
717+ OpenTelemetryMetricsModule .this , target , callOptions ,
696718 recordMethodName (method .getFullMethodName (), method .isSampledToLocalTracing ()),
697719 callPlugins );
698720 ClientCall <ReqT , RespT > call =
@@ -707,7 +729,7 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
707729 new SimpleForwardingClientCallListener <RespT >(responseListener ) {
708730 @ Override
709731 public void onClose (Status status , Metadata trailers ) {
710- tracerFactory .callEnded (status );
732+ tracerFactory .callEnded (status , finalCallOptions );
711733 super .onClose (status , trailers );
712734 }
713735 },
0 commit comments