From fa564c9f6755a73699398ea44d1e22b0e75e48dd Mon Sep 17 00:00:00 2001 From: Daniel Dyla Date: Fri, 15 Nov 2024 11:42:26 -0700 Subject: [PATCH] Feature Flag evaluation event (#1440) Co-authored-by: Liudmila Molkova Co-authored-by: Josh Suereth --- .chloggen/1440.yaml | 6 ++ docs/attributes-registry/feature-flag.md | 38 ++++++-- docs/feature-flags/README.md | 1 - docs/feature-flags/feature-flags-logs.md | 87 +++++++++++++++---- docs/feature-flags/feature-flags-spans.md | 80 ----------------- docs/general/trace.md | 1 - .../deprecated/registry-deprecated.yaml | 12 +++ model/feature-flag/events.yaml | 14 --- model/feature-flag/logs.yaml | 64 ++++++++++++++ model/feature-flag/registry.yaml | 79 +++++++++++++++-- schema-next.yaml | 5 ++ 11 files changed, 260 insertions(+), 127 deletions(-) create mode 100644 .chloggen/1440.yaml delete mode 100644 docs/feature-flags/feature-flags-spans.md create mode 100644 model/feature-flag/deprecated/registry-deprecated.yaml delete mode 100644 model/feature-flag/events.yaml create mode 100644 model/feature-flag/logs.yaml diff --git a/.chloggen/1440.yaml b/.chloggen/1440.yaml new file mode 100644 index 0000000000..f130197287 --- /dev/null +++ b/.chloggen/1440.yaml @@ -0,0 +1,6 @@ +change_type: breaking +component: feature_flag +note: > + Rename `feature_flag` event to `feature_flag.evaluation` event, define new feature flag attributes and provide body definition. + Remove `feature_flag` span event definition in favor of log-based event. +issues: [1440] diff --git a/docs/attributes-registry/feature-flag.md b/docs/attributes-registry/feature-flag.md index 91e0be7a53..de4cd52d50 100644 --- a/docs/attributes-registry/feature-flag.md +++ b/docs/attributes-registry/feature-flag.md @@ -6,21 +6,47 @@ # Feature Flag +- [Feature Flag Attributes](#feature-flag-attributes) +- [Deprecated Feature Flag Attributes](#deprecated-feature-flag-attributes) + ## Feature Flag Attributes This document defines attributes for Feature Flags. | Attribute | Type | Description | Examples | Stability | |---|---|---|---|---| -| `feature_flag.key` | string | The unique identifier of the feature flag. | `logo-color` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `feature_flag.provider_name` | string | The name of the service provider that performs the flag evaluation. | `Flag Manager` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| `feature_flag.variant` | string | SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the value can be used. [1] | `red`; `true`; `on` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.context.id` | string | The unique identifier for the flag evaluation context. For example, the targeting key. | `5157782b-2203-4c80-a857-dbbd5e7761db` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.evaluation.error.message` | string | A message explaining the nature of an error occurring during flag evaluation. | `Flag `header-color` expected type `string` but found type `number`` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.evaluation.reason` | string | The reason code which shows how a feature flag value was determined. | `static`; `targeting_match`; `error`; `default` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.key` | string | The lookup key of the feature flag. | `logo-color` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.set.id` | string | The identifier of the [flag set](https://openfeature.dev/specification/glossary/#flag-set) to which the feature flag belongs. | `proj-1`; `ab98sgs`; `service1/dev` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.system` | string | Identifies the feature flag provider. | `Flag Manager` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.variant` | string | A semantic identifier for an evaluated flag value. [1] | `red`; `true`; `on` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `feature_flag.version` | string | The version of the ruleset used during the evaluation. This may be any stable value which uniquely identifies the ruleset. | `1`; `01ABCDEF` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** A semantic identifier, commonly referred to as a variant, provides a means for referring to a value without including the value itself. This can provide additional context for understanding the meaning behind a value. For example, the variant `red` maybe be used for the value `#c05543`. -A stringified version of the value can be used in situations where a -semantic identifier is unavailable. String representation of the value -should be determined by the implementer. +`feature_flag.evaluation.reason` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `cached` | The resolved value was retrieved from cache. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `default` | The resolved value fell back to a pre-configured value (no dynamic evaluation occurred or dynamic evaluation yielded no result). | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `disabled` | The resolved value was the result of the flag being disabled in the management system. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `error` | The resolved value was the result of an error. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `split` | The resolved value was the result of pseudorandom assignment. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `stale` | The resolved value is non-authoritative or possibly out of date | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `static` | The resolved value is static (no dynamic evaluation). | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `targeting_match` | The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `unknown` | The reason for the resolved value could not be determined. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +## Deprecated Feature Flag Attributes + +Describes deprecated Feature Flag attributes. + +| Attribute | Type | Description | Examples | Stability | +|---|---|---|---|---| +| `feature_flag.provider_name` | string | Deprecated, use `feature_flag.system` instead. | `Flag Manager` | ![Deprecated](https://img.shields.io/badge/-deprecated-red)
Replaced by `feature_flag.system`. | diff --git a/docs/feature-flags/README.md b/docs/feature-flags/README.md index 2262031198..1d4a454078 100644 --- a/docs/feature-flags/README.md +++ b/docs/feature-flags/README.md @@ -14,7 +14,6 @@ evaluations in spans and logs. Semantic conventions for feature flags are defined for the following signals: -* [Feature Flags in Spans](feature-flags-spans.md): Semantic Conventions for recording feature flags in *spans*. * [Feature Flags in Logs](feature-flags-logs.md): Semantic Conventions for recording feature flags in *logs*. [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/feature-flags/feature-flags-logs.md b/docs/feature-flags/feature-flags-logs.md index 32b2519220..85964d8181 100644 --- a/docs/feature-flags/feature-flags-logs.md +++ b/docs/feature-flags/feature-flags-logs.md @@ -11,12 +11,16 @@ a [log record](https://github.com/open-telemetry/opentelemetry-specification/tre [Logger API](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.37.0/specification/logs/bridge-api.md#emit-a-logrecord). This is useful when a flag is evaluated outside of a transaction context such as when the application loads or on a timer. -To record a flag evaluation as a part of a transaction context, -consider [recording it as a span event](feature-flags-spans.md). -For more information about why it is useful to capture feature flag evaluations, -refer to the [motivation](feature-flags-spans.md#motivation) -section of the trace semantic convention for feature flag evaluations. +## Motivation + +Features flags are commonly used in modern applications to decouple feature releases from deployments. +Many feature flagging tools support the ability to update flag configurations in near real-time from a remote feature flag management service. +They also commonly allow rulesets to be defined that return values based on contextual information. +For example, a feature could be enabled only for a specific subset of users based on context (e.g. users email domain, membership tier, country). + +Since feature flags are dynamic and affect runtime behavior, it's important to collect relevant feature flag telemetry signals. +This can be used to determine the impact a feature has on a request, enabling enhanced observability use cases, such as A/B testing or progressive feature releases. @@ -37,7 +41,7 @@ context. The table below indicates which attributes should be added to the [LogRecord](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.37.0/specification/logs/data-model.md#log-and-event-record-definition) and their types. - + @@ -46,24 +50,75 @@ The table below indicates which attributes should be added to the **Status:** ![Experimental](https://img.shields.io/badge/-experimental-blue) -The event name MUST be `feature_flag`. +The event name MUST be `feature_flag.evaluation`. -This event describes feature flag evaluation. +Defines feature flag evaluation as an event. + +A `feature_flag.evaluation` event SHOULD be emitted whenever a feature flag value is evaluated, which may happen many times over the course of an application lifecycle. For example, a website A/B testing different animations may evaluate a flag each time a button is clicked. A `feature_flag.evaluation` event is emitted on each evaluation even if the result is the same. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`feature_flag.key`](/docs/attributes-registry/feature-flag.md) | string | The unique identifier of the feature flag. | `logo-color` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`feature_flag.provider_name`](/docs/attributes-registry/feature-flag.md) | string | The name of the service provider that performs the flag evaluation. | `Flag Manager` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`feature_flag.variant`](/docs/attributes-registry/feature-flag.md) | string | SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the value can be used. [1] | `red`; `true`; `on` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | - -**[1]:** A semantic identifier, commonly referred to as a variant, provides a means +| [`feature_flag.key`](/docs/attributes-registry/feature-flag.md) | string | The lookup key of the feature flag. | `logo-color` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `provider_not_ready`; `targeting_key_missing`; `provider_fatal`; `general` | `Conditionally Required` [2] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`feature_flag.variant`](/docs/attributes-registry/feature-flag.md) | string | A semantic identifier for an evaluated flag value. [3] | `red`; `true`; `on` | `Conditionally Required` [4] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`feature_flag.context.id`](/docs/attributes-registry/feature-flag.md) | string | The unique identifier for the flag evaluation context. For example, the targeting key. | `5157782b-2203-4c80-a857-dbbd5e7761db` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`feature_flag.evaluation.error.message`](/docs/attributes-registry/feature-flag.md) | string | A message explaining the nature of an error occurring during flag evaluation. | `Flag `header-color` expected type `string` but found type `number`` | `Recommended` [5] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`feature_flag.evaluation.reason`](/docs/attributes-registry/feature-flag.md) | string | The reason code which shows how a feature flag value was determined. | `static`; `targeting_match`; `error`; `default` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`feature_flag.set.id`](/docs/attributes-registry/feature-flag.md) | string | The identifier of the [flag set](https://openfeature.dev/specification/glossary/#flag-set) to which the feature flag belongs. | `proj-1`; `ab98sgs`; `service1/dev` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`feature_flag.system`](/docs/attributes-registry/feature-flag.md) | string | Identifies the feature flag provider. | `Flag Manager` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`feature_flag.version`](/docs/attributes-registry/feature-flag.md) | string | The version of the ruleset used during the evaluation. This may be any stable value which uniquely identifies the ruleset. | `1`; `01ABCDEF` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[1]:** If one of these values applies, then it MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `flag_not_found` | The flag could not be found. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `invalid_context` | The evaluation context does not meet provider requirements. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `parse_error` | An error was encountered parsing data, such as a flag configuration. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `provider_fatal` | The provider has entered an irrecoverable error state. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `provider_not_ready` | The value was resolved before the provider was initialized. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `targeting_key_missing` | The provider requires a targeting key and one was not provided in the evaluation context. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `type_mismatch` | The type of the flag value does not match the expected type. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `general` | The error was for a reason not enumerated above. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[2]:** If and only if an error occurred during flag evaluation. + +**[3]:** A semantic identifier, commonly referred to as a variant, provides a means for referring to a value without including the value itself. This can provide additional context for understanding the meaning behind a value. For example, the variant `red` maybe be used for the value `#c05543`. -A stringified version of the value can be used in situations where a -semantic identifier is unavailable. String representation of the value -should be determined by the implementer. +**[4]:** If feature flag provider supplies a variant or equivalent concept. + +**[5]:** If and only if an error occurred. It's NOT RECOMMENDED to duplicate the value of `error.type` in `feature_flag.evaluation.error.message`. + +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +`feature_flag.evaluation.reason` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `cached` | The resolved value was retrieved from cache. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `default` | The resolved value fell back to a pre-configured value (no dynamic evaluation occurred or dynamic evaluation yielded no result). | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `disabled` | The resolved value was the result of the flag being disabled in the management system. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `error` | The resolved value was the result of an error. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `split` | The resolved value was the result of pseudorandom assignment. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `stale` | The resolved value is non-authoritative or possibly out of date | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `static` | The resolved value is static (no dynamic evaluation). | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `targeting_match` | The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `unknown` | The reason for the resolved value could not be determined. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**Body fields:** + +| Body Field | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| `value` | undefined | The evaluated value of the feature flag. | `#ff0000`; `1`; `true` | `Conditionally Required` [1] | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[1]:** If and only if feature flag provider does not supply variant or equivalent concept. Otherwise, `value` should be treated as opt-in. diff --git a/docs/feature-flags/feature-flags-spans.md b/docs/feature-flags/feature-flags-spans.md deleted file mode 100644 index de0ded12fb..0000000000 --- a/docs/feature-flags/feature-flags-spans.md +++ /dev/null @@ -1,80 +0,0 @@ - - -# Semantic Conventions for Feature Flags in Spans - -**Status**: [Experimental][DocumentStatus] - -This document defines semantic conventions for recording dynamic feature flag -evaluations within a transaction as span events. -To record an evaluation outside of a transaction context, consider -[recording it as a log record](feature-flags-logs.md). - - - - - -- [Motivation](#motivation) -- [Overview](#overview) -- [Convention](#convention) - - [Evaluation event](#evaluation-event) - - - -## Motivation - -Features flags are commonly used in modern applications to decouple feature releases from deployments. -Many feature flagging tools support the ability to update flag configurations in near real-time from a remote feature flag management service. -They also commonly allow rulesets to be defined that return values based on contextual information. -For example, a feature could be enabled only for a specific subset of users based on context (e.g. users email domain, membership tier, country). - -Since feature flags are dynamic and affect runtime behavior, it's important to collect relevant feature flag telemetry signals. -This can be used to determine the impact a feature has on a request, enabling enhanced observability use cases, such as A/B testing or progressive feature releases. - -## Overview - -The following semantic convention defines how feature flags can be represented as an `Event` in OpenTelemetry. -The terminology was defined in the [OpenFeature specification](https://docs.openfeature.dev/docs/specification/), which represents an industry consensus. -It's intended to be vendor neutral and provide flexibility for current and future use cases. - -## Convention - -A flag evaluation SHOULD be recorded as an Event on the span during which it occurred. - -### Evaluation event - - - - - - - - -**Status:** ![Experimental](https://img.shields.io/badge/-experimental-blue) - -The event name MUST be `feature_flag`. - -This event describes feature flag evaluation. - -| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | -|---|---|---|---|---|---| -| [`feature_flag.key`](/docs/attributes-registry/feature-flag.md) | string | The unique identifier of the feature flag. | `logo-color` | `Required` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`feature_flag.provider_name`](/docs/attributes-registry/feature-flag.md) | string | The name of the service provider that performs the flag evaluation. | `Flag Manager` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`feature_flag.variant`](/docs/attributes-registry/feature-flag.md) | string | SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the value can be used. [1] | `red`; `true`; `on` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | - -**[1]:** A semantic identifier, commonly referred to as a variant, provides a means -for referring to a value without including the value itself. This can -provide additional context for understanding the meaning behind a value. -For example, the variant `red` maybe be used for the value `#c05543`. - -A stringified version of the value can be used in situations where a -semantic identifier is unavailable. String representation of the value -should be determined by the implementer. - - - - - - -[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/general/trace.md b/docs/general/trace.md index 09b164af16..565913a31b 100644 --- a/docs/general/trace.md +++ b/docs/general/trace.md @@ -27,7 +27,6 @@ The following semantic conventions for spans are defined: * [Database](/docs/database/database-spans.md): For SQL and NoSQL client call spans. * [Exceptions](/docs/exceptions/exceptions-spans.md): For recording exceptions associated with a span. * [FaaS](/docs/faas/faas-spans.md): For [Function as a Service](https://wikipedia.org/wiki/Function_as_a_service) (e.g., AWS Lambda) spans. -* [Feature Flags](/docs/feature-flags/feature-flags-spans.md): For recording feature flag evaluations associated with a span. * [HTTP](/docs/http/http-spans.md): For HTTP client and server spans. * [Messaging](/docs/messaging/messaging-spans.md): For messaging systems (queues, publish/subscribe, etc.) spans. * [Object Stores](/docs/object-stores/README.md): Semantic Conventions for object stores spans. diff --git a/model/feature-flag/deprecated/registry-deprecated.yaml b/model/feature-flag/deprecated/registry-deprecated.yaml new file mode 100644 index 0000000000..2f3a681454 --- /dev/null +++ b/model/feature-flag/deprecated/registry-deprecated.yaml @@ -0,0 +1,12 @@ +groups: + - id: registry.feature_flag.deprecated + type: attribute_group + display_name: Deprecated Feature Flag Attributes + brief: "Describes deprecated Feature Flag attributes." + attributes: + - id: feature_flag.provider_name + type: string + brief: 'Deprecated, use `feature_flag.system` instead.' + stability: experimental + deprecated: "Replaced by `feature_flag.system`." + examples: ["Flag Manager"] diff --git a/model/feature-flag/events.yaml b/model/feature-flag/events.yaml deleted file mode 100644 index bd2cff8829..0000000000 --- a/model/feature-flag/events.yaml +++ /dev/null @@ -1,14 +0,0 @@ -groups: - - id: event.feature_flag - type: event - stability: experimental - name: feature_flag - brief: > - This event describes feature flag evaluation. - attributes: - - ref: feature_flag.key - requirement_level: required - - ref: feature_flag.provider_name - requirement_level: recommended - - ref: feature_flag.variant - requirement_level: recommended diff --git a/model/feature-flag/logs.yaml b/model/feature-flag/logs.yaml new file mode 100644 index 0000000000..0de7c95577 --- /dev/null +++ b/model/feature-flag/logs.yaml @@ -0,0 +1,64 @@ +groups: + - id: event.feature_flag.evaluation + type: event + name: feature_flag.evaluation + brief: > + Defines feature flag evaluation as an event. + note: > + A `feature_flag.evaluation` event SHOULD be emitted whenever a feature flag + value is evaluated, which may happen many times over the course of an + application lifecycle. + For example, a website A/B testing different animations may evaluate a + flag each time a button is clicked. + A `feature_flag.evaluation` event is emitted on each evaluation even if the result is the same. + attributes: + - ref: feature_flag.key + requirement_level: required + - ref: feature_flag.variant + requirement_level: + conditionally_required: If feature flag provider supplies a variant or equivalent concept. + - ref: feature_flag.system + requirement_level: recommended + - ref: feature_flag.context.id + requirement_level: recommended + - ref: feature_flag.version + requirement_level: recommended + - ref: feature_flag.set.id + requirement_level: recommended + - ref: feature_flag.evaluation.reason + requirement_level: recommended + - ref: error.type + examples: ["provider_not_ready", "targeting_key_missing", "provider_fatal", "general"] + requirement_level: + conditionally_required: If and only if an error occurred during flag evaluation. + # TODO: move note to yaml once https://github.com/open-telemetry/build-tools/issues/192 is supported + note: | + If one of these values applies, then it MUST be used; otherwise, a custom value MAY be used. + + | Value | Description | Stability | + |---|---|---| + | `flag_not_found` | The flag could not be found. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `invalid_context` | The evaluation context does not meet provider requirements. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `parse_error` | An error was encountered parsing data, such as a flag configuration. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `provider_fatal` | The provider has entered an irrecoverable error state. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `provider_not_ready` | The value was resolved before the provider was initialized. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `targeting_key_missing` | The provider requires a targeting key and one was not provided in the evaluation context. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `type_mismatch` | The type of the flag value does not match the expected type. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + | `general` | The error was for a reason not enumerated above. | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + - ref: feature_flag.evaluation.error.message + requirement_level: + recommended: If and only if an error occurred. It's NOT RECOMMENDED to duplicate the value of `error.type` in `feature_flag.evaluation.error.message`. + body: + id: feature_flag.evaluation + type: map + requirement_level: recommended + fields: + - id: value + type: undefined + stability: experimental + brief: The evaluated value of the feature flag. + requirement_level: + conditionally_required: > + If and only if feature flag provider does not supply variant or equivalent concept. + Otherwise, `value` should be treated as opt-in. + examples: ["#ff0000", "1", "true"] diff --git a/model/feature-flag/registry.yaml b/model/feature-flag/registry.yaml index 380ef79d5f..76b1d5fe3c 100644 --- a/model/feature-flag/registry.yaml +++ b/model/feature-flag/registry.yaml @@ -9,26 +9,87 @@ groups: - id: feature_flag.key type: string stability: experimental - brief: The unique identifier of the feature flag. + brief: The lookup key of the feature flag. examples: ["logo-color"] - - id: feature_flag.provider_name + - id: feature_flag.system type: string stability: experimental - brief: The name of the service provider that performs the flag evaluation. + brief: Identifies the feature flag provider. examples: ["Flag Manager"] - id: feature_flag.variant type: string stability: experimental examples: ["red", "true", "on"] brief: > - SHOULD be a semantic identifier for a value. If one is unavailable, a - stringified version of the value can be used. + A semantic identifier for an evaluated flag value. note: |- A semantic identifier, commonly referred to as a variant, provides a means for referring to a value without including the value itself. This can provide additional context for understanding the meaning behind a value. For example, the variant `red` maybe be used for the value `#c05543`. - - A stringified version of the value can be used in situations where a - semantic identifier is unavailable. String representation of the value - should be determined by the implementer. + - id: feature_flag.context.id + type: string + stability: experimental + examples: ["5157782b-2203-4c80-a857-dbbd5e7761db"] + brief: > + The unique identifier for the flag evaluation context. For example, the targeting key. + - id: feature_flag.version + type: string + stability: experimental + examples: ["1", "01ABCDEF"] + brief: > + The version of the ruleset used during the evaluation. This may be any stable value which uniquely identifies the ruleset. + - id: feature_flag.set.id + type: string + stability: experimental + examples: ["proj-1", "ab98sgs", "service1/dev"] + brief: > + The identifier of the [flag set](https://openfeature.dev/specification/glossary/#flag-set) to which the feature flag belongs. + - id: feature_flag.evaluation.reason + type: + members: + - id: static + value: "static" + brief: The resolved value is static (no dynamic evaluation). + stability: experimental + - id: default + value: "default" + brief: The resolved value fell back to a pre-configured value (no dynamic evaluation occurred or dynamic evaluation yielded no result). + stability: experimental + - id: targeting_match + value: "targeting_match" + brief: The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. + stability: experimental + - id: split + value: "split" + brief: The resolved value was the result of pseudorandom assignment. + stability: experimental + - id: cached + value: "cached" + brief: The resolved value was retrieved from cache. + stability: experimental + - id: disabled + value: "disabled" + brief: The resolved value was the result of the flag being disabled in the management system. + stability: experimental + - id: unknown + value: "unknown" + brief: The reason for the resolved value could not be determined. + stability: experimental + - id: stale + value: "stale" + brief: The resolved value is non-authoritative or possibly out of date + stability: experimental + - id: error + value: "error" + brief: The resolved value was the result of an error. + stability: experimental + stability: experimental + examples: ["static", "targeting_match", "error", "default"] + brief: > + The reason code which shows how a feature flag value was determined. + - id: feature_flag.evaluation.error.message + type: string + stability: experimental + examples: ["Flag `header-color` expected type `string` but found type `number`"] + brief: A message explaining the nature of an error occurring during flag evaluation. diff --git a/schema-next.yaml b/schema-next.yaml index 5439843483..50afab2b96 100644 --- a/schema-next.yaml +++ b/schema-next.yaml @@ -16,6 +16,11 @@ versions: vcs.repository.ref.name: vcs.ref.head.name vcs.repository.ref.revision: vcs.ref.head.revision vcs.repository.ref.type: vcs.ref.head.type + # https://github.com/open-telemetry/semantic-conventions/pull/1440 + - rename_attributes: + attribute_map: + feature_flag.provider_name: feature_flag.system + metrics: changes: # https://github.com/open-telemetry/semantic-conventions/pull/1492