1
- import { ErrorCode , StandardResolutionReasons , type EvaluationDetails , type FlagValue } from '../evaluation/evaluation ' ;
2
- import type { HookContext } from '../hooks/hooks ' ;
1
+ import { ErrorCode , StandardResolutionReasons , type EvaluationDetails , type FlagValue } from '../evaluation' ;
2
+ import type { HookContext } from '../hooks' ;
3
3
import { TelemetryAttribute } from './attributes' ;
4
4
import { TelemetryFlagMetadata } from './flag-metadata' ;
5
5
6
+ /**
7
+ * Attribute types for OpenTelemetry.
8
+ * @see https://github.com/open-telemetry/opentelemetry-js/blob/fbbce6e1c0de86e4c504b5788d876fae4d3bc254/api/src/common/Attributes.ts#L35
9
+ */
10
+ export declare type AttributeValue =
11
+ | string
12
+ | number
13
+ | boolean
14
+ | Array < null | undefined | string >
15
+ | Array < null | undefined | number >
16
+ | Array < null | undefined | boolean > ;
17
+
6
18
type EvaluationEvent = {
7
19
/**
8
20
* The name of the feature flag evaluation event.
@@ -13,7 +25,7 @@ type EvaluationEvent = {
13
25
* @experimental The attributes are subject to change.
14
26
* @see https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/
15
27
*/
16
- attributes : Record < string , string | number | boolean | FlagValue > ;
28
+ attributes : Record < string , AttributeValue | undefined > ;
17
29
} ;
18
30
19
31
const FLAG_EVALUATION_EVENT_NAME = 'feature_flag.evaluation' ;
@@ -36,12 +48,23 @@ export function createEvaluationEvent(
36
48
37
49
if ( evaluationDetails . variant ) {
38
50
attributes [ TelemetryAttribute . VARIANT ] = evaluationDetails . variant ;
39
- } else {
40
- attributes [ TelemetryAttribute . VALUE ] = evaluationDetails . value ;
51
+ }
52
+
53
+ if ( evaluationDetails . value !== null ) {
54
+ if ( typeof evaluationDetails . value !== 'object' ) {
55
+ attributes [ TelemetryAttribute . VALUE ] = evaluationDetails . value ;
56
+ } else {
57
+ try {
58
+ // Objects are not valid attribute values, so we convert them to a JSON string
59
+ attributes [ TelemetryAttribute . VALUE ] = JSON . stringify ( evaluationDetails . value ) ;
60
+ } catch {
61
+ // We ignore non serializable values
62
+ }
63
+ }
41
64
}
42
65
43
66
const contextId =
44
- evaluationDetails . flagMetadata [ TelemetryFlagMetadata . CONTEXT_ID ] || hookContext . context . targetingKey ;
67
+ evaluationDetails . flagMetadata [ TelemetryFlagMetadata . CONTEXT_ID ] ?? hookContext . context . targetingKey ;
45
68
if ( contextId ) {
46
69
attributes [ TelemetryAttribute . CONTEXT_ID ] = contextId ;
47
70
}
0 commit comments