diff --git a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGenerator.java b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGenerator.java index ff49d3b1..d04a9abb 100644 --- a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGenerator.java +++ b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGenerator.java @@ -16,11 +16,11 @@ package com.solarwinds.opentelemetry.extensions; -import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static com.solarwinds.opentelemetry.extensions.SharedNames.LEGACY_TRANSACTION_NAME_KEY; +import static com.solarwinds.opentelemetry.extensions.SharedNames.TRANSACTION_NAME_KEY; import com.solarwinds.joboe.logging.Logger; import com.solarwinds.joboe.logging.LoggerFactory; -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.metrics.LongHistogram; @@ -37,10 +37,6 @@ public class InboundMeasurementMetricsGenerator implements ExtendedSpanProcessor { private LongHistogram responseTime; - private static final AttributeKey TRANSACTION_NAME_KEY = - stringKey(SharedNames.TRANSACTION_NAME_KEY); - private static final AttributeKey LEGACY_TRANSACTION_NAME_KEY = - stringKey("TransactionName"); private static final Logger logger = LoggerFactory.getLogger(); diff --git a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/SharedNames.java b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/SharedNames.java index a85911e9..3c566b3c 100644 --- a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/SharedNames.java +++ b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/SharedNames.java @@ -16,13 +16,15 @@ package com.solarwinds.opentelemetry.extensions; +import static io.opentelemetry.api.common.AttributeKey.stringKey; + +import io.opentelemetry.api.common.AttributeKey; + public final class SharedNames { private SharedNames() {} public static final String COMPONENT_NAME = "solarwinds"; - public static final String TRANSACTION_NAME_KEY = "sw.transaction"; - public static final String SPAN_STACKTRACE_FILTER_CLASS = "com.solarwinds.opentelemetry.extensions.SpanStacktraceFilter"; @@ -33,4 +35,9 @@ private SharedNames() {} public static final String SW_OTEL_PROXY_HOST_KEY = "sw.otel.exporter.proxy.host"; public static final String SW_OTEL_PROXY_PORT_KEY = "sw.otel.exporter.proxy.port"; + + public static final AttributeKey TRANSACTION_NAME_KEY = stringKey("sw.transaction"); + + public static final AttributeKey LEGACY_TRANSACTION_NAME_KEY = + stringKey("TransactionName"); } diff --git a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/TransactionNameManager.java b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/TransactionNameManager.java index 1ecb9165..1e90026b 100644 --- a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/TransactionNameManager.java +++ b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/TransactionNameManager.java @@ -16,6 +16,8 @@ package com.solarwinds.opentelemetry.extensions; +import static com.solarwinds.opentelemetry.extensions.SharedNames.TRANSACTION_NAME_KEY; + import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.solarwinds.joboe.config.ConfigManager; @@ -164,8 +166,13 @@ static String truncateTransactionName(String inputTransactionName) { static String buildTransactionName(SpanData spanData) { Attributes spanAttributes = spanData.getAttributes(); - String custName = CustomTransactionNameDict.get(spanData.getTraceId()); + String transactionName = spanAttributes.get(TRANSACTION_NAME_KEY); + if (transactionName != null && !transactionName.isEmpty()) { + logger.trace(String.format("Using pre-computed transaction name -> %s", transactionName)); + return transactionName; + } + String custName = CustomTransactionNameDict.get(spanData.getTraceId()); if (custName != null) { logger.trace(String.format("Using custom transaction name -> %s", custName)); return custName; @@ -201,7 +208,7 @@ static String buildTransactionName(SpanData spanData) { if (customTransactionNamePattern != null) { // try forming transaction name by the custom configured pattern - String transactionName = + transactionName = getTransactionNameByUrlAndPattern( path, customTransactionNamePattern, false, CUSTOM_TRANSACTION_NAME_PATTERN_SEPARATOR); diff --git a/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGeneratorTest.java b/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGeneratorTest.java index a389a506..1e3fbb16 100644 --- a/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGeneratorTest.java +++ b/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/InboundMeasurementMetricsGeneratorTest.java @@ -129,9 +129,7 @@ void verifyMetricAttributeValuesIsCorrectWhenNotErrorSpan() { && Boolean.FALSE.equals( attributes.get(AttributeKey.booleanKey("sw.is_error"))) && TransactionNameManager.getTransactionName(testSpanData) - .equals( - attributes.get( - AttributeKey.stringKey(SharedNames.TRANSACTION_NAME_KEY)))); + .equals(attributes.get(SharedNames.TRANSACTION_NAME_KEY))); assertTrue(allMatch); } @@ -170,9 +168,7 @@ void verifyMetricAttributeValuesIsCorrectWhenErrorSpan() { && Boolean.TRUE.equals( attributes.get(AttributeKey.booleanKey("sw.is_error"))) && TransactionNameManager.getTransactionName(testSpanData) - .equals( - attributes.get( - AttributeKey.stringKey(SharedNames.TRANSACTION_NAME_KEY)))); + .equals(attributes.get(SharedNames.TRANSACTION_NAME_KEY))); assertTrue(allMatch); } diff --git a/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/TransactionNameManagerTest.java b/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/TransactionNameManagerTest.java new file mode 100644 index 00000000..d155bde8 --- /dev/null +++ b/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/TransactionNameManagerTest.java @@ -0,0 +1,83 @@ +/* + * © SolarWinds Worldwide, LLC. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.solarwinds.opentelemetry.extensions; + +import static com.solarwinds.opentelemetry.extensions.SharedNames.TRANSACTION_NAME_KEY; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.sdk.testing.trace.TestSpanData; +import io.opentelemetry.sdk.trace.data.StatusData; +import org.junit.jupiter.api.Test; + +class TransactionNameManagerTest { + + @Test + void buildTransactionNameReturnsPreComputedNameFromSpanAttribute() { + TestSpanData spanData = + TestSpanData.builder() + .setName("test") + .setKind(SpanKind.SERVER) + .setStartEpochNanos(0) + .setEndEpochNanos(10_000_000) + .setHasEnded(true) + .setStatus(StatusData.ok()) + .setAttributes(Attributes.of(TRANSACTION_NAME_KEY, "pre-computed-name")) + .build(); + + String result = TransactionNameManager.buildTransactionName(spanData); + assertEquals("pre-computed-name", result); + } + + @Test + void buildTransactionNameFallsBackWhenPreComputedNameIsEmpty() { + TestSpanData spanData = + TestSpanData.builder() + .setName("test") + .setKind(SpanKind.SERVER) + .setStartEpochNanos(0) + .setEndEpochNanos(10_000_000) + .setHasEnded(true) + .setStatus(StatusData.ok()) + .setAttributes(Attributes.of(TRANSACTION_NAME_KEY, "")) + .build(); + + String result = TransactionNameManager.buildTransactionName(spanData); + assertNotEquals("", result); + } + + @Test + void buildTransactionNameFallsBackWhenTransactionNameAttributeIsAbsent() { + TestSpanData spanData = + TestSpanData.builder() + .setName("test") + .setKind(SpanKind.SERVER) + .setStartEpochNanos(0) + .setEndEpochNanos(10_000_000) + .setHasEnded(true) + .setStatus(StatusData.ok()) + .setAttributes(Attributes.empty()) + .build(); + + String result = TransactionNameManager.buildTransactionName(spanData); + assertNotNull(result); + assertNotEquals("", result); + } +}