1
1
import type { BaseHook , HookContext , EvaluationDetails , FlagValue , Logger } from '@openfeature/core' ;
2
- import type { Span } from '@opentelemetry/api' ;
2
+ import type { Attributes , Exception , Span } from '@opentelemetry/api' ;
3
3
import { trace } from '@opentelemetry/api' ;
4
- import type { EventLogger } from '@opentelemetry/api-events' ;
4
+ import type { EventLogger , Event } from '@opentelemetry/api-events' ;
5
5
import { events } from '@opentelemetry/api-events' ;
6
+ import {
7
+ ATTR_EXCEPTION_MESSAGE ,
8
+ ATTR_EXCEPTION_STACKTRACE ,
9
+ ATTR_EXCEPTION_TYPE ,
10
+ } from '@opentelemetry/semantic-conventions' ;
6
11
import type { OpenTelemetryHookOptions } from '../otel-hook' ;
7
12
import { OpenTelemetryHook } from '../otel-hook' ;
8
13
@@ -27,10 +32,41 @@ export class EventHook extends OpenTelemetryHook implements BaseHook {
27
32
}
28
33
29
34
error ( _ : HookContext , err : Error ) {
30
- if ( ! this . excludeExceptionsFromTrace ) {
31
- trace . getActiveSpan ( ) ?. recordException ( err ) ;
35
+ if ( ! this . excludeExceptions ) {
36
+ this . eventLogger . emit ( this . toExceptionLogEvent ( err ) ) ;
32
37
}
33
38
}
39
+
40
+ /**
41
+ * Converts an exception to an OpenTelemetry log event.
42
+ * The event is compatible to https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-logs/
43
+ * The mapping code is adapted from the OpenTelemetry JS SDK:
44
+ * https://github.com/open-telemetry/opentelemetry-js/blob/09bf31eb966bab627e76a6c5c05c6e51ccd2f387/packages/opentelemetry-sdk-trace-base/src/Span.ts#L330
45
+ * @private
46
+ */
47
+ private toExceptionLogEvent ( exception : Exception ) : Event {
48
+ const attributes : Attributes = { } ;
49
+ if ( typeof exception === 'string' ) {
50
+ attributes [ ATTR_EXCEPTION_MESSAGE ] = exception ;
51
+ } else if ( exception ) {
52
+ if ( exception . code ) {
53
+ attributes [ ATTR_EXCEPTION_TYPE ] = exception . code . toString ( ) ;
54
+ } else if ( exception . name ) {
55
+ attributes [ ATTR_EXCEPTION_TYPE ] = exception . name ;
56
+ }
57
+ if ( exception . message ) {
58
+ attributes [ ATTR_EXCEPTION_MESSAGE ] = exception . message ;
59
+ }
60
+ if ( exception . stack ) {
61
+ attributes [ ATTR_EXCEPTION_STACKTRACE ] = exception . stack ;
62
+ }
63
+ }
64
+
65
+ return {
66
+ name : 'exception' ,
67
+ attributes,
68
+ } ;
69
+ }
34
70
}
35
71
36
72
/**
@@ -58,7 +94,7 @@ export class SpanEventHook extends OpenTelemetryHook implements BaseHook {
58
94
}
59
95
60
96
error ( _ : HookContext , err : Error ) {
61
- if ( ! this . excludeExceptionsFromTrace ) {
97
+ if ( ! this . excludeExceptions ) {
62
98
trace . getActiveSpan ( ) ?. recordException ( err ) ;
63
99
}
64
100
}
@@ -105,7 +141,7 @@ export class SpanHook extends OpenTelemetryHook implements BaseHook {
105
141
}
106
142
107
143
error ( hookContext : Readonly < HookContext < FlagValue , SpanAttributesTracingHookData > > , err : Error ) {
108
- if ( ! this . excludeExceptionsFromTrace ) {
144
+ if ( ! this . excludeExceptions ) {
109
145
const currentSpan = hookContext . hookData . get ( HookContextSpanKey ) ?? trace . getActiveSpan ( ) ;
110
146
currentSpan ?. recordException ( err ) ;
111
147
}
0 commit comments