open-telemetry / opentelemetry-java-instrumentation

OpenTelemetry auto-instrumentation and instrumentation libraries for Java
https://opentelemetry.io
Apache License 2.0
1.79k stars 782 forks source link

Auto-configure EventLoggerProvider #11623

Open swar8080 opened 1 week ago

swar8080 commented 1 week ago

Is your feature request related to a problem? Please describe.

We're looking to use the Events API but currently have to build an EventLogger manually. It's error-prone getting the manual set-up to use all the auto-configuration that we're used to the java agent doing for us. For example, our attempt is:

  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api-incubator</artifactId>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
    <version>${opentelemetry.version}</version>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
    <version>${opentelemetry.version}</version>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-resources</artifactId>
    <version>${opentelemetry.javaagent.version}-alpha</version>
  </dependency>
  <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
    <version>${opentelemetry.version}</version>
  </dependency>
...
  @Bean
  EventLogger otelEventLogger() {
    var autoOtelSdk = AutoConfiguredOpenTelemetrySdk.builder().build();
    var otelConfig = AutoConfigureUtil.getConfig(autoOtelSdk);
    if (otelConfig == null) {
      logger.info(
          "No OTEL ConfigProperties available for EventLogger. Using empty configuration instead");
      otelConfig = DefaultConfigProperties.create(new HashMap<>());
    }

    Resource resource = Resource.getDefault();
    ServiceLoader<ResourceProvider> serviceLoader = ServiceLoader.load(ResourceProvider.class);
    for (ResourceProvider provider : serviceLoader) {
      Resource provided = provider.createResource(otelConfig);
      resource = resource.merge(provided);
    }

    OtlpGrpcLogRecordExporter exporter =
        OtlpGrpcLogRecordExporter.builder()
            .setRetryPolicy(
                RetryPolicy.builder()
                    .setMaxAttempts(5)
                    .setMaxBackoff(Duration.ofSeconds(3L))
                    .build())
            .build();
    BatchLogRecordProcessor processor =
        BatchLogRecordProcessor.builder(exporter)
            .setMeterProvider(GlobalOpenTelemetry.getMeterProvider())
            .build();
    SdkLoggerProvider loggerProvider =
        SdkLoggerProvider.builder().setResource(resource).addLogRecordProcessor(processor).build();

    EventLoggerProvider eventLoggerProvider = SdkEventLoggerProvider.create(loggerProvider);
    return eventLoggerProvider.eventLoggerBuilder("com.demo").build();
  }

Describe the solution you'd like

Have the javaagent auto-configure the EventLoggerProvider and expose it for applications.

@jack-berg had a suggestion for how to do this: https://cloud-native.slack.com/archives/C014L2KCTE3/p1718657558881159?thread_ts=1718293157.542669&cid=C014L2KCTE3

Describe alternatives you've considered

Additional context

Any guesses if packaging our manual set-up in an agent extension would work as a temporary solution? Or would the call GlobalEventLoggerProvider.set happen using a different class loader than what's available to the application?