From 18a94c29fc5aa8204dcdae91f354a12985ca1a10 Mon Sep 17 00:00:00 2001 From: Srinivas Chippagiri Date: Thu, 5 Nov 2026 01:40:40 -0800 Subject: [PATCH] fix: don't modify the configuration in the Metrics constructor When the configuration had no telemetry configuration, the Metrics constructor set a new default one on it. A configuration shared with other code paths was thereby changed as a side effect. Fall back to a default telemetry configuration inside Metrics instead, and let Attributes.prepare take the telemetry configuration directly. Fixes #292 Signed-off-by: Srinivas Chippagiri --- .../dev/openfga/sdk/telemetry/Attributes.java | 32 ++++++++++++------- .../dev/openfga/sdk/telemetry/Metrics.java | 28 ++++++++++------ .../openfga/sdk/telemetry/MetricsTest.java | 28 ++++++++++++++++ 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/main/java/dev/openfga/sdk/telemetry/Attributes.java b/src/main/java/dev/openfga/sdk/telemetry/Attributes.java index 71289cda..466447e9 100644 --- a/src/main/java/dev/openfga/sdk/telemetry/Attributes.java +++ b/src/main/java/dev/openfga/sdk/telemetry/Attributes.java @@ -4,6 +4,7 @@ import dev.openfga.sdk.api.client.ApiResponse; import dev.openfga.sdk.api.configuration.Configuration; +import dev.openfga.sdk.api.configuration.TelemetryConfiguration; import dev.openfga.sdk.api.configuration.Credentials; import dev.openfga.sdk.api.configuration.CredentialsMethod; import io.opentelemetry.api.common.AttributeKey; @@ -97,23 +98,32 @@ public class Attributes { */ public static io.opentelemetry.api.common.Attributes prepare( Map attributes, Metric metric, Configuration configuration) { + return prepare(attributes, metric, configuration == null ? null : configuration.getTelemetryConfiguration()); + } + + /** + * Filters the given attributes based on the telemetry configuration. + * + * @param attributes the attributes to filter + * @param metric the metric to filter the attributes for + * @param telemetryConfiguration the telemetry configuration to filter with + * + * @return the prepared attributes + */ + public static io.opentelemetry.api.common.Attributes prepare( + Map attributes, Metric metric, TelemetryConfiguration telemetryConfiguration) { if (attributes == null || attributes.isEmpty() - || configuration == null - || configuration.getTelemetryConfiguration() == null - || configuration.getTelemetryConfiguration().metrics() == null - || configuration.getTelemetryConfiguration().metrics().isEmpty() - || !configuration.getTelemetryConfiguration().metrics().containsKey(metric) - || configuration - .getTelemetryConfiguration() - .metrics() - .get(metric) - .isEmpty()) { + || telemetryConfiguration == null + || telemetryConfiguration.metrics() == null + || telemetryConfiguration.metrics().isEmpty() + || !telemetryConfiguration.metrics().containsKey(metric) + || telemetryConfiguration.metrics().get(metric).isEmpty()) { return io.opentelemetry.api.common.Attributes.empty(); } Map> configAllowedAttributes = - configuration.getTelemetryConfiguration().metrics().get(metric); + telemetryConfiguration.metrics().get(metric); io.opentelemetry.api.common.AttributesBuilder builder = io.opentelemetry.api.common.Attributes.builder(); diff --git a/src/main/java/dev/openfga/sdk/telemetry/Metrics.java b/src/main/java/dev/openfga/sdk/telemetry/Metrics.java index 817a331d..89068d88 100644 --- a/src/main/java/dev/openfga/sdk/telemetry/Metrics.java +++ b/src/main/java/dev/openfga/sdk/telemetry/Metrics.java @@ -17,6 +17,7 @@ public class Metrics { private final Map counters; private final Map histograms; private final Configuration configuration; + private final TelemetryConfiguration defaultTelemetryConfiguration; public Metrics() { this(new Configuration()); @@ -27,9 +28,16 @@ public Metrics(Configuration configuration) { this.counters = new ConcurrentHashMap<>(); this.histograms = new ConcurrentHashMap<>(); this.configuration = configuration; - if (this.configuration.getTelemetryConfiguration() == null) { - this.configuration.telemetryConfiguration(new TelemetryConfiguration()); - } + this.defaultTelemetryConfiguration = new TelemetryConfiguration(); + } + + /** + * Returns the telemetry configuration of the configuration, or the default one if it has none. The caller's + * configuration is never modified, since it may be shared. + */ + private TelemetryConfiguration telemetryConfiguration() { + TelemetryConfiguration telemetryConfiguration = configuration.getTelemetryConfiguration(); + return telemetryConfiguration != null ? telemetryConfiguration : defaultTelemetryConfiguration; } /** @@ -51,8 +59,9 @@ public Meter getMeter() { * @return The LongCounter metric instance, if the counter was configured. Otherwise, null. */ public LongCounter getCounter(Counter counter, Long value, Map attributes) { - if (configuration.getTelemetryConfiguration().metrics() == null - || !configuration.getTelemetryConfiguration().metrics().containsKey(counter)) { + TelemetryConfiguration telemetryConfiguration = telemetryConfiguration(); + if (telemetryConfiguration.metrics() == null + || !telemetryConfiguration.metrics().containsKey(counter)) { return null; } LongCounter counterInstance = counters.computeIfAbsent(counter.getName(), name -> meter.counterBuilder(name) @@ -60,7 +69,7 @@ public LongCounter getCounter(Counter counter, Long value, Map attributes) { - if (configuration.getTelemetryConfiguration().metrics() == null - || !configuration.getTelemetryConfiguration().metrics().containsKey(histogram)) { + TelemetryConfiguration telemetryConfiguration = telemetryConfiguration(); + if (telemetryConfiguration.metrics() == null + || !telemetryConfiguration.metrics().containsKey(histogram)) { return null; } @@ -88,7 +98,7 @@ public DoubleHistogram getHistogram(Histogram histogram, Double value, Map