Skip to content

Commit bbaa9e5

Browse files
committed
Lazily evaluate ExceptionEventData exception.* attributes
1 parent 3c71b79 commit bbaa9e5

File tree

2 files changed

+103
-35
lines changed

2 files changed

+103
-35
lines changed

sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkSpan.java

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@
2020
import io.opentelemetry.sdk.internal.InstrumentationScopeUtil;
2121
import io.opentelemetry.sdk.resources.Resource;
2222
import io.opentelemetry.sdk.trace.data.EventData;
23-
import io.opentelemetry.sdk.trace.data.ExceptionEventData;
2423
import io.opentelemetry.sdk.trace.data.LinkData;
2524
import io.opentelemetry.sdk.trace.data.SpanData;
2625
import io.opentelemetry.sdk.trace.data.StatusData;
2726
import io.opentelemetry.sdk.trace.internal.ExtendedSpanProcessor;
28-
import java.io.PrintWriter;
29-
import java.io.StringWriter;
27+
import io.opentelemetry.sdk.trace.internal.data.LazyExceptionEventData;
3028
import java.util.ArrayList;
3129
import java.util.Collections;
3230
import java.util.List;
@@ -117,13 +115,6 @@ private enum EndState {
117115
@Nullable
118116
private Thread spanEndingThread;
119117

120-
private static final AttributeKey<String> EXCEPTION_TYPE =
121-
AttributeKey.stringKey("exception.type");
122-
private static final AttributeKey<String> EXCEPTION_MESSAGE =
123-
AttributeKey.stringKey("exception.message");
124-
private static final AttributeKey<String> EXCEPTION_STACKTRACE =
125-
AttributeKey.stringKey("exception.stacktrace");
126-
127118
private SdkSpan(
128119
SpanContext context,
129120
String name,
@@ -475,32 +466,9 @@ public ReadWriteSpan recordException(Throwable exception, Attributes additionalA
475466
additionalAttributes = Attributes.empty();
476467
}
477468

478-
AttributesMap attributes =
479-
AttributesMap.create(
480-
spanLimits.getMaxNumberOfAttributes(), spanLimits.getMaxAttributeValueLength());
481-
String exceptionName = exception.getClass().getCanonicalName();
482-
String exceptionMessage = exception.getMessage();
483-
StringWriter stringWriter = new StringWriter();
484-
try (PrintWriter printWriter = new PrintWriter(stringWriter)) {
485-
exception.printStackTrace(printWriter);
486-
}
487-
String stackTrace = stringWriter.toString();
488-
489-
if (exceptionName != null) {
490-
attributes.put(EXCEPTION_TYPE, exceptionName);
491-
}
492-
if (exceptionMessage != null) {
493-
attributes.put(EXCEPTION_MESSAGE, exceptionMessage);
494-
}
495-
if (stackTrace != null) {
496-
attributes.put(EXCEPTION_STACKTRACE, stackTrace);
497-
}
498-
499-
additionalAttributes.forEach(attributes::put);
500-
501469
addTimedEvent(
502-
ExceptionEventData.create(
503-
clock.now(), exception, attributes, attributes.getTotalAddedValues()));
470+
LazyExceptionEventData.create(clock.now(), exception, additionalAttributes, spanLimits));
471+
504472
return this;
505473
}
506474

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.sdk.trace.internal.data;
7+
8+
import com.google.auto.value.AutoValue;
9+
import com.google.auto.value.extension.memoized.Memoized;
10+
import io.opentelemetry.api.common.AttributeKey;
11+
import io.opentelemetry.api.common.Attributes;
12+
import io.opentelemetry.sdk.internal.AttributesMap;
13+
import io.opentelemetry.sdk.trace.SpanLimits;
14+
import io.opentelemetry.sdk.trace.data.ExceptionEventData;
15+
import java.io.PrintWriter;
16+
import java.io.StringWriter;
17+
import javax.annotation.concurrent.Immutable;
18+
19+
/**
20+
* An {@link ExceptionEventData} implementation with {@link #getAttributes()} lazily evaluated,
21+
* allowing the (relatively) expensive exception attribute rendering to take place off the hot path.
22+
*
23+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
24+
* at any time.
25+
*/
26+
@AutoValue
27+
@Immutable
28+
public abstract class LazyExceptionEventData implements ExceptionEventData {
29+
30+
private static final AttributeKey<String> EXCEPTION_TYPE =
31+
AttributeKey.stringKey("exception.type");
32+
private static final AttributeKey<String> EXCEPTION_MESSAGE =
33+
AttributeKey.stringKey("exception.message");
34+
private static final AttributeKey<String> EXCEPTION_STACKTRACE =
35+
AttributeKey.stringKey("exception.stacktrace");
36+
private static final String EXCEPTION_EVENT_NAME = "exception";
37+
38+
@Override
39+
public final String getName() {
40+
return EXCEPTION_EVENT_NAME;
41+
}
42+
43+
/** TODO. */
44+
public static ExceptionEventData create(
45+
long epochNanos,
46+
Throwable exception,
47+
Attributes additionalAttributes,
48+
SpanLimits spanLimits) {
49+
return new AutoValue_LazyExceptionEventData(
50+
epochNanos, exception, spanLimits, additionalAttributes);
51+
}
52+
53+
abstract SpanLimits getSpanLimits();
54+
55+
public abstract Attributes getAdditionalAttributes();
56+
57+
@Override
58+
@Memoized
59+
public Attributes getAttributes() {
60+
Throwable exception = getException();
61+
SpanLimits spanLimits = getSpanLimits();
62+
Attributes additionalAttributes = getAdditionalAttributes();
63+
64+
AttributesMap attributes =
65+
AttributesMap.create(
66+
spanLimits.getMaxNumberOfAttributes(), spanLimits.getMaxAttributeValueLength());
67+
String exceptionName = exception.getClass().getCanonicalName();
68+
String exceptionMessage = exception.getMessage();
69+
StringWriter stringWriter = new StringWriter();
70+
try (PrintWriter printWriter = new PrintWriter(stringWriter)) {
71+
exception.printStackTrace(printWriter);
72+
}
73+
String stackTrace = stringWriter.toString();
74+
75+
if (exceptionName != null) {
76+
attributes.put(EXCEPTION_TYPE, exceptionName);
77+
}
78+
if (exceptionMessage != null) {
79+
attributes.put(EXCEPTION_MESSAGE, exceptionMessage);
80+
}
81+
if (stackTrace != null) {
82+
attributes.put(EXCEPTION_STACKTRACE, stackTrace);
83+
}
84+
85+
additionalAttributes.forEach(attributes::put);
86+
87+
return attributes.immutableCopy();
88+
}
89+
90+
@Override
91+
public int getTotalAttributeCount() {
92+
// getAttributes() lazily adds 3 attributes to getAdditionalAttributes():
93+
// - exception.type
94+
// - exception.message
95+
// - exception.stacktrace
96+
return getAdditionalAttributes().size() + 3;
97+
}
98+
99+
LazyExceptionEventData() {}
100+
}

0 commit comments

Comments
 (0)