Skip to content

Commit

Permalink
Merge pull request #213 from solarwinds-cloud/cc/NH-75165
Browse files Browse the repository at this point in the history
NH-75165: use instrumentation api to access root span and set custom transaction name
  • Loading branch information
cleverchuk authored Apr 8, 2024
2 parents 0770949 + 663b568 commit 48e0545
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 176 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void onStart(Context parentContext, ReadWriteSpan span) {
if (!parentSpanContext.isValid()
|| parentSpanContext.isRemote()) { // then a root span of this service
String transactionName = TransactionNameManager.getTransactionName(span.toSpanData());
span.setAttribute("sw.transaction", transactionName);
span.setAttribute(TRANSACTION_NAME_KEY, transactionName);
logger.debug(
String.format("Transaction name derived on root span start: %s", transactionName));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.solarwinds.joboe.logging.Logger;
import com.solarwinds.joboe.logging.LoggerFactory;
import com.solarwinds.joboe.sampling.SettingsManager;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.javaagent.extension.AgentListener;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
import io.opentelemetry.sdk.trace.samplers.Sampler;
Expand All @@ -26,6 +27,13 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk openTelemetrySdk) {
new AwsLambdaSettingsFetcher(new FileSettingsReader("/tmp/solarwinds-apm-settings.json")),
SamplingConfigProvider.getSamplingConfiguration());

TransactionNameManager.setRuntimeNameGenerator(
spanData ->
new TransactionNameManager.TransactionNameResult(
spanData
.getAttributes()
.get(AttributeKey.stringKey(SharedNames.TRANSACTION_NAME_KEY)),
true));
logger.info("Successfully submitted SolarwindsAPM OpenTelemetry extensions settings");
} else {
logger.info("SolarwindsAPM OpenTelemetry extensions is disabled");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ void verifyMetricAttributeValuesIsCorrectWhenNotErrorSpan() {
200L, attributes.get(AttributeKey.longKey("http.status_code")))
&& !attributes.get(AttributeKey.booleanKey("sw.is_error"))
&& TransactionNameManager.getTransactionName(testSpanData)
.equals(attributes.get(AttributeKey.stringKey("sw.transaction"))));
.equals(
attributes.get(
AttributeKey.stringKey(SharedNames.TRANSACTION_NAME_KEY))));

assertTrue(allMatch);
}
Expand Down Expand Up @@ -144,7 +146,9 @@ void verifyMetricAttributeValuesIsCorrectWhenErrorSpan() {
500L, attributes.get(AttributeKey.longKey("http.status_code")))
&& attributes.get(AttributeKey.booleanKey("sw.is_error"))
&& TransactionNameManager.getTransactionName(testSpanData)
.equals(attributes.get(AttributeKey.stringKey("sw.transaction"))));
.equals(
attributes.get(
AttributeKey.stringKey(SharedNames.TRANSACTION_NAME_KEY))));

assertTrue(allMatch);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.Value;

public class TransactionNameManager {
private static final Logger logger = LoggerFactory.getLogger();
Expand All @@ -44,6 +48,11 @@ public class TransactionNameManager {

private static NamingScheme namingScheme = new DefaultNamingScheme(null);

@Getter @Setter
private static RuntimeNameGenerator runtimeNameGenerator =
(SpanData spanData) ->
new TransactionNameResult(CustomTransactionNameDict.get(spanData.getTraceId()), false);

static {
customTransactionNamePattern = getTransactionNamePattern();
addNameCountChangeListener();
Expand Down Expand Up @@ -103,7 +112,13 @@ static String[] parseTransactionNamePattern(String pattern) {
* @return transaction name
*/
public static String getTransactionName(SpanData spanData) {
String transactionName = buildTransactionName(spanData);
TransactionNameResult transactionNameResult = buildTransactionName(spanData);
String transactionName = transactionNameResult.name;

if (transactionNameResult.isLambda()) {
return transactionName;
}

if (transactionName != null) {
Boolean domainPrefixedTransactionName =
ConfigManager.getConfigOptional(
Expand Down Expand Up @@ -172,29 +187,19 @@ static String transformTransactionName(String inputTransactionName) {
return transactionName;
}

/**
* Builds a transaction name based on information provided in a span
*
* @param spanData otel span data
* @return a transaction name built based on the span, null if no transaction name can be built
*/
static String buildTransactionName(SpanData spanData) {
return buildTransactionName(
spanData.getTraceId(), spanData.getName(), spanData.getAttributes());
}

static String buildTransactionName(String traceId, String spanName, Attributes spanAttributes) {
static TransactionNameResult buildTransactionName(SpanData spanData) {
Attributes spanAttributes = spanData.getAttributes();
TransactionNameResult transactionNameResult = runtimeNameGenerator.generateName(spanData);

String customName = CustomTransactionNameDict.get(traceId);
if (customName != null) {
logger.trace(String.format("Using custom transaction name -> %s", customName));
return customName;
if (transactionNameResult.name != null) {
logger.trace(String.format("Using custom transaction name -> %s", transactionNameResult));
return transactionNameResult;
}

String name = namingScheme.createName(spanAttributes);
if (name != null && !name.isEmpty()) {
logger.trace(String.format("Using scheme derived transaction name -> %s", name));
return name;
return new TransactionNameResult(name, false);
}

String path = spanAttributes.get(SemanticAttributes.URL_PATH);
Expand All @@ -203,14 +208,14 @@ static String buildTransactionName(String traceId, String spanName, Attributes s
String handlerName = spanAttributes.get(AttributeKey.stringKey("HandlerName"));
if (handlerName != null) {
logger.trace(String.format("Using HandlerName(%s) as the transaction name", handlerName));
return handlerName;
return new TransactionNameResult(handlerName, false);
}

// use "http.route"
String httpRoute = spanAttributes.get(SemanticAttributes.HTTP_ROUTE);
if (httpRoute != null) {
logger.trace(String.format("Using http.route (%s) as the transaction name", httpRoute));
return httpRoute;
return new TransactionNameResult(httpRoute, false);
}

// get transaction name from url
Expand All @@ -225,7 +230,7 @@ static String buildTransactionName(String traceId, String spanName, Attributes s
String.format(
"Using custom configure pattern to extract transaction name: (%s)",
transactionName));
return transactionName;
return new TransactionNameResult(transactionName, false);
}
}

Expand All @@ -240,11 +245,12 @@ static String buildTransactionName(String traceId, String spanName, Attributes s
logger.trace(
String.format(
"Using token name pattern to extract transaction name: (%s)", transactionNameByUrl));
return transactionNameByUrl;
return new TransactionNameResult(transactionNameByUrl, false);
}

String spanName = spanData.getName();
logger.trace(String.format("Using span name as the transaction name: (%s)", spanName));
return spanName;
return new TransactionNameResult(spanName, false);
}

/**
Expand Down Expand Up @@ -357,4 +363,16 @@ static void reset() {
URL_TRANSACTION_NAME_CACHE.invalidateAll();
maxNameCount = DEFAULT_MAX_NAME_COUNT;
}

@Value
@RequiredArgsConstructor
public static class TransactionNameResult {
String name;
boolean lambda;
}

@FunctionalInterface
public interface RuntimeNameGenerator {
TransactionNameResult generateName(SpanData spanData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private void reportMetrics(SpanData spanData) {
final Map<String, String> swoTags =
new HashMap<String, String>() {
{
put("sw.transaction", transactionName);
put(SharedNames.TRANSACTION_NAME_KEY, transactionName);
}
};

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public SdkTracerProviderBuilder apply(
if (isAgentEnabled()) {
tracerProvider
.setSampler(new SolarwindsSampler())
.addSpanProcessor(new SolarwindsRootSpanProcessor())
.addSpanProcessor(new SolarwindsProfilingSpanProcessor())
.addSpanProcessor(new SolarwindsInboundMetricsSpanProcessor());
}
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion smoke-tests/spring-boot-webmvc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ version = "0.0.1-SNAPSHOT"


repositories {
mavenCentral()
mavenCentral()
}

dependencies {
Expand Down
3 changes: 2 additions & 1 deletion solarwinds-otel-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ dependencies {

compileOnly("io.opentelemetry:opentelemetry-api:${versions.opentelemetry}")
compileOnly("io.opentelemetry:opentelemetry-context:${versions.opentelemetry}")

compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap:${versions.opentelemetryJavaagentAlpha}")

compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:${versions.opentelemetryJavaagent}")
compileOnly "com.solarwinds.joboe:core:${versions.joboe}"
compileOnly "com.solarwinds.joboe:metrics:${versions.joboe}"

Expand Down
Loading

0 comments on commit 48e0545

Please sign in to comment.