Skip to content

Commit 3e6bcae

Browse files
authored
refactor(telemetry): update telemetry attributes and remove unused evaluation data (#1189)
## This PR - update the evaluation event to match the latest OTel semcon ### Related Issues Fixes #1188 ### Notes Update the createEvaluationEvent to match the latest OpenTelemetry spec. Unforutnately, this is a breaking change. I'll denote this in the release notes but not in the library version. That's because we're following the experimental OTel spec and the method itself is currently undocumented except from the generated JS Doc. It's also worth noting that OTel JS SDK event API doesn't currently support object as attribute values. @dyladan will update the OTel SDK. ### Follow-up Tasks Update the ToggleShop. ### How to test `npm run test` Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
1 parent 66a3ce0 commit 3e6bcae

File tree

6 files changed

+34
-42
lines changed

6 files changed

+34
-42
lines changed

packages/shared/src/evaluation/evaluation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { JsonValue } from '../types/structure';
33
export type FlagValueType = 'boolean' | 'string' | 'number' | 'object';
44

55
/**
6-
* Represents a JSON node value, or Date.
6+
* Represents a JSON node value.
77
*/
88
export type FlagValue = boolean | string | number | JsonValue;
99

packages/shared/src/telemetry/attributes.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ export const TelemetryAttribute = {
2020
* - example: `flag_not_found`
2121
*/
2222
ERROR_CODE: 'error.type',
23+
/**
24+
* A message explaining the nature of an error occurring during flag evaluation.
25+
*
26+
* - type: `string`
27+
* - requirement level: `recommended`
28+
* - example: `Flag not found`
29+
*/
30+
ERROR_MESSAGE: 'error.message',
2331
/**
2432
* A semantic identifier for an evaluated flag value.
2533
*
@@ -28,39 +36,40 @@ export const TelemetryAttribute = {
2836
* - condition: variant is defined on the evaluation details
2937
* - example: `blue`; `on`; `true`
3038
*/
31-
VARIANT: 'feature_flag.variant',
39+
VARIANT: 'feature_flag.result.variant',
3240
/**
33-
* The unique identifier for the flag evaluation context. For example, the targeting key.
41+
* The evaluated value of the feature flag.
3442
*
35-
* - type: `string`
36-
* - requirement level: `recommended`
37-
* - example: `5157782b-2203-4c80-a857-dbbd5e7761db`
43+
* - type: `undefined`
44+
* - requirement level: `conditionally required`
45+
* - condition: variant is not defined on the evaluation details
46+
* - example: `#ff0000`; `1`; `true`
3847
*/
39-
CONTEXT_ID: 'feature_flag.context.id',
48+
VALUE: 'feature_flag.result.value',
4049
/**
41-
* A message explaining the nature of an error occurring during flag evaluation.
50+
* The unique identifier for the flag evaluation context. For example, the targeting key.
4251
*
4352
* - type: `string`
4453
* - requirement level: `recommended`
45-
* - example: `Flag not found`
54+
* - example: `5157782b-2203-4c80-a857-dbbd5e7761db`
4655
*/
47-
ERROR_MESSAGE: 'feature_flag.evaluation.error.message',
56+
CONTEXT_ID: 'feature_flag.context.id',
4857
/**
4958
* The reason code which shows how a feature flag value was determined.
5059
*
5160
* - type: `string`
5261
* - requirement level: `recommended`
5362
* - example: `targeting_match`
5463
*/
55-
REASON: 'feature_flag.evaluation.reason',
64+
REASON: 'feature_flag.result.reason',
5665
/**
5766
* Describes a class of error the operation ended with.
5867
*
5968
* - type: `string`
6069
* - requirement level: `recommended`
6170
* - example: `flag_not_found`
6271
*/
63-
PROVIDER: 'feature_flag.provider_name',
72+
PROVIDER: 'feature_flag.provider.name',
6473
/**
6574
* The identifier of the flag set to which the feature flag belongs.
6675
*

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

Lines changed: 0 additions & 17 deletions
This file was deleted.

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import { ErrorCode, StandardResolutionReasons, type EvaluationDetails, type FlagValue } from '../evaluation/evaluation';
22
import type { HookContext } from '../hooks/hooks';
3-
import type { JsonValue } from '../types';
43
import { TelemetryAttribute } from './attributes';
5-
import { TelemetryEvaluationData } from './evaluation-data';
64
import { TelemetryFlagMetadata } from './flag-metadata';
75

86
type EvaluationEvent = {
7+
/**
8+
* The name of the feature flag evaluation event.
9+
*/
910
name: string;
10-
attributes: Record<string, string | number | boolean>;
11-
body: Record<string, JsonValue>;
11+
/**
12+
* The attributes of an OpenTelemetry compliant event for flag evaluation.
13+
* @experimental The attributes are subject to change.
14+
* @see https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/
15+
*/
16+
attributes: Record<string, string | number | boolean | FlagValue>;
1217
};
1318

1419
const FLAG_EVALUATION_EVENT_NAME = 'feature_flag.evaluation';
@@ -28,12 +33,11 @@ export function createEvaluationEvent(
2833
[TelemetryAttribute.PROVIDER]: hookContext.providerMetadata.name,
2934
[TelemetryAttribute.REASON]: (evaluationDetails.reason ?? StandardResolutionReasons.UNKNOWN).toLowerCase(),
3035
};
31-
const body: EvaluationEvent['body'] = {};
3236

3337
if (evaluationDetails.variant) {
3438
attributes[TelemetryAttribute.VARIANT] = evaluationDetails.variant;
3539
} else {
36-
body[TelemetryEvaluationData.VALUE] = evaluationDetails.value;
40+
attributes[TelemetryAttribute.VALUE] = evaluationDetails.value;
3741
}
3842

3943
const contextId =
@@ -62,6 +66,5 @@ export function createEvaluationEvent(
6266
return {
6367
name: FLAG_EVALUATION_EVENT_NAME,
6468
attributes,
65-
body,
6669
};
6770
}
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export * from './attributes';
2-
export * from './evaluation-data';
32
export * from './flag-metadata';
43
export * from './evaluation-event';

packages/shared/test/telemetry.spec.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createEvaluationEvent } from '../src/telemetry/evaluation-event';
22
import { ErrorCode, StandardResolutionReasons, type EvaluationDetails } from '../src/evaluation/evaluation';
33
import type { HookContext } from '../src/hooks/hooks';
4-
import { TelemetryAttribute, TelemetryFlagMetadata, TelemetryEvaluationData } from '../src/telemetry';
4+
import { TelemetryAttribute, TelemetryFlagMetadata } from '../src/telemetry';
55

66
describe('evaluationEvent', () => {
77
const flagKey = 'test-flag';
@@ -43,9 +43,7 @@ describe('evaluationEvent', () => {
4343
[TelemetryAttribute.PROVIDER]: 'test-provider',
4444
[TelemetryAttribute.REASON]: StandardResolutionReasons.STATIC.toLowerCase(),
4545
[TelemetryAttribute.CONTEXT_ID]: 'test-target',
46-
});
47-
expect(result.body).toEqual({
48-
[TelemetryEvaluationData.VALUE]: true,
46+
[TelemetryAttribute.VALUE]: true,
4947
});
5048
});
5149

@@ -61,7 +59,7 @@ describe('evaluationEvent', () => {
6159
const result = createEvaluationEvent(mockHookContext, details);
6260

6361
expect(result.attributes[TelemetryAttribute.VARIANT]).toBe('test-variant');
64-
expect(result.attributes[TelemetryEvaluationData.VALUE]).toBeUndefined();
62+
expect(result.attributes[TelemetryAttribute.VALUE]).toBeUndefined();
6563
});
6664

6765
it('should include flag metadata when provided', () => {

0 commit comments

Comments
 (0)