Skip to content

Commit d421421

Browse files
committed
fix: make OTEL evaluation event attribute types compliant to OTEL types
Signed-off-by: Lukas Reining <[email protected]>
1 parent ee23639 commit d421421

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

packages/shared/src/telemetry/evaluation-event.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
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';
33
import { TelemetryAttribute } from './attributes';
44
import { TelemetryFlagMetadata } from './flag-metadata';
55

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+
618
type EvaluationEvent = {
719
/**
820
* The name of the feature flag evaluation event.
@@ -13,7 +25,7 @@ type EvaluationEvent = {
1325
* @experimental The attributes are subject to change.
1426
* @see https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/
1527
*/
16-
attributes: Record<string, string | number | boolean | FlagValue>;
28+
attributes: Record<string, AttributeValue | undefined>;
1729
};
1830

1931
const FLAG_EVALUATION_EVENT_NAME = 'feature_flag.evaluation';
@@ -36,12 +48,23 @@ export function createEvaluationEvent(
3648

3749
if (evaluationDetails.variant) {
3850
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+
}
4164
}
4265

4366
const contextId =
44-
evaluationDetails.flagMetadata[TelemetryFlagMetadata.CONTEXT_ID] || hookContext.context.targetingKey;
67+
evaluationDetails.flagMetadata[TelemetryFlagMetadata.CONTEXT_ID] ?? hookContext.context.targetingKey;
4568
if (contextId) {
4669
attributes[TelemetryAttribute.CONTEXT_ID] = contextId;
4770
}

0 commit comments

Comments
 (0)