Skip to content

Commit 937ce11

Browse files
committed
Refactor AwsMetricAttributesSpanExporter to an onEnding processor
1 parent 423c87b commit 937ce11

File tree

9 files changed

+258
-687
lines changed

9 files changed

+258
-687
lines changed

appsignals-tests/contract-tests/src/test/java/software/amazon/opentelemetry/appsignals/test/httpservers/base/BaseHttpServerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
public abstract class BaseHttpServerTest extends ContractTestBase {
5353

5454
/**
55-
* Assert span attributes inserted by the AwsMetricAttributesSpanExporter
55+
* Assert span attributes inserted by the AwsAttributeGeneratingSpanProcessor
5656
*
5757
* @param resourceScopeSpans list of spans that were exported by the application
5858
* @param method the http method that was used (GET, PUT, DELETE...)

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsApplicationSignalsCustomizerProvider.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
* <li>Add SpanMetricsProcessor to create RED metrics.
7777
* <li>Add AttributePropagatingSpanProcessor to propagate span attributes from parent to child
7878
* spans.
79-
* <li>Add AwsMetricAttributesSpanExporter to add more attributes to all spans.
79+
* <li>Add AwsAttributeGeneratingSpanProcessor to add more attributes to all spans.
8080
* </ul>
8181
*
8282
* <p>You can control when these customizations are applied using the property
@@ -337,6 +337,9 @@ private SdkTracerProviderBuilder customizeTracerProviderBuilder(
337337
// Construct and set local and remote attributes span processor
338338
tracerProviderBuilder.addSpanProcessor(
339339
AttributePropagatingSpanProcessorBuilder.create().build());
340+
// Construct and set AWS Attribute Generating Span Processor
341+
tracerProviderBuilder.addSpanProcessor(
342+
AwsAttributeGeneratingSpanProcessorBuilder.create(ResourceHolder.getResource()).build());
340343

341344
// If running on Lambda, we just need to export 100% spans and skip generating any Application
342345
// Signals metrics.
@@ -351,16 +354,9 @@ private SdkTracerProviderBuilder customizeTracerProviderBuilder(
351354
.setEndpoint(tracesEndpoint)
352355
.build();
353356

354-
// Wrap the udp exporter with the AwsMetricsAttributesSpanExporter to add Application
355-
// Signals attributes to unsampled spans too
356-
SpanExporter appSignalsSpanExporter =
357-
AwsMetricAttributesSpanExporterBuilder.create(
358-
spanExporter, ResourceHolder.getResource())
359-
.build();
360-
361357
tracerProviderBuilder.addSpanProcessor(
362358
AwsUnsampledOnlySpanProcessorBuilder.create()
363-
.setSpanExporter(appSignalsSpanExporter)
359+
.setSpanExporter(spanExporter)
364360
.setMaxExportBatchSize(LAMBDA_SPAN_EXPORT_BATCH_SIZE)
365361
.build());
366362
return tracerProviderBuilder;
@@ -461,12 +457,6 @@ SpanExporter customizeSpanExporter(SpanExporter spanExporter, ConfigProperties c
461457
}
462458
}
463459

464-
if (isApplicationSignalsEnabled(configProps)) {
465-
spanExporter =
466-
AwsMetricAttributesSpanExporterBuilder.create(spanExporter, ResourceHolder.getResource())
467-
.build();
468-
}
469-
470460
if (this.sampler instanceof AwsXrayRemoteSampler) {
471461
((AwsXrayRemoteSampler) this.sampler).setSpanExporter(spanExporter);
472462
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates.
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+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.opentelemetry.javaagent.providers;
17+
18+
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_SPAN_KIND;
19+
20+
import io.opentelemetry.api.common.Attributes;
21+
import io.opentelemetry.context.Context;
22+
import io.opentelemetry.sdk.resources.Resource;
23+
import io.opentelemetry.sdk.trace.ReadWriteSpan;
24+
import io.opentelemetry.sdk.trace.ReadableSpan;
25+
import io.opentelemetry.sdk.trace.data.SpanData;
26+
import io.opentelemetry.sdk.trace.internal.ExtendedSpanProcessor;
27+
import java.util.Map;
28+
29+
public class AwsAttributeGeneratingSpanProcessor implements ExtendedSpanProcessor {
30+
31+
private final MetricAttributeGenerator generator;
32+
private final Resource resource;
33+
34+
public static AwsAttributeGeneratingSpanProcessor create(
35+
MetricAttributeGenerator generator, Resource resource) {
36+
return new AwsAttributeGeneratingSpanProcessor(generator, resource);
37+
}
38+
39+
private AwsAttributeGeneratingSpanProcessor(
40+
MetricAttributeGenerator generator, Resource resource) {
41+
this.generator = generator;
42+
this.resource = resource;
43+
}
44+
45+
@Override
46+
public void onStart(Context parentContext, ReadWriteSpan span) {}
47+
48+
@Override
49+
public boolean isStartRequired() {
50+
return false;
51+
}
52+
53+
@Override
54+
public void onEnding(ReadWriteSpan span) {
55+
// If the map has no items, no modifications are required. If there is one item, it means the
56+
// span either produces Service or Dependency metric attributes, and in either case we want to
57+
// modify the span with them. If there are two items, the span produces both Service and
58+
// Dependency metric attributes indicating the span is a local dependency root. The Service
59+
// Attributes must be a subset of the Dependency, with the exception of AWS_SPAN_KIND. The
60+
// knowledge that the span is a local root is more important than knowing that it is a
61+
// Dependency metric, so we take all the Dependency metrics but replace AWS_SPAN_KIND with
62+
// LOCAL_ROOT.
63+
SpanData spanData = span.toSpanData();
64+
Map<String, Attributes> attributeMap =
65+
generator.generateMetricAttributeMapFromSpan(span.toSpanData(), resource);
66+
67+
boolean generatesServiceMetrics =
68+
AwsSpanProcessingUtil.shouldGenerateServiceMetricAttributes(spanData);
69+
boolean generatesDependencyMetrics =
70+
AwsSpanProcessingUtil.shouldGenerateDependencyMetricAttributes(spanData);
71+
72+
if (generatesServiceMetrics && generatesDependencyMetrics) {
73+
// Order matters: dependency metric attributes include AWS_SPAN_KIND key
74+
span.setAllAttributes(attributeMap.get(MetricAttributeGenerator.DEPENDENCY_METRIC));
75+
span.setAttribute(AWS_SPAN_KIND, AwsSpanProcessingUtil.LOCAL_ROOT);
76+
} else if (generatesServiceMetrics) {
77+
span.setAllAttributes(attributeMap.get(MetricAttributeGenerator.SERVICE_METRIC));
78+
} else if (generatesDependencyMetrics) {
79+
span.setAllAttributes(attributeMap.get(MetricAttributeGenerator.DEPENDENCY_METRIC));
80+
}
81+
}
82+
83+
@Override
84+
public boolean isOnEndingRequired() {
85+
return true;
86+
}
87+
88+
@Override
89+
public void onEnd(ReadableSpan span) {}
90+
91+
@Override
92+
public boolean isEndRequired() {
93+
return false;
94+
}
95+
}
Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,40 @@
1919

2020
import com.google.errorprone.annotations.CanIgnoreReturnValue;
2121
import io.opentelemetry.sdk.resources.Resource;
22-
import io.opentelemetry.sdk.trace.export.SpanExporter;
2322

24-
public class AwsMetricAttributesSpanExporterBuilder {
23+
public class AwsAttributeGeneratingSpanProcessorBuilder {
2524

2625
// Defaults
2726
private static final MetricAttributeGenerator DEFAULT_GENERATOR =
2827
new AwsMetricAttributeGenerator();
2928

3029
// Required builder elements
31-
private final SpanExporter delegate;
3230
private final Resource resource;
3331

3432
// Optional builder elements
3533
private MetricAttributeGenerator generator = DEFAULT_GENERATOR;
3634

37-
public static AwsMetricAttributesSpanExporterBuilder create(
38-
SpanExporter delegate, Resource resource) {
39-
return new AwsMetricAttributesSpanExporterBuilder(delegate, resource);
35+
public static AwsAttributeGeneratingSpanProcessorBuilder create(Resource resource) {
36+
return new AwsAttributeGeneratingSpanProcessorBuilder(resource);
4037
}
4138

42-
private AwsMetricAttributesSpanExporterBuilder(SpanExporter delegate, Resource resource) {
43-
this.delegate = delegate;
39+
private AwsAttributeGeneratingSpanProcessorBuilder(Resource resource) {
4440
this.resource = resource;
4541
}
4642

4743
/**
48-
* Sets the generator used to generate attributes used spancs exported by the exporter. If unset,
44+
* Sets the generator used to generate attributes added to spans in the processor. If unset,
4945
* defaults to {@link #DEFAULT_GENERATOR}. Must not be null.
5046
*/
5147
@CanIgnoreReturnValue
52-
public AwsMetricAttributesSpanExporterBuilder setGenerator(MetricAttributeGenerator generator) {
48+
public AwsAttributeGeneratingSpanProcessorBuilder setGenerator(
49+
MetricAttributeGenerator generator) {
5350
requireNonNull(generator, "generator");
5451
this.generator = generator;
5552
return this;
5653
}
5754

58-
public AwsMetricAttributesSpanExporter build() {
59-
return AwsMetricAttributesSpanExporter.create(delegate, generator, resource);
55+
public AwsAttributeGeneratingSpanProcessor build() {
56+
return AwsAttributeGeneratingSpanProcessor.create(generator, resource);
6057
}
6158
}

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/AwsMetricAttributesSpanExporter.java

Lines changed: 0 additions & 169 deletions
This file was deleted.

awsagentprovider/src/main/java/software/amazon/opentelemetry/javaagent/providers/MetricAttributeGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
/**
2424
* Metric attribute generator defines an interface for classes that can generate specific attributes
2525
* to be used by an {@link AwsSpanMetricsProcessor} to produce metrics and by {@link
26-
* AwsMetricAttributesSpanExporter} to wrap the original span.
26+
* AwsAttributeGeneratingSpanProcessor} to update the original span.
2727
*/
2828
public interface MetricAttributeGenerator {
2929
static final String SERVICE_METRIC = "Service";

0 commit comments

Comments
 (0)