Skip to content

Commit 21795b3

Browse files
amarzialidevflow.devflow-routing-intake
andauthored
Add service name source to trace stats (#10653)
Add service name source to stats Add tests and move postprocessors later Finalize implementation Fix agent integration tests Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
1 parent 20abae4 commit 21795b3

File tree

11 files changed

+232
-83
lines changed

11 files changed

+232
-83
lines changed

dd-trace-core/src/main/java/datadog/trace/common/metrics/ConflatingMetricsAggregator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ private boolean publish(CoreSpan<?> span, boolean isTopLevel, CharSequence spanK
331331
span.getResourceName(),
332332
SERVICE_NAMES.computeIfAbsent(span.getServiceName(), UTF8_ENCODE),
333333
span.getOperationName(),
334+
span.getServiceNameSource(),
334335
span.getType(),
335336
span.getHttpStatusCode(),
336337
isSynthetic(span),

dd-trace-core/src/main/java/datadog/trace/common/metrics/MetricKey.java

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
66
import java.util.Collections;
77
import java.util.List;
8+
import java.util.Objects;
89

910
/** The aggregation key for tracked metrics. */
1011
public final class MetricKey {
1112
private final UTF8BytesString resource;
1213
private final UTF8BytesString service;
14+
private final UTF8BytesString serviceSource;
1315
private final UTF8BytesString operationName;
1416
private final UTF8BytesString type;
1517
private final int httpStatusCode;
@@ -21,35 +23,11 @@ public final class MetricKey {
2123
private final UTF8BytesString httpMethod;
2224
private final UTF8BytesString httpEndpoint;
2325

24-
// Constructor without httpMethod and httpEndpoint for backward compatibility
25-
public MetricKey(
26-
CharSequence resource,
27-
CharSequence service,
28-
CharSequence operationName,
29-
CharSequence type,
30-
int httpStatusCode,
31-
boolean synthetics,
32-
boolean isTraceRoot,
33-
CharSequence spanKind,
34-
List<UTF8BytesString> peerTags) {
35-
this(
36-
resource,
37-
service,
38-
operationName,
39-
type,
40-
httpStatusCode,
41-
synthetics,
42-
isTraceRoot,
43-
spanKind,
44-
peerTags,
45-
null,
46-
null);
47-
}
48-
4926
public MetricKey(
5027
CharSequence resource,
5128
CharSequence service,
5229
CharSequence operationName,
30+
CharSequence serviceSource,
5331
CharSequence type,
5432
int httpStatusCode,
5533
boolean synthetics,
@@ -60,6 +38,7 @@ public MetricKey(
6038
CharSequence httpEndpoint) {
6139
this.resource = null == resource ? EMPTY : UTF8BytesString.create(resource);
6240
this.service = null == service ? EMPTY : UTF8BytesString.create(service);
41+
this.serviceSource = null == serviceSource ? null : UTF8BytesString.create(serviceSource);
6342
this.operationName = null == operationName ? EMPTY : UTF8BytesString.create(operationName);
6443
this.type = null == type ? EMPTY : UTF8BytesString.create(type);
6544
this.httpStatusCode = httpStatusCode;
@@ -79,18 +58,34 @@ public MetricKey(
7958

8059
// Only include httpMethod and httpEndpoint in hash if they are not null
8160
// This ensures backward compatibility when the feature is disabled
82-
this.hash =
83-
-196_513_505 * Boolean.hashCode(this.isTraceRoot)
84-
+ -1_807_454_463 * this.spanKind.hashCode()
85-
+ 887_503_681 * this.peerTags.hashCode()
86-
+ (this.httpMethod != null ? 28_629_151 * this.httpMethod.hashCode() : 0)
87-
+ (this.httpEndpoint != null ? 923_521 * this.httpEndpoint.hashCode() : 0)
88-
+ 29_791 * this.resource.hashCode()
89-
+ 961 * this.service.hashCode()
90-
+ 31 * this.operationName.hashCode()
91-
+ this.type.hashCode()
92-
+ 31 * httpStatusCode
93-
+ (this.synthetics ? 1 : 0);
61+
62+
// Note: all the multiplication got constant folded at compile time (see javap -verbose ...)
63+
int tmpHash =
64+
(int) (31L * 31 * 31 * 31 * 31 * 31 * 31 * 31) * Boolean.hashCode(this.isTraceRoot) // 8
65+
+ (int) (31L * 31 * 31 * 31 * 31 * 31 * 31) * this.spanKind.hashCode() // 7
66+
+ 31 * 31 * 31 * 31 * 31 * 31 * this.peerTags.hashCode() // 6
67+
+ 31 * 31 * 31 * 31 * 31 * this.resource.hashCode() // 5
68+
+ 31 * 31 * 31 * 31 * this.service.hashCode() // 4
69+
+ 31 * 31 * 31 * this.operationName.hashCode() // 3
70+
+ 31 * 31 * this.type.hashCode() // 2
71+
+ 31 * this.httpStatusCode // 1
72+
+ (this.synthetics ? 1 : 0); // 0
73+
// optional fields
74+
if (this.serviceSource != null) {
75+
tmpHash +=
76+
(int) (31L * 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31) * this.serviceSource.hashCode(); // 9
77+
}
78+
if (this.httpEndpoint != null) {
79+
tmpHash +=
80+
(int) (31L * 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31)
81+
* this.httpEndpoint.hashCode(); // 10
82+
}
83+
if (this.httpMethod != null) {
84+
tmpHash +=
85+
(int) (31L * 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31 * 31)
86+
* this.httpMethod.hashCode(); // 11
87+
}
88+
this.hash = tmpHash;
9489
}
9590

9691
public UTF8BytesString getResource() {
@@ -101,6 +96,10 @@ public UTF8BytesString getService() {
10196
return service;
10297
}
10398

99+
public UTF8BytesString getServiceSource() {
100+
return serviceSource;
101+
}
102+
104103
public UTF8BytesString getOperationName() {
105104
return operationName;
106105
}
@@ -144,29 +143,19 @@ public boolean equals(Object o) {
144143
}
145144
if ((o instanceof MetricKey)) {
146145
MetricKey metricKey = (MetricKey) o;
147-
boolean basicEquals =
148-
hash == metricKey.hash
149-
&& synthetics == metricKey.synthetics
150-
&& httpStatusCode == metricKey.httpStatusCode
151-
&& resource.equals(metricKey.resource)
152-
&& service.equals(metricKey.service)
153-
&& operationName.equals(metricKey.operationName)
154-
&& type.equals(metricKey.type)
155-
&& isTraceRoot == metricKey.isTraceRoot
156-
&& spanKind.equals(metricKey.spanKind)
157-
&& peerTags.equals(metricKey.peerTags);
158-
159-
// Only compare httpMethod and httpEndpoint if at least one of them is not null
160-
// This ensures backward compatibility when the feature is disabled
161-
boolean thisHasEndpoint = httpMethod != null || httpEndpoint != null;
162-
boolean otherHasEndpoint = metricKey.httpMethod != null || metricKey.httpEndpoint != null;
163-
164-
if (thisHasEndpoint || otherHasEndpoint) {
165-
return basicEquals
166-
&& java.util.Objects.equals(httpMethod, metricKey.httpMethod)
167-
&& java.util.Objects.equals(httpEndpoint, metricKey.httpEndpoint);
168-
}
169-
return basicEquals;
146+
return hash == metricKey.hash
147+
&& synthetics == metricKey.synthetics
148+
&& httpStatusCode == metricKey.httpStatusCode
149+
&& resource.equals(metricKey.resource)
150+
&& service.equals(metricKey.service)
151+
&& operationName.equals(metricKey.operationName)
152+
&& type.equals(metricKey.type)
153+
&& isTraceRoot == metricKey.isTraceRoot
154+
&& spanKind.equals(metricKey.spanKind)
155+
&& peerTags.equals(metricKey.peerTags)
156+
&& Objects.equals(serviceSource, metricKey.serviceSource)
157+
&& Objects.equals(httpMethod, metricKey.httpMethod)
158+
&& Objects.equals(httpEndpoint, metricKey.httpEndpoint);
170159
}
171160
return false;
172161
}

dd-trace-core/src/main/java/datadog/trace/common/metrics/SerializingMetricWriter.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public final class SerializingMetricWriter implements MetricWriter {
3737
private static final byte[] PEER_TAGS = "PeerTags".getBytes(ISO_8859_1);
3838
private static final byte[] HTTP_METHOD = "HTTPMethod".getBytes(ISO_8859_1);
3939
private static final byte[] HTTP_ENDPOINT = "HTTPEndpoint".getBytes(ISO_8859_1);
40+
private static final byte[] SERVICE_SOURCE = "srv_src".getBytes(ISO_8859_1);
4041

4142
// Constant declared here for compile-time folding
4243
public static final int TRISTATE_TRUE = TriState.TRUE.serialValue;
@@ -109,7 +110,9 @@ public void add(MetricKey key, AggregateMetric aggregate) {
109110
// Calculate dynamic map size based on optional fields
110111
final boolean hasHttpMethod = key.getHttpMethod() != null;
111112
final boolean hasHttpEndpoint = key.getHttpEndpoint() != null;
112-
final int mapSize = 15 + (hasHttpMethod ? 1 : 0) + (hasHttpEndpoint ? 1 : 0);
113+
final boolean hasServiceSource = key.getServiceSource() != null;
114+
final int mapSize =
115+
15 + (hasServiceSource ? 1 : 0) + (hasHttpMethod ? 1 : 0) + (hasHttpEndpoint ? 1 : 0);
113116

114117
writer.startMap(mapSize);
115118

@@ -145,6 +148,10 @@ public void add(MetricKey key, AggregateMetric aggregate) {
145148
writer.writeUTF8(peerTag);
146149
}
147150

151+
if (hasServiceSource) {
152+
writer.writeUTF8(SERVICE_SOURCE);
153+
writer.writeUTF8(key.getServiceSource());
154+
}
148155
// Only include HTTPMethod if present
149156
if (hasHttpMethod) {
150157
writer.writeUTF8(HTTP_METHOD);

dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ public interface CoreSpan<T extends CoreSpan<T>> {
99

1010
String getServiceName();
1111

12+
default CharSequence getServiceNameSource() {
13+
return null;
14+
}
15+
1216
CharSequence getOperationName();
1317

1418
CharSequence getResourceName();

dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,11 @@ public void setServiceName(@Nonnull String serviceName, @Nonnull CharSequence so
590590
context.setServiceName(serviceName, source);
591591
}
592592

593+
@Override
594+
public CharSequence getServiceNameSource() {
595+
return context.getServiceNameSource();
596+
}
597+
593598
@Override
594599
public final DDSpan setResourceName(final CharSequence resourceName) {
595600
return setResourceName(resourceName, ResourceNamePriorities.DEFAULT);

dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ private static class Lazy {
1313
private static TagsPostProcessor lazyProcessor = createLazyChain();
1414

1515
private static TagsPostProcessor createEagerChain() {
16-
final List<TagsPostProcessor> processors = new ArrayList<>(4);
16+
final List<TagsPostProcessor> processors = new ArrayList<>(3);
1717
processors.add(new PeerServiceCalculator());
1818
if (addBaseService) {
1919
processors.add(new BaseServiceAdder(Config.get().getServiceName()));
@@ -23,12 +23,11 @@ private static TagsPostProcessor createEagerChain() {
2323
if (Config.get().isTraceResourceRenamingEnabled()) {
2424
processors.add(new HttpEndpointPostProcessor());
2525
}
26-
processors.add(new ServiceNameSourceAdder()); // eager since needed for stats
2726
return new PostProcessorChain(processors.toArray(new TagsPostProcessor[0]));
2827
}
2928

3029
private static TagsPostProcessor createLazyChain() {
31-
final List<TagsPostProcessor> processors = new ArrayList<>(7);
30+
final List<TagsPostProcessor> processors = new ArrayList<>(8);
3231

3332
processors.add(new QueryObfuscator(Config.get().getObfuscationQueryRegexp()));
3433
if (addRemoteHostname) {
@@ -48,6 +47,7 @@ private static TagsPostProcessor createLazyChain() {
4847
processors.add(new SpanPointersProcessor());
4948
}
5049
processors.add(new IntegrationAdder());
50+
processors.add(new ServiceNameSourceAdder());
5151
return new PostProcessorChain(
5252
processors.toArray(processors.toArray(new TagsPostProcessor[0])));
5353
}

dd-trace-core/src/test/groovy/datadog/trace/common/metrics/AggregateMetricTest.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class AggregateMetricTest extends DDSpecification {
6565
given:
6666
AggregateMetric aggregate = new AggregateMetric().recordDurations(3, new AtomicLongArray(0L, 0L, 0L | ERROR_TAG | TOP_LEVEL_TAG))
6767

68-
Batch batch = new Batch().reset(new MetricKey("foo", "bar", "qux", "type", 0, false, true, "corge", [UTF8BytesString.create("grault:quux")], null, null))
68+
Batch batch = new Batch().reset(new MetricKey("foo", "bar", "qux", null, "type", 0, false, true, "corge", [UTF8BytesString.create("grault:quux")], null, null))
6969
batch.add(0L, 10)
7070
batch.add(0L, 10)
7171
batch.add(0L, 10)
@@ -140,7 +140,7 @@ class AggregateMetricTest extends DDSpecification {
140140
def "consistent under concurrent attempts to read and write"() {
141141
given:
142142
AggregateMetric aggregate = new AggregateMetric()
143-
MetricKey key = new MetricKey("foo", "bar", "qux", "type", 0, false, true, "corge", [UTF8BytesString.create("grault:quux")], null, null)
143+
MetricKey key = new MetricKey("foo", "bar", "qux", null, "type", 0, false, true, "corge", [UTF8BytesString.create("grault:quux")], null, null)
144144
BlockingDeque<Batch> queue = new LinkedBlockingDeque<>(1000)
145145
ExecutorService reader = Executors.newSingleThreadExecutor()
146146
int writerCount = 10

0 commit comments

Comments
 (0)