Skip to content

Instantly share code, notes, and snippets.

@lmolkova
Last active November 30, 2022 03:29
Show Gist options
  • Save lmolkova/bfe1694da8e2257835d849900394f466 to your computer and use it in GitHub Desktop.
Save lmolkova/bfe1694da8e2257835d849900394f466 to your computer and use it in GitHub Desktop.

Azure SDK for Java: tracing changes

Motivation

  • Improve API usability for SB/EH
  • Allow explicit configuration
  • GA tracing plugin

Usage scenarios

End-users

Absolution majority of users will use no code configuration -javaagent:\path\to\opentelemetry-javaagent.jar or applicationinsights-agent.jar

Some of these users might want to configure tracing:

  • control the schema of emitted telemetry (in future):

    TracingOptions tracingOptions = new OpenTelemetryTracingOptions()
        .setSchemaVersion(OpenTelemetrySchemaVersion.V1_12_0);
    
    SecretClient secretClient = new SecretClientBuilder()
        .vaultUrl(VAULT_URL)
        .clientOptions(new ClientOptions().setTracingOptions(tracingOptions))
        .credential(new DefaultAzureCredentialBuilder().build())
        .buildClient();
  • disable tracing from specific client instances:

    TracingOptions tracingOptions = new TracingOptions().setEnabled(false);
    
    SecretClient secretClient = new SecretClientBuilder()
        .vaultUrl(VAULT_URL)
        .clientOptions(new ClientOptions().setTracingOptions(tracingOptions))
        .credential(new DefaultAzureCredentialBuilder().build())
        .buildClient();
  • configure custom telemtery pipelines for Azure clients, mock tracing for testing purposes

    SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
        .setSampler(new MyAzureSdkSpanSampler())
        .addSpanProcessor(new MyAzureSdkEnrichingProcessor())
        .build();
    
    TracingOptions tracingOptions = new OpenTelemetryTracingOptions()
        .setProvider(tracerProvider);
    
    SecretClient secretClient = new SecretClientBuilder()
        .vaultUrl(VAULT_URL)
        .clientOptions(new ClientOptions().setTracingOptions(tracingOptions))
        .credential(new DefaultAzureCredentialBuilder().build())
        .buildClient();

Client libraries changes

  1. Better API for eventhubs/serivebus

    • Before

      Context builder = tracer.getSharedSpanBuilder("send message", Context.NONE);
      
      // rigid context propagation support
      String diagnosticId = message1.getApplicationProperties().get("diagnostic-id");
      
      Context spanContext = tracer.extractContext(diagnosticId, Context.NONE);
      
      // untyped attributes mixed with objects in context
      tracer.addLink(builder
          .addData("enqueued-time", "now")
          .addData("span-context", spanContext.getData("span-context")));
      
      // messaging-specific APIs
      Context span = tracer.start("send message", builder, ProcessKind.SEND);
      // do stuff
      tracer.end("ok", null, span);
    • After:

      StartSpanOptions options = new StartSpanOptions(SpanKind.CLIENT)
          .setAttribute("host", "my-eventhubs.com")
          .setAttribute("entity", "namespace");
      
      // supports additional context to comply with new standards
      Context message1TraceContext = tracer.extractContext((name) -> message1.getApplicationProperties().get(name);
      
      // more strongly types APIs
      Link link1 = new Link(message1TraceContext, Collections.singletonMap("enqueued-time", "now"));
      
      options.addLink(link1);
      
      // general-purpose tracing APIs, not specific to messaging
      Context span = tracer.start("send message", options, Context.NONE);
      // do stuff
      tracer.end("ok", null, span);
  2. Optimization: no need to pass az.namespace in Context (on each call)

    • Before:

      Mono<PagedResponse<String>> pagedResponseMono = this.registriesImplClient.getRepositoriesSinglePageAsync(null, 
         pageSize, context.addData(AZ_TRACING_NAMESPACE_KEY, CONTAINER_REGISTRY_TRACING_NAMESPACE_VALUE))
                 .map(res -> UtilsImpl.getPagedResponseWithContinuationToken(res))
                 .onErrorMap(UtilsImpl::mapException);
    • After:

      // builder
      HttpPipeline httpPipeline =
             new HttpPipelineBuilder()
                 .policies(policies.toArray(new HttpPipelinePolicy[0]))
                 .httpClient(httpClient)
                 .tracer(TracerProvider.getDefaultProvider().createTracer(CLIENT_NAME, CLIENT_VERSION, CONTAINER_REGISTRY_TRACING_NAMESPACE_VALUE, tracingOptions))
                 .build();
      // Service client           
      Mono<PagedResponse<String>> pagedResponseMono = this.registriesImplClient.getRepositoriesSinglePageAsync(null,
           pageSize, context)
                 .map(res -> UtilsImpl.getPagedResponseWithContinuationToken(res))
                 .onErrorMap(UtilsImpl::mapException);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment