001package io.prometheus.metrics.core.exemplars; 002 003import io.prometheus.metrics.annotations.StableApi; 004import io.prometheus.metrics.model.snapshots.Labels; 005import java.util.concurrent.atomic.AtomicReference; 006import java.util.function.Supplier; 007import javax.annotation.Nullable; 008 009/** 010 * Global holder for a {@link Supplier} of additional {@link Labels} that are merged into every 011 * automatically-sampled Exemplar across the entire application. 012 * 013 * <p>This is the global counterpart to the per-metric {@code exemplarLabelsSupplier(...)} builder 014 * method. Registering a supplier here affects <em>all</em> metrics, including metrics registered by 015 * third-party libraries that the application does not control. This makes it the right tool when 016 * you cannot modify the code that creates the metrics. 017 * 018 * <p>The supplier is invoked on the metric hot path (rate-limited by the exemplar sampler), each 019 * time an Exemplar is sampled from a valid, sampled span context. It should therefore be cheap and 020 * non-blocking. It may return dynamic, request-scoped values, for example an identifier read from a 021 * thread-local: 022 * 023 * <pre>{@code 024 * ExemplarLabelsSupplier.setExemplarLabelsSupplier( 025 * () -> Labels.of("management_id", currentManagementId())); 026 * }</pre> 027 * 028 * <p>Labels returned by the supplier that collide with {@code trace_id}/{@code span_id} (or, when a 029 * per-metric supplier is also configured, with that supplier's labels) are silently dropped rather 030 * than causing an error: the per-metric supplier takes precedence over the global one, and the 031 * reserved {@code trace_id}/{@code span_id} labels always win. If the supplier throws, the 032 * exception is swallowed and the Exemplar is created without the additional labels, so a 033 * misbehaving supplier never breaks metric collection. 034 */ 035@StableApi 036public class ExemplarLabelsSupplier { 037 038 private static final AtomicReference<Supplier<Labels>> supplierRef = new AtomicReference<>(); 039 040 private ExemplarLabelsSupplier() {} 041 042 /** 043 * Register a global supplier of additional exemplar labels. Pass {@code null} to remove a 044 * previously registered supplier. The most recently registered supplier wins. 045 */ 046 public static void setExemplarLabelsSupplier(@Nullable Supplier<Labels> supplier) { 047 supplierRef.set(supplier); 048 } 049 050 /** Returns the registered global supplier, or {@code null} if none has been set. */ 051 @Nullable 052 public static Supplier<Labels> getExemplarLabelsSupplier() { 053 return supplierRef.get(); 054 } 055}