Skip to content
Draft

init #11719

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ final class AggregateEntry extends Hashtable.Entry {
DDCaches.newFixedSizeCache(32);
private static final DDCache<String, UTF8BytesString> GRPC_STATUS_CODE_CACHE =
DDCaches.newFixedSizeCache(32);
// Origin is a small fixed vocabulary (synthetics, synthetics-browser, rum, ciapp-test, lambda).
private static final DDCache<String, UTF8BytesString> ORIGIN_CACHE =
DDCaches.newFixedSizeCache(8);

/**
* Outer cache keyed by peer-tag name, with an inner per-name cache keyed by value. The inner
Expand Down Expand Up @@ -108,8 +111,13 @@ final class AggregateEntry extends Hashtable.Entry {
@Nullable private final UTF8BytesString grpcStatusCode;
private final short httpStatusCode;

/** Whether the root span carried the {@code synthetics} origin tag (synthetic-monitoring run). */
private final boolean synthetic;
/**
* Trace origin (e.g. {@code synthetics}, {@code rum}, {@code ciapp-test}, {@code lambda}), or
* {@code null} when the root span carried no origin. Part of the bucket key, so spans with
* distinct origins aggregate separately. The OTLP export emits this as {@code datadog.origin};
* the native msgpack path reads {@link #isSynthetics()}, derived from it.
*/
@Nullable private final UTF8BytesString origin;

/** Whether this span is the trace root ({@code parentId == 0}). */
private final boolean traceRoot;
Expand Down Expand Up @@ -139,7 +147,8 @@ final class AggregateEntry extends Hashtable.Entry {
private int errorCount;
private int hitCount;
private int topLevelCount;
private long duration;
private long okDuration;
private long errorDuration;

/** Hot-path constructor for the producer/consumer flow. Builds UTF8 fields via the caches. */
AggregateEntry(SpanSnapshot s, long keyHash) {
Expand All @@ -154,7 +163,7 @@ final class AggregateEntry extends Hashtable.Entry {
this.httpEndpoint = canonicalizeOptional(HTTP_ENDPOINT_CACHE, s.httpEndpoint);
this.grpcStatusCode = canonicalizeOptional(GRPC_STATUS_CODE_CACHE, s.grpcStatusCode);
this.httpStatusCode = s.httpStatusCode;
this.synthetic = s.synthetic;
this.origin = canonicalizeOptional(ORIGIN_CACHE, s.origin);
this.traceRoot = s.traceRoot;
this.peerTagNames = s.peerTagSchema == null ? null : s.peerTagSchema.names;
this.peerTagValues = s.peerTagValues;
Expand All @@ -174,11 +183,12 @@ void recordOneDuration(long tagAndDuration) {
if ((tagAndDuration & ERROR_TAG) == ERROR_TAG) {
tagAndDuration ^= ERROR_TAG;
errorLatenciesForWrite().accept(tagAndDuration);
errorDuration += tagAndDuration;
++errorCount;
} else {
okLatencies.accept(tagAndDuration);
okDuration += tagAndDuration;
}
duration += tagAndDuration;
}

int getErrorCount() {
Expand All @@ -194,7 +204,15 @@ int getTopLevelCount() {
}

long getDuration() {
return duration;
return okDuration + errorDuration;
}

long getOkDuration() {
return okDuration;
}

long getErrorDuration() {
return errorDuration;
}

Histogram getOkLatencies() {
Expand Down Expand Up @@ -232,7 +250,8 @@ void clear() {
this.errorCount = 0;
this.hitCount = 0;
this.topLevelCount = 0;
this.duration = 0;
this.okDuration = 0;
this.errorDuration = 0;
this.okLatencies.clear();
// errorLatencies stays null on entries that never errored. Only clear if it was allocated.
if (this.errorLatencies != null) {
Expand All @@ -243,7 +262,7 @@ void clear() {
boolean matches(SpanSnapshot s) {
String[] snapshotNames = s.peerTagSchema == null ? null : s.peerTagSchema.names;
return httpStatusCode == s.httpStatusCode
&& synthetic == s.synthetic
&& contentEquals(origin, s.origin)
&& traceRoot == s.traceRoot
&& contentEquals(resource, s.resourceName)
&& contentEquals(service, s.serviceName)
Expand Down Expand Up @@ -284,7 +303,7 @@ static long hashOf(SpanSnapshot s) {
h = LongHashingUtils.addToHash(h, s.serviceNameSource);
h = LongHashingUtils.addToHash(h, s.spanType);
h = LongHashingUtils.addToHash(h, s.httpStatusCode);
h = LongHashingUtils.addToHash(h, s.synthetic);
h = LongHashingUtils.addToHash(h, s.origin);
h = LongHashingUtils.addToHash(h, s.traceRoot);
h = LongHashingUtils.addToHash(h, s.spanKind);
// Always mix in both the schema's content hash and the values' content hash, unconditionally
Expand Down Expand Up @@ -352,8 +371,21 @@ int getHttpStatusCode() {
return httpStatusCode;
}

/**
* The full trace origin, or {@code null} when unset. Used by {@link OtlpStatsMetricWriter} to
* emit {@code datadog.origin}.
*/
@Nullable
UTF8BytesString getOrigin() {
return origin;
}

/**
* Whether the origin is {@code synthetics}. Derived from {@link #origin} for the native msgpack
* writer, which emits a synthetics boolean rather than the full origin.
*/
boolean isSynthetics() {
return synthetic;
return origin != null && "synthetics".contentEquals(origin);
}

boolean isTraceRoot() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ public final class ConflatingMetricsAggregator implements MetricsAggregator, Eve
private static final Map<String, String> DEFAULT_HEADERS =
Collections.singletonMap(DDAgentApi.DATADOG_META_TRACER_VERSION, DDTraceCoreInfo.VERSION);

private static final CharSequence SYNTHETICS_ORIGIN = "synthetics";

private static final SpanKindFilter METRICS_ELIGIBLE_KINDS =
SpanKindFilter.builder()
.includeServer()
Expand Down Expand Up @@ -346,7 +344,7 @@ private boolean publish(CoreSpan<?> span, boolean isTopLevel) {
span.getServiceNameSource(),
spanType,
span.getHttpStatusCode(),
isSynthetic(span),
span.getOrigin(),
span.getParentId() == 0,
spanKind,
peerTagSchema,
Expand Down Expand Up @@ -466,10 +464,6 @@ private static String[] capturePeerTagValues(CoreSpan<?> span, PeerTagSchema sch
return values;
}

private static boolean isSynthetic(CoreSpan<?> span) {
return span.getOrigin() != null && SYNTHETICS_ORIGIN.equals(span.getOrigin().toString());
}

public void stop() {
if (null != cancellation) {
cancellation.cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ final class SpanSnapshot implements InboxItem {
final CharSequence serviceNameSource;
final CharSequence spanType;
final short httpStatusCode;
final boolean synthetic;

/**
* Trace origin (e.g. {@code synthetics}, {@code synthetics-browser}, {@code rum}, {@code
* ciapp-test}, {@code lambda}), or {@code null} when the root span carried no origin. Captured in
* full -- rather than collapsed to a synthetics flag -- so the OTLP export can emit {@code
* datadog.origin} with the recognized value; the native msgpack path derives its synthetics
* boolean from it via {@link AggregateEntry#isSynthetics()}.
*/
final CharSequence origin;

final boolean traceRoot;
final String spanKind;

Expand Down Expand Up @@ -48,7 +57,7 @@ final class SpanSnapshot implements InboxItem {
CharSequence serviceNameSource,
CharSequence spanType,
short httpStatusCode,
boolean synthetic,
CharSequence origin,
boolean traceRoot,
String spanKind,
PeerTagSchema peerTagSchema,
Expand All @@ -63,7 +72,7 @@ final class SpanSnapshot implements InboxItem {
this.serviceNameSource = serviceNameSource;
this.spanType = spanType;
this.httpStatusCode = httpStatusCode;
this.synthetic = synthetic;
this.origin = origin;
this.traceRoot = traceRoot;
this.spanKind = spanKind;
this.peerTagSchema = peerTagSchema;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private static SpanSnapshot snapshotWithPeerTags(String[] names, String[] values
null,
"type",
(short) 200,
false,
null,
true,
"client",
PeerTagSchema.testSchema(names),
Expand All @@ -151,7 +151,7 @@ private static AggregateEntry newEntry() {
null,
"type",
(short) 200,
false,
null,
true,
"client",
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ public static AggregateEntry of(
serviceSource,
type,
(short) httpStatusCode,
synthetic,
// The legacy boolean maps onto the full origin field: true => "synthetics", false =>
// no origin. Tests needing a non-synthetics origin use ofOrigin(...).
synthetic ? "synthetics" : null,
traceRoot,
spanKind == null ? null : spanKind.toString(),
schema,
Expand All @@ -88,6 +90,38 @@ public static AggregateEntry of(
return forSnapshot(syntheticSnapshot);
}

/**
* Builds a minimal {@link AggregateEntry} carrying an explicit trace {@code origin} (e.g. {@code
* rum}, {@code ciapp-test}, {@code lambda}). A trace-root server entry with no HTTP/RPC/peer-tag
* fields; durations are recorded by the caller.
*/
public static AggregateEntry ofOrigin(
CharSequence resource,
CharSequence service,
CharSequence operationName,
CharSequence type,
CharSequence spanKind,
@Nullable CharSequence origin) {
SpanSnapshot snapshot =
new SpanSnapshot(
resource,
service == null ? null : service.toString(),
operationName,
null,
type,
(short) 0,
origin,
true,
spanKind == null ? null : spanKind.toString(),
null,
null,
null,
null,
null,
0L);
return forSnapshot(snapshot);
}

/**
* Builds an {@link AggregateEntry} from {@code s} by computing its lookup hash via {@link
* AggregateEntry#hashOf(SpanSnapshot)} and calling the package-private constructor directly.
Expand All @@ -106,7 +140,7 @@ public static boolean equals(AggregateEntry a, AggregateEntry b) {
if (a == b) return true;
if (a == null || b == null) return false;
return a.getHttpStatusCode() == b.getHttpStatusCode()
&& a.isSynthetics() == b.isSynthetics()
&& Objects.equals(a.getOrigin(), b.getOrigin())
&& a.isTraceRoot() == b.isTraceRoot()
&& Objects.equals(a.getResource(), b.getResource())
&& Objects.equals(a.getService(), b.getService())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ private static SpanSnapshot nullServiceKindSnapshot(String service, String spanK
null,
"web",
(short) 200,
false,
null,
true,
spanKind,
null,
Expand All @@ -294,7 +294,7 @@ private static SpanSnapshot nullableSnapshot(
serviceNameSource,
type,
(short) 200,
false,
null,
true,
"client",
null,
Expand Down Expand Up @@ -350,7 +350,7 @@ SpanSnapshot build() {
null,
"web",
(short) 200,
false,
null,
true,
spanKind,
peerTagSchema,
Expand Down
Loading