opentelemetry-java icon indicating copy to clipboard operation
opentelemetry-java copied to clipboard

[JavaAgent] Autoconfigure customizer for metric exporter in pull-based model, E.g., Prometheus, for all (custom and autogenerated) metrics.

Open lokeshmavale opened this issue 2 years ago • 6 comments

Discussed in https://github.com/open-telemetry/opentelemetry-java/discussions/5163

Originally posted by lokeshmavale February 1, 2023 Hi Team, I have requirement to send metrics in OTLP & Prometheus format. While sending metric I want to enrich the attributes for all the metrics (custom and autogenerated).

With Auto Configure SPI, I was able to override metrics using autoConfiguration.addMetricExporterCustomizer(this::configureSdkMetricExporterProvider);

I have observed that, this exporter only has access to OTLP (push based) exporter. How can I override Prometheus exporter without creating all new Prometheus server and registering it with auto agent using autoConfiguration.addMeterProviderCustomizer(). ?

Do we support pull based model exporter override via auto configuration?

Thanks, Lokesh

lokeshmavale avatar Feb 01 '23 13:02 lokeshmavale

If this is specifically about how to customize a prometheus exporter with the agent, I think we should move this question/issue over to the instrumentation repository. Does that make sense to you?

jkwatson avatar Feb 01 '23 16:02 jkwatson

Discussed in https://github.com/open-telemetry/opentelemetry-java/discussions/5163

@jkwatson ^^

trask avatar Feb 01 '23 17:02 trask

Discussed in open-telemetry/opentelemetry-java-instrumentation#5163

@jkwatson ^^

does that mean we should close this issue then?

jkwatson avatar Feb 01 '23 17:02 jkwatson

Thanks @trask & @jkwatson, Sure. I can close this issue here. Please let me know if I can raise this issue under open-telemetry/opentelemetry-java-instrumentation ?

lokeshmavale avatar Feb 01 '23 17:02 lokeshmavale

Discussed in open-telemetry/opentelemetry-java-instrumentation#5163

@jkwatson ^^

does that mean we should close this issue then?

oh my bad, I thought that issue was already in java-instrumentation repo.

I will transfer this one, thx

trask avatar Feb 01 '23 18:02 trask

sorry to bounce this issue around, but I think it is at its core an SDK autoconfiguration question, so I've transferred it back

I think this is currently blocked by specification work: https://github.com/open-telemetry/opentelemetry-specification/issues/4298

Though there is an internal API that you can use today, something like:

@AutoService(AutoConfigurationCustomizerProvider.class)
public class DynamicMetricAttributeEnricher implements AutoConfigurationCustomizerProvider {
    
    @Override
    public void customize(AutoConfigurationCustomizer autoConfiguration) {
        autoConfiguration.addMeterProviderCustomizer((builder, config) -> {
            
            AttributesProcessor processor = new AttributesProcessor() {
                @Override
                public Attributes process(Attributes incoming, Context context) {
                    // Add dynamic attributes based on runtime context
                    return incoming.toBuilder()
                        .put("request.timestamp", System.currentTimeMillis())
                        .put("thread.name", Thread.currentThread().getName())
                        .put("hostname", System.getenv().getOrDefault("HOSTNAME", "unknown"))
                        .build();
                }
                
                @Override
                public boolean usesContext() {
                    return false; // Set to true if you use Context for attribute values
                }
            };
            
            // Apply to all instruments with wildcard selector
            ViewBuilder viewBuilder = View.builder();
            addAttributesProcessor(viewBuilder, processor);
            
            builder.registerView(
                InstrumentSelector.builder().setName("*").build(),
                viewBuilder.build()
            );
            
            return builder;
        });
    }
    
    // Helper to call internal API via reflection
    private static void addAttributesProcessor(ViewBuilder viewBuilder, 
                                               AttributesProcessor processor) {
        try {
            Method method = ViewBuilder.class.getDeclaredMethod(
                "addAttributesProcessor", AttributesProcessor.class);
            method.setAccessible(true);
            method.invoke(viewBuilder, processor);
        } catch (Exception e) {
            throw new IllegalStateException(
                "Failed to add AttributesProcessor", e);
        }
    }
}

trask avatar Oct 03 '25 02:10 trask