Skip to content

Commit 2349754

Browse files
Merge branch 'master' into add-context-functions
2 parents dbd4ab2 + 70065d7 commit 2349754

File tree

7 files changed

+73
-27
lines changed

7 files changed

+73
-27
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
# This file controls who is tagged for review for any given pull request.
33

44
# For anything not explicitly taken by someone else:
5-
* @Workiva/observability @evanweible-wf @dustinlessard-wf
5+
* @blakeroberts-wk @evanweible-wf

lib/src/api/common/semantic_attributes.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ class SemanticAttributes {
1616
/// representation is to be determined and documented by each language SIG.
1717
static const String exceptionStacktrace = 'exception.stacktrace';
1818

19+
/// Set to true if the exception event is recorded at a point where it is
20+
/// known that the exception is escaping the scope of the span.
21+
static const String exceptionEscaped = 'exception.escaped';
22+
1923
/// HTTP request method.
2024
static const String httpMethod = 'http.method';
2125

lib/src/api/trace/nonrecording_span.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ class NonRecordingSpan implements api.Span {
3838
api.SpanContext get spanContext => _spanContext;
3939

4040
@override
41-
void recordException(dynamic exception, {StackTrace? stackTrace}) {}
41+
void recordException(dynamic exception,
42+
{bool escaped = false,
43+
StackTrace? stackTrace,
44+
List<api.Attribute>? attributes}) {}
4245

4346
@override
4447
void addEvent(String name,

lib/src/api/trace/span.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ abstract class Span {
6666
/// Marks the end of this span's execution.
6767
void end({Int64 endTime});
6868

69-
/// Records a [api.SpanEvent] about the given exception.
70-
void recordException(dynamic exception, {StackTrace stackTrace});
69+
/// Record metadata about an exception occurring during this span.
70+
void recordException(dynamic exception,
71+
{bool escaped, StackTrace stackTrace, List<api.Attribute> attributes});
7172
}

lib/src/sdk/trace/span.dart

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import 'package:fixnum/fixnum.dart';
55
import 'package:meta/meta.dart';
6+
import 'package:opentelemetry/api.dart';
67

78
import '../../../api.dart' as api;
89
import '../../../sdk.dart' as sdk;
@@ -138,16 +139,18 @@ class Span implements sdk.ReadWriteSpan {
138139

139140
@override
140141
void recordException(dynamic exception,
141-
{StackTrace stackTrace = StackTrace.empty}) {
142-
// ignore: todo
143-
// TODO: O11Y-1531: Consider integration of Events here.
144-
setAttributes([
145-
api.Attribute.fromString(api.SemanticAttributes.exceptionType,
142+
{bool escaped = true,
143+
StackTrace stackTrace = StackTrace.empty,
144+
List<api.Attribute> attributes = const []}) {
145+
addEvent('exception', attributes: [
146+
Attribute.fromString(api.SemanticAttributes.exceptionType,
146147
exception.runtimeType.toString()),
147-
api.Attribute.fromString(
148+
Attribute.fromString(
148149
api.SemanticAttributes.exceptionMessage, exception.toString()),
149-
api.Attribute.fromString(
150+
Attribute.fromString(
150151
api.SemanticAttributes.exceptionStacktrace, stackTrace.toString()),
152+
Attribute.fromBoolean(api.SemanticAttributes.exceptionEscaped, escaped),
153+
...attributes
151154
]);
152155
}
153156

test/integration/open_telemetry_test.dart

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:async';
66

77
import 'package:opentelemetry/api.dart' as api;
88
import 'package:opentelemetry/sdk.dart' as sdk;
9+
import 'package:opentelemetry/src/api/trace/span_event.dart';
910
import 'package:opentelemetry/src/sdk/trace/span.dart';
1011
import 'package:opentelemetry/src/sdk/trace/tracer.dart';
1112
import 'package:test/test.dart';
@@ -74,10 +75,14 @@ void main() {
7475
expect(span.endTime, isNotNull);
7576
expect(span.status.code, equals(api.StatusCode.error));
7677
expect(span.status.description, equals('Exception: Oh noes!'));
77-
expect(span.attributes.get(api.SemanticAttributes.exceptionType),
78-
equals('_Exception'));
79-
expect(span.attributes.get(api.SemanticAttributes.exceptionMessage),
80-
equals('Exception: Oh noes!'));
78+
expect(span.events, [
79+
hasExceptionEvent({
80+
api.SemanticAttributes.exceptionType: '_Exception',
81+
api.SemanticAttributes.exceptionMessage: 'Exception: Oh noes!',
82+
api.SemanticAttributes.exceptionStacktrace: anything,
83+
api.SemanticAttributes.exceptionEscaped: true,
84+
})
85+
]);
8186
});
8287

8388
test('trace asynchronous execution', () async {
@@ -145,10 +150,14 @@ void main() {
145150
expect(span.endTime, isNotNull);
146151
expect(span.status.code, equals(api.StatusCode.error));
147152
expect(span.status.description, equals('Exception: Oh noes!'));
148-
expect(span.attributes.get(api.SemanticAttributes.exceptionType),
149-
equals('_Exception'));
150-
expect(span.attributes.get(api.SemanticAttributes.exceptionMessage),
151-
equals('Exception: Oh noes!'));
153+
expect(span.events, [
154+
hasExceptionEvent({
155+
api.SemanticAttributes.exceptionType: '_Exception',
156+
api.SemanticAttributes.exceptionMessage: 'Exception: Oh noes!',
157+
api.SemanticAttributes.exceptionStacktrace: anything,
158+
api.SemanticAttributes.exceptionEscaped: true,
159+
})
160+
]);
152161
});
153162

154163
test('trace asynchronous execution completes with error', () async {
@@ -173,9 +182,22 @@ void main() {
173182
expect(span.endTime, isNotNull);
174183
expect(span.status.code, equals(api.StatusCode.error));
175184
expect(span.status.description, equals('Exception: Oh noes!'));
176-
expect(span.attributes.get(api.SemanticAttributes.exceptionType),
177-
equals('_Exception'));
178-
expect(span.attributes.get(api.SemanticAttributes.exceptionMessage),
179-
equals('Exception: Oh noes!'));
185+
expect(span.events, [
186+
hasExceptionEvent({
187+
api.SemanticAttributes.exceptionType: '_Exception',
188+
api.SemanticAttributes.exceptionMessage: 'Exception: Oh noes!',
189+
api.SemanticAttributes.exceptionStacktrace: anything,
190+
api.SemanticAttributes.exceptionEscaped: true,
191+
})
192+
]);
180193
});
181194
}
195+
196+
Matcher hasExceptionEvent(Map<String, Object> attributes) =>
197+
isA<SpanEvent>().having(
198+
(e) => e.attributes,
199+
'attributes',
200+
isA<Iterable<api.Attribute>>().having(
201+
(a) => a.map((e) => [e.key, e.value]),
202+
'attributes',
203+
containsAll(attributes.entries.map((e) => [e.key, e.value]))));

test/integration/sdk/span_test.dart

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,22 @@ void main() {
210210
span.recordException(e, stackTrace: s);
211211
}
212212

213-
expect(span.attributes.get(api.SemanticAttributes.exceptionType),
214-
equals('_Exception'));
215-
expect(span.attributes.get(api.SemanticAttributes.exceptionMessage),
216-
equals('Exception: Oh noes!'));
213+
expect(span.events, [
214+
hasExceptionEvent({
215+
api.SemanticAttributes.exceptionType: '_Exception',
216+
api.SemanticAttributes.exceptionMessage: 'Exception: Oh noes!',
217+
api.SemanticAttributes.exceptionStacktrace: anything,
218+
api.SemanticAttributes.exceptionEscaped: true,
219+
})
220+
]);
217221
});
218222
}
223+
224+
Matcher hasExceptionEvent(Map<String, Object> attributes) =>
225+
isA<api.SpanEvent>().having(
226+
(e) => e.attributes,
227+
'attributes',
228+
isA<Iterable<api.Attribute>>().having(
229+
(a) => a.map((e) => [e.key, e.value]),
230+
'attributes',
231+
containsAll(attributes.entries.map((e) => [e.key, e.value]))));

0 commit comments

Comments
 (0)