Skip to content

Commit e907455

Browse files
authored
Add ability to add additional context for appd integrations. (#2198)
* add ability to add additional context for appd integrations. * add span processor explicitly to tracer builder, instead of composing. * fix autoconfigured components * move constants closer to usage * don't inject if "none" propagator selected. * spotless * address code review comments * move constants out of single package file
1 parent ead0e74 commit e907455

File tree

9 files changed

+657
-0
lines changed

9 files changed

+657
-0
lines changed

custom/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ dependencies {
33
compileOnly("io.opentelemetry:opentelemetry-sdk")
44
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
55
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
6+
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator")
67
compileOnly("io.opentelemetry.semconv:opentelemetry-semconv")
78
compileOnly("io.opentelemetry.semconv:opentelemetry-semconv-incubating")
89
compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api")
@@ -20,6 +21,7 @@ dependencies {
2021
testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
2122
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
2223
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
24+
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator")
2325
testImplementation("io.opentelemetry.semconv:opentelemetry-semconv")
2426
testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api")
2527
testImplementation("io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api")
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright Splunk Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.splunk.opentelemetry.appd;
18+
19+
import javax.annotation.Nullable;
20+
21+
public class AppdBonusContext {
22+
@Nullable private final String appId;
23+
@Nullable private final String accountId;
24+
@Nullable private final String businessTransactionId;
25+
@Nullable private final String tierId;
26+
27+
public AppdBonusContext(
28+
@Nullable String accountId,
29+
@Nullable String appId,
30+
@Nullable String businessTransactionId,
31+
@Nullable String tierId) {
32+
this.accountId = accountId;
33+
this.appId = appId;
34+
this.businessTransactionId = businessTransactionId;
35+
this.tierId = tierId;
36+
}
37+
38+
@Nullable
39+
public String getAccountId() {
40+
return accountId;
41+
}
42+
43+
@Nullable
44+
public String getAppId() {
45+
return appId;
46+
}
47+
48+
@Nullable
49+
public String getBusinessTransactionId() {
50+
return businessTransactionId;
51+
}
52+
53+
@Nullable
54+
public String getTierId() {
55+
return tierId;
56+
}
57+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright Splunk Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.splunk.opentelemetry.appd;
18+
19+
import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME;
20+
import static io.opentelemetry.semconv.incubating.DeploymentIncubatingAttributes.DEPLOYMENT_ENVIRONMENT_NAME;
21+
22+
import com.google.auto.service.AutoService;
23+
import com.google.common.annotations.VisibleForTesting;
24+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
25+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
26+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
27+
import io.opentelemetry.sdk.extension.incubator.trace.OnStartSpanProcessor;
28+
import io.opentelemetry.sdk.trace.SpanProcessor;
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
31+
import java.util.Collections;
32+
import java.util.HashMap;
33+
import java.util.List;
34+
import java.util.Map;
35+
36+
@AutoService(AutoConfigurationCustomizerProvider.class)
37+
public final class AppdBonusCustomizer implements AutoConfigurationCustomizerProvider {
38+
39+
private static final String CONFIG_CISCO_CTX_ENABLED = "cisco.ctx.enabled";
40+
41+
static final List<String> DEFAULT_PROPAGATORS = Arrays.asList("tracecontext", "baggage");
42+
43+
@Override
44+
public void customize(AutoConfigurationCustomizer customizer) {
45+
customize(customizer, AppdBonusPropagator.getInstance());
46+
}
47+
48+
@VisibleForTesting
49+
void customize(AutoConfigurationCustomizer customizer, AppdBonusPropagator propagator) {
50+
customizer.addPropertiesCustomizer(this::customizeProperties);
51+
52+
customizer.addTracerProviderCustomizer(
53+
(builder, config) -> {
54+
if (featureEnabled(config)) {
55+
SpanProcessor processor = OnStartSpanProcessor.create(new AppdBonusSpanProcessor());
56+
return builder.addSpanProcessor(processor);
57+
}
58+
return builder;
59+
});
60+
customizer.addResourceCustomizer(
61+
(resource, configProperties) -> {
62+
propagator.setEnvironmentName(resource.getAttribute(DEPLOYMENT_ENVIRONMENT_NAME));
63+
propagator.setServiceName(resource.getAttribute(SERVICE_NAME));
64+
return resource;
65+
});
66+
}
67+
68+
private static boolean featureEnabled(ConfigProperties config) {
69+
return config.getBoolean(CONFIG_CISCO_CTX_ENABLED, false)
70+
&& !config.getList("otel.propagators", DEFAULT_PROPAGATORS).contains("none");
71+
}
72+
73+
/** Used to add the AppD propagator name to the otel.propagators list if configured. */
74+
private Map<String, String> customizeProperties(ConfigProperties config) {
75+
if (!config.getBoolean(CONFIG_CISCO_CTX_ENABLED, false)) {
76+
return Collections.emptyMap();
77+
}
78+
List<String> existing = config.getList("otel.propagators", DEFAULT_PROPAGATORS);
79+
if (existing.contains(AppdBonusPropagator.NAME) || existing.contains("none")) {
80+
return Collections.emptyMap();
81+
}
82+
List<String> propagators = new ArrayList<>(existing);
83+
propagators.add(AppdBonusPropagator.NAME);
84+
Map<String, String> customized = new HashMap<>();
85+
customized.put("otel.propagators", String.join(",", propagators));
86+
return customized;
87+
}
88+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright Splunk Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.splunk.opentelemetry.appd;
18+
19+
import io.opentelemetry.context.Context;
20+
import io.opentelemetry.context.ContextKey;
21+
import io.opentelemetry.context.propagation.TextMapGetter;
22+
import io.opentelemetry.context.propagation.TextMapPropagator;
23+
import io.opentelemetry.context.propagation.TextMapSetter;
24+
import java.util.Arrays;
25+
import java.util.Collection;
26+
import java.util.List;
27+
import javax.annotation.Nullable;
28+
29+
final class AppdBonusPropagator implements TextMapPropagator {
30+
31+
static final String NAME = "appd-bonus";
32+
static final String CTX_KEY = "cisco-bonus-ctx";
33+
static final String CTX_HEADER_ENV = "cisco-ctx-env";
34+
static final String CTX_HEADER_SERVICE = "cisco-ctx-service";
35+
36+
static final String CTX_HEADER_ACCT = "cisco-ctx-acct-id";
37+
static final String CTX_HEADER_APP = "cisco-ctx-app-id";
38+
static final String CTX_HEADER_BT = "cisco-ctx-bt-id";
39+
static final String CTX_HEADER_TIER = "cisco-ctx-tier-id";
40+
private static final List<String> FIELDS =
41+
Arrays.asList(
42+
CTX_HEADER_ACCT,
43+
CTX_HEADER_APP,
44+
CTX_HEADER_BT,
45+
CTX_HEADER_TIER,
46+
CTX_HEADER_ENV,
47+
CTX_HEADER_SERVICE);
48+
49+
public static final ContextKey<AppdBonusContext> CONTEXT_KEY = ContextKey.named(CTX_KEY);
50+
private static final AppdBonusPropagator INSTANCE = new AppdBonusPropagator();
51+
52+
@Nullable private String serviceName;
53+
@Nullable private String environmentName;
54+
55+
private AppdBonusPropagator() {}
56+
57+
static AppdBonusPropagator getInstance() {
58+
return INSTANCE;
59+
}
60+
61+
@Override
62+
public Collection<String> fields() {
63+
return FIELDS;
64+
}
65+
66+
@Override
67+
public <C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter) {
68+
if (environmentName != null) {
69+
setter.set(carrier, CTX_HEADER_ENV, environmentName);
70+
}
71+
if (serviceName != null) {
72+
setter.set(carrier, CTX_HEADER_SERVICE, serviceName);
73+
}
74+
}
75+
76+
@Override
77+
public <C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> getter) {
78+
String account = getter.get(carrier, CTX_HEADER_ACCT);
79+
String app = getter.get(carrier, CTX_HEADER_APP);
80+
String bt = getter.get(carrier, CTX_HEADER_BT);
81+
String tier = getter.get(carrier, CTX_HEADER_TIER);
82+
AppdBonusContext appdContext = new AppdBonusContext(account, app, bt, tier);
83+
return context.with(CONTEXT_KEY, appdContext);
84+
}
85+
86+
public void setServiceName(String serviceName) {
87+
this.serviceName = serviceName;
88+
}
89+
90+
public void setEnvironmentName(String environmentName) {
91+
this.environmentName = environmentName;
92+
}
93+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright Splunk Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.splunk.opentelemetry.appd;
18+
19+
import com.google.auto.service.AutoService;
20+
import io.opentelemetry.context.propagation.TextMapPropagator;
21+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
22+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider;
23+
24+
@AutoService(ConfigurablePropagatorProvider.class)
25+
public class AppdBonusPropagatorProvider implements ConfigurablePropagatorProvider {
26+
27+
@Override
28+
public TextMapPropagator getPropagator(ConfigProperties config) {
29+
return AppdBonusPropagator.getInstance();
30+
}
31+
32+
@Override
33+
public String getName() {
34+
return AppdBonusPropagator.NAME;
35+
}
36+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Splunk Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.splunk.opentelemetry.appd;
18+
19+
import static com.splunk.opentelemetry.appd.AppdBonusPropagator.CONTEXT_KEY;
20+
import static io.opentelemetry.api.common.AttributeKey.stringKey;
21+
22+
import io.opentelemetry.api.common.AttributeKey;
23+
import io.opentelemetry.context.Context;
24+
import io.opentelemetry.sdk.extension.incubator.trace.OnStartSpanProcessor;
25+
import io.opentelemetry.sdk.trace.ReadWriteSpan;
26+
27+
public class AppdBonusSpanProcessor implements OnStartSpanProcessor.OnStart {
28+
29+
static final AttributeKey<String> APPD_ATTR_ACCT = stringKey("appd.upstream.account.id");
30+
static final AttributeKey<String> APPD_ATTR_APP = stringKey("appd.upstream.app.id");
31+
static final AttributeKey<String> APPD_ATTR_BT = stringKey("appd.upstream.bt.id");
32+
static final AttributeKey<String> APPD_ATTR_TIER = stringKey("appd.upstream.tier.id");
33+
34+
@Override
35+
public void apply(Context context, ReadWriteSpan span) {
36+
AppdBonusContext ctx = context.get(CONTEXT_KEY);
37+
if (ctx == null) {
38+
return;
39+
}
40+
if (ctx.getAccountId() != null) {
41+
span.setAttribute(APPD_ATTR_ACCT, ctx.getAccountId());
42+
}
43+
if (ctx.getAppId() != null) {
44+
span.setAttribute(APPD_ATTR_APP, ctx.getAppId());
45+
}
46+
if (ctx.getBusinessTransactionId() != null) {
47+
span.setAttribute(APPD_ATTR_BT, ctx.getBusinessTransactionId());
48+
}
49+
if (ctx.getTierId() != null) {
50+
span.setAttribute(APPD_ATTR_TIER, ctx.getTierId());
51+
}
52+
}
53+
}

0 commit comments

Comments
 (0)