This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-26611-camel-4.18.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit e43bf75cec77a4a7fa34ee72c1da7d7d5b15e0f0 Author: Claus Ibsen <[email protected]> AuthorDate: Thu Nov 5 13:05:35 2026 +0100 CAMEL-26611: camel-micrometer, camel-opentelemetry-metrics - use tags and attributes from headers as given (#29223) Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit 49a0b3fed1af723c00a147ec63cf4cb7c94ac50d) Signed-off-by: Claus Ibsen <[email protected]> # Conflicts: # catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/micrometer-component.adoc # catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/opentelemetry-metrics-component.adoc # components/camel-micrometer/src/main/docs/micrometer-component.adoc # components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/CounterRouteTest.java # components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/CounterRouteTest.java # docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc --- .../camel/catalog/components/micrometer.json | 2 +- .../catalog/components/opentelemetry-metrics.json | 2 +- .../camel/component/micrometer/micrometer.json | 2 +- .../src/main/docs/micrometer-component.adoc | 5 +++ .../micrometer/AbstractMicrometerProducer.java | 4 ++- .../component/micrometer/MicrometerConstants.java | 4 ++- .../component/micrometer/CounterRouteTest.java | 40 ++++++++++++++++++++++ .../metrics/opentelemetry-metrics.json | 2 +- .../main/docs/opentelemetry-metrics-component.adoc | 5 +++ .../metrics/AbstractOpenTelemetryProducer.java | 17 ++++----- .../metrics/OpenTelemetryConstants.java | 3 +- .../opentelemetry/metrics/CounterRouteTest.java | 40 ++++++++++++++++++++++ .../dsl/MicrometerEndpointBuilderFactory.java | 4 ++- .../dsl/OpenTelemetryEndpointBuilderFactory.java | 4 ++- 14 files changed, 114 insertions(+), 20 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json index 9f359adc4a8f..859da62236c4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json @@ -35,7 +35,7 @@ "CamelMetricsCounterIncrement": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override increment value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_COUNTER_INCREMENT" }, "CamelMetricsName": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override name value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_NAME" }, "CamelMetricsDescription": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override description value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_DESCRIPTION" }, - "CamelMetricsTags": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.lang.Iterable<Tag>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter tags defined as URI parameters", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_TAGS" } + "CamelMetricsTags": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.lang.Iterable<Tag>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter tags defined as URI parameters. The tags from the header are used as given; use the tags URI parameters for Simple expressions.", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER [...] }, "properties": { "metricsType": { "index": 0, "kind": "path", "displayName": "Metrics Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "io.micrometer.core.instrument.Meter.Type", "enum": [ "counter", "summary", "timer" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Type of metrics" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json index 4559aac92435..f3f840e8a155 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json @@ -35,7 +35,7 @@ "CamelMetricsCounterIncrement": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override increment value in URI", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_COUNTER_INCREMENT" }, "CamelMetricsName": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override name value in URI", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_METRIC_NAME" }, "CamelMetricsDescription": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override description value in URI", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_METRIC_DESCRIPTION" }, - "CamelMetricsAttributes": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "io.opentelemetry.api.common.Attributes", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter attributes defined as URI parameters", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_METRIC_ATTRIBUTES" } + "CamelMetricsAttributes": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "io.opentelemetry.api.common.Attributes", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter attributes defined as URI parameters. The attributes from the header are used as given; use the attributes URI parameters for Simple expressions.", "constantName": "org.apache.camel.opentele [...] }, "properties": { "metricType": { "index": 0, "kind": "path", "displayName": "Metric Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.opentelemetry.metrics.InstrumentType", "enum": [ "counter", "summary", "timer" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Type of metrics" }, diff --git a/components/camel-micrometer/src/generated/resources/META-INF/org/apache/camel/component/micrometer/micrometer.json b/components/camel-micrometer/src/generated/resources/META-INF/org/apache/camel/component/micrometer/micrometer.json index 9f359adc4a8f..859da62236c4 100644 --- a/components/camel-micrometer/src/generated/resources/META-INF/org/apache/camel/component/micrometer/micrometer.json +++ b/components/camel-micrometer/src/generated/resources/META-INF/org/apache/camel/component/micrometer/micrometer.json @@ -35,7 +35,7 @@ "CamelMetricsCounterIncrement": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override increment value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_COUNTER_INCREMENT" }, "CamelMetricsName": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override name value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_NAME" }, "CamelMetricsDescription": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override description value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_DESCRIPTION" }, - "CamelMetricsTags": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.lang.Iterable<Tag>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter tags defined as URI parameters", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_TAGS" } + "CamelMetricsTags": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.lang.Iterable<Tag>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter tags defined as URI parameters. The tags from the header are used as given; use the tags URI parameters for Simple expressions.", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER [...] }, "properties": { "metricsType": { "index": 0, "kind": "path", "displayName": "Metrics Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "io.micrometer.core.instrument.Meter.Type", "enum": [ "counter", "summary", "timer" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Type of metrics" }, diff --git a/components/camel-micrometer/src/main/docs/micrometer-component.adoc b/components/camel-micrometer/src/main/docs/micrometer-component.adoc index de970ff722f3..50893e20f145 100644 --- a/components/camel-micrometer/src/main/docs/micrometer-component.adoc +++ b/components/camel-micrometer/src/main/docs/micrometer-component.adoc @@ -147,6 +147,11 @@ from("direct:in") will update a counter with name `new.name` instead of `name.not.used` using the tag `dynamic-key` with value `dynamic-value` in addition to the tag `key` with value `value`. +The tags from the `CamelMetricsTags` header are used as given: unlike the `tags` URI parameters, +their keys and values are not evaluated as `Simple` expressions. A tag from the header overrides a tag +from the URI with the same key. To tag a meter with a value from the message, use a `tags` URI parameter +such as `tags.customer=${header.customerId}`, or compute the value in the route before setting the header. + All Metrics specific headers are removed from the message once the Micrometer endpoint finishes processing of exchange. While processing exchange Micrometer endpoint will catch all exceptions and write log entry using level `warn`. diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/AbstractMicrometerProducer.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/AbstractMicrometerProducer.java index c89b6b7234d9..ba1175a296b8 100644 --- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/AbstractMicrometerProducer.java +++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/AbstractMicrometerProducer.java @@ -64,11 +64,13 @@ public abstract class AbstractMicrometerProducer<T extends Meter> extends Defaul String defaultMetricsDescription = simple(exchange, getEndpoint().getMetricsDescription(), String.class); String finalMetricsDescription = getStringHeader(in, HEADER_METRIC_DESCRIPTION, defaultMetricsDescription); Iterable<Tag> headerTags = getTagHeader(in, HEADER_METRIC_TAGS, Tags.empty()); - Iterable<Tag> finalTags = Tags.concat(tags, headerTags).stream() + // only the tags from the endpoint are simple expressions, the tags from the header are used as given + Iterable<Tag> finalTags = Tags.of(tags).stream() .map(tag -> Tag.of( simple(exchange, tag.getKey(), String.class), simple(exchange, tag.getValue(), String.class))) .reduce(Tags.empty(), Tags::and, Tags::and) + .and(headerTags) .and(Tags.of( CAMEL_CONTEXT_TAG, getEndpoint().getCamelContext().getName())); try { diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConstants.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConstants.java index 997968187465..8584214872d4 100644 --- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConstants.java +++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConstants.java @@ -37,7 +37,9 @@ public final class MicrometerConstants { public static final String HEADER_METRIC_NAME = HEADER_PREFIX + "Name"; @Metadata(description = "Override description value in URI", javaType = "String") public static final String HEADER_METRIC_DESCRIPTION = HEADER_PREFIX + "Description"; - @Metadata(description = "To augment meter tags defined as URI parameters", javaType = "java.lang.Iterable<Tag>") + @Metadata(description = "To augment meter tags defined as URI parameters. The tags from the header are used as given;" + + " use the tags URI parameters for Simple expressions.", + javaType = "java.lang.Iterable<Tag>") public static final String HEADER_METRIC_TAGS = HEADER_PREFIX + "Tags"; public static final String DEFAULT_CAMEL_MESSAGE_HISTORY_METER_NAME = "camel.message.history"; diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/CounterRouteTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/CounterRouteTest.java index 2e332a3721db..c5a4813d621b 100644 --- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/CounterRouteTest.java +++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/CounterRouteTest.java @@ -16,8 +16,11 @@ */ package org.apache.camel.component.micrometer; +import java.util.Map; + import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import org.apache.camel.BindToRegistry; import org.apache.camel.EndpointInject; @@ -35,8 +38,10 @@ import org.springframework.context.support.AbstractApplicationContext; import static org.apache.camel.component.micrometer.MicrometerConstants.HEADER_COUNTER_DECREMENT; import static org.apache.camel.component.micrometer.MicrometerConstants.HEADER_COUNTER_INCREMENT; import static org.apache.camel.component.micrometer.MicrometerConstants.HEADER_METRIC_NAME; +import static org.apache.camel.component.micrometer.MicrometerConstants.HEADER_METRIC_TAGS; import static org.apache.camel.component.micrometer.MicrometerConstants.METRICS_REGISTRY_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; @CamelSpringTest public class CounterRouteTest extends CamelSpringTestSupport { @@ -56,6 +61,9 @@ public class CounterRouteTest extends CamelSpringTestSupport { @Produce("direct:in-4") private ProducerTemplate producer4; + @Produce("direct:in-5") + private ProducerTemplate producer5; + @BindToRegistry(METRICS_REGISTRY_NAME) private MeterRegistry registry = new SimpleMeterRegistry(); @@ -85,6 +93,10 @@ public class CounterRouteTest extends CamelSpringTestSupport { from("direct:in-4") .to("micrometer:counter:D?increment=${body.length}&tags.a=${body.length}") .to("mock:out"); + + from("direct:in-5") + .to("micrometer:counter:I?tags.a=${body.length}&tags.b=uri") + .to("mock:out"); } }; } @@ -136,4 +148,32 @@ public class CounterRouteTest extends CamelSpringTestSupport { assertEquals(Integer.toString(message.length()), counter.getId().getTag("a")); endpoint.assertIsSatisfied(); } + + @Test + public void testHeaderTagsAreUsedAsGiven() throws Exception { + endpoint.expectedMessageCount(1); + producer5.sendBodyAndHeaders("Hello", Map.of( + "k", "key", + HEADER_METRIC_TAGS, Tags.of("c", "${body}", "${header.k}", "d"))); + Counter counter = registry.find("I").counter(); + assertEquals(1.0D, counter.count(), 0.01D); + // the tags from the uri are resolved per exchange + assertEquals("5", counter.getId().getTag("a")); + assertEquals("uri", counter.getId().getTag("b")); + // the tags from the header are not + assertEquals("${body}", counter.getId().getTag("c")); + assertEquals("d", counter.getId().getTag("${header.k}")); + assertNull(counter.getId().getTag("key")); + endpoint.assertIsSatisfied(); + } + + @Test + public void testHeaderTagOverridesUriTagWithSameKey() throws Exception { + endpoint.expectedMessageCount(1); + producer5.sendBodyAndHeader("Hello", HEADER_METRIC_TAGS, Tags.of("b", "header")); + Counter counter = registry.find("I").counter(); + assertEquals("5", counter.getId().getTag("a")); + assertEquals("header", counter.getId().getTag("b")); + endpoint.assertIsSatisfied(); + } } diff --git a/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json b/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json index 4559aac92435..f3f840e8a155 100644 --- a/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json +++ b/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json @@ -35,7 +35,7 @@ "CamelMetricsCounterIncrement": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override increment value in URI", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_COUNTER_INCREMENT" }, "CamelMetricsName": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override name value in URI", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_METRIC_NAME" }, "CamelMetricsDescription": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override description value in URI", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_METRIC_DESCRIPTION" }, - "CamelMetricsAttributes": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "io.opentelemetry.api.common.Attributes", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter attributes defined as URI parameters", "constantName": "org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_METRIC_ATTRIBUTES" } + "CamelMetricsAttributes": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "io.opentelemetry.api.common.Attributes", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter attributes defined as URI parameters. The attributes from the header are used as given; use the attributes URI parameters for Simple expressions.", "constantName": "org.apache.camel.opentele [...] }, "properties": { "metricType": { "index": 0, "kind": "path", "displayName": "Metric Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.opentelemetry.metrics.InstrumentType", "enum": [ "counter", "summary", "timer" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Type of metrics" }, diff --git a/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc b/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc index ba8051734bec..ca02d02a7cd4 100644 --- a/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc +++ b/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc @@ -90,6 +90,11 @@ from("direct:in") will update a counter with name `new.name` (instead of `name.not.used`) using the attribute `dynamic-key` with value `dynamic-value` in addition to the attribute `key` with value `value`. +The attributes from the `CamelMetricsAttributes` header are used as given: unlike the `attributes` URI parameters, +their keys and values are not evaluated as `Simple` expressions. An attribute from the header overrides an attribute +from the URI with the same key. To add an attribute with a value from the message, use an `attributes` URI parameter +such as `attributes.customer=${header.customerId}`, or compute the value in the route before setting the header. + All Metrics specific headers are removed from the message once the OpenTelemetry endpoint finishes processing the exchange. While processing the exchange the OpenTelemetry endpoint will catch all exceptions and write log entry using level `warn`. diff --git a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/AbstractOpenTelemetryProducer.java b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/AbstractOpenTelemetryProducer.java index f033094546e4..db469ee5a212 100644 --- a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/AbstractOpenTelemetryProducer.java +++ b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/AbstractOpenTelemetryProducer.java @@ -16,10 +16,6 @@ */ package org.apache.camel.opentelemetry.metrics; -import java.util.HashMap; -import java.util.Map; - -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import org.apache.camel.Exchange; @@ -63,14 +59,13 @@ abstract public class AbstractOpenTelemetryProducer<T> extends DefaultProducer { String defaultMetricsDescription = simple(exchange, getEndpoint().getMetricsDescription(), String.class); String finalMetricsDescription = getStringHeader(in, HEADER_METRIC_DESCRIPTION, defaultMetricsDescription); - Map<AttributeKey<?>, Object> map = new HashMap<>(attributes.asMap()); - map.putAll(getAttributesHeader(in, HEADER_METRIC_ATTRIBUTES, Attributes.empty()).asMap()); - + // only the attributes from the endpoint are simple expressions, the attributes from the header are used as given AttributesBuilder ab = Attributes.builder(); - for (Map.Entry<AttributeKey<?>, Object> entry : map.entrySet()) { - ab.put(simple(exchange, entry.getKey().toString(), String.class), - simple(exchange, entry.getValue().toString(), String.class)); - } + attributes.forEach((key, value) -> ab.put( + simple(exchange, key.getKey(), String.class), + simple(exchange, value.toString(), String.class))); + getAttributesHeader(in, HEADER_METRIC_ATTRIBUTES, Attributes.empty()) + .forEach((key, value) -> ab.put(key.getKey(), value.toString())); ab.put(CAMEL_CONTEXT_ATTRIBUTE, getEndpoint().getCamelContext().getName()); try { diff --git a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java index 2a2d61c78b94..dcaa6a7000f2 100644 --- a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java +++ b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java @@ -34,7 +34,8 @@ public class OpenTelemetryConstants { public static final String HEADER_METRIC_NAME = HEADER_PREFIX + "Name"; @Metadata(description = "Override description value in URI", javaType = "String") public static final String HEADER_METRIC_DESCRIPTION = HEADER_PREFIX + "Description"; - @Metadata(description = "To augment meter attributes defined as URI parameters", + @Metadata(description = "To augment meter attributes defined as URI parameters. The attributes from the header are used" + + " as given; use the attributes URI parameters for Simple expressions.", javaType = "io.opentelemetry.api.common.Attributes") public static final String HEADER_METRIC_ATTRIBUTES = HEADER_PREFIX + "Attributes"; diff --git a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/CounterRouteTest.java b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/CounterRouteTest.java index 035c4d0e9b41..56d38def13a5 100644 --- a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/CounterRouteTest.java +++ b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/CounterRouteTest.java @@ -17,6 +17,7 @@ package org.apache.camel.opentelemetry.metrics; import java.util.Collection; +import java.util.Map; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -36,6 +37,7 @@ import static org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.HEAD import static org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.HEADER_METRIC_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; public class CounterRouteTest extends CamelTestSupport { @@ -76,6 +78,10 @@ public class CounterRouteTest extends CamelTestSupport { .setHeader(OpenTelemetryConstants.HEADER_COUNTER_INCREMENT, simple("${body.length}")) .to("opentelemetry-metrics:counter:F") .to("mock:result"); + + from("direct:in7") + .to("opentelemetry-metrics:counter:J?attributes.a=${body.length}&attributes.b=uri") + .to("mock:result"); } }; } @@ -226,6 +232,40 @@ public class CounterRouteTest extends CamelTestSupport { MockEndpoint.assertIsSatisfied(context); } + @Test + public void testHeaderAttributesAreUsedAsGiven() throws Exception { + MockEndpoint mockEndpoint = getMockEndpoint("mock:result"); + mockEndpoint.expectedMessageCount(1); + template.sendBodyAndHeaders("direct:in7", "Hello", Map.of( + "k", "key", + HEADER_METRIC_ATTRIBUTES, Attributes.of( + AttributeKey.stringKey("c"), "${body}", + AttributeKey.stringKey("${header.k}"), "d"))); + + Attributes attributes = getMetric("J").getAttributes(); + // the attributes from the uri are resolved per exchange + assertEquals("5", attributes.get(AttributeKey.stringKey("a"))); + assertEquals("uri", attributes.get(AttributeKey.stringKey("b"))); + // the attributes from the header are not + assertEquals("${body}", attributes.get(AttributeKey.stringKey("c"))); + assertEquals("d", attributes.get(AttributeKey.stringKey("${header.k}"))); + assertNull(attributes.get(AttributeKey.stringKey("key"))); + MockEndpoint.assertIsSatisfied(context); + } + + @Test + public void testHeaderAttributeOverridesUriAttributeWithSameKey() throws Exception { + MockEndpoint mockEndpoint = getMockEndpoint("mock:result"); + mockEndpoint.expectedMessageCount(1); + template.sendBodyAndHeader("direct:in7", "Hello", HEADER_METRIC_ATTRIBUTES, + Attributes.of(AttributeKey.stringKey("b"), "header")); + + Attributes attributes = getMetric("J").getAttributes(); + assertEquals("5", attributes.get(AttributeKey.stringKey("a"))); + assertEquals("header", attributes.get(AttributeKey.stringKey("b"))); + MockEndpoint.assertIsSatisfied(context); + } + protected LongPointData getMetric(String metricName) { PointData pd = otelExtension.getMetrics().stream() .filter(d -> d.getName().equals(metricName)) diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MicrometerEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MicrometerEndpointBuilderFactory.java index 3ea81aec35b0..9dcb52012fde 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MicrometerEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MicrometerEndpointBuilderFactory.java @@ -365,7 +365,9 @@ public interface MicrometerEndpointBuilderFactory { return "CamelMetricsDescription"; } /** - * To augment meter tags defined as URI parameters. + * To augment meter tags defined as URI parameters. The tags from the + * header are used as given; use the tags URI parameters for Simple + * expressions. * * The option is a: {@code java.lang.Iterable<Tag>} type. * diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java index 23d96aaf5c13..b05d8da4d953 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java @@ -395,7 +395,9 @@ public interface OpenTelemetryEndpointBuilderFactory { return "CamelMetricsDescription"; } /** - * To augment meter attributes defined as URI parameters. + * To augment meter attributes defined as URI parameters. The attributes + * from the header are used as given; use the attributes URI parameters + * for Simple expressions. * * The option is a: {@code io.opentelemetry.api.common.Attributes} type. *
