Project: OpenFeature (Observability and Analysis / Feature Flagging)
File: 04-hooks.md

title: Hooks description: The specification that defines the expectations and life cycle of hooks. tocmaxheading_level: 4 `Hooks` are a mechanism whereby application developers can add arbitrary behavior to flag evaluation. They operate similarly to middleware in many web frameworks. Hooks add their logic at any of four specific stages of flag evaluation: `before`, immediately before flag evaluation `after`, immediately after successful flag evaluation `error`, immediately after an unsuccessful during flag evaluation `finally` unconditionally after flag evaluation Hooks can be configured to run globally (impacting all flag evaluations), per client, or per flag evaluation invocation. Some example use-cases for hook include adding additional data to the , performing validation on the received flag value, providing data to telemetric tools, and logging errors. Hook: Application author/integrator-supplied logic that is called by the OpenFeature framework at a specific stage. Stage: An explicit portion of the flag evaluation lifecycle. e.g. `before` being "before the is run. Invocation: A single call to evaluate a flag. `client.getBooleanValue(..)` is an invocation. API: The global API singleton. Hook context exists to provide hooks with information about the invocation. Hook context MUST provide: the `flag key`, `flag value type`, `evaluation context`, and the `default value`. The `hook context` SHOULD provide: access to the `client metadata` and the `provider metadata` fields. The `flag key`, `flag type`, and `default value` properties MUST be immutable. If the language does not support immutability, the hook MUST NOT modify these properties. The implementation uses the dynamic-context paradigm. see: The evaluation context MUST be mutable only within the `before` hook. `hook hints` MUST be a structure supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean | string | number | datetime | structure`.. The implementation language supports a mechanism for marking data as immutable. Condition: `Hook hints` MUST be immutable. Condition: The client `metadata` field in the `hook context` MUST be immutable. Condition: The provider `metadata` field in the `hook context` MUST be immutable. Hooks MUST specify at least one stage. The implementation uses the dynamic-context paradigm. see: The `before` stage MUST run before flag resolution occurs. It accepts a `hook context` (required) and `hook hints` (optional) as parameters and returns either an `evaluation context` or nothing. ```java EvaluationContext | void before(HookContext hookContext, HookHints hints); ``` ](https://github.com/open-feature/spec/tree/main/specification#experimental) The implementation uses the static-context paradigm. see: The `before` stage MUST run before flag resolution occurs. It accepts a `hook context` (required) and `hook hints` (optional) as parameters. It has no return

```java void before(HookContext hookContext, HookHints hints); ``` Any `evaluation context` returned from a `before` hook MUST be passed to subsequent `before` hooks (via `HookContext`). When `before` hooks have finished executing, any resulting `evaluation context` MUST be merged with the existing `evaluation context`. Evaluation context merge order is defined in . The `after` stage MUST run after flag resolution occurs. It accepts a `hook context` (required), `flag evaluation details` (required) and `hook hints` (optional). It has no return value. The `error` hook MUST run when errors are encountered in the `before` stage, the `after` stage or during flag resolution. It accepts `hook context` (required), `exception` representing what went wrong (required), and `hook hints` (optional). It has no return value. The `finally` hook MUST run after the `before`, `after`, and `error` stages. It accepts a `hook context` (required) and `hook hints` (optional). There is no return value. `finally` is a reserved word in the language. Instead of `finally`, `finallyAfter` SHOULD be used. The API, Client, Provider, and invocation MUST have a method for registering hooks. ```js OpenFeature.addHooks(new Hook1()); //... Client client = OpenFeature.getClient(); client.addHooks(new Hook2()); ` //... client.getValue('my-flag', 'defaultValue', new Hook3()); ``` Hooks MUST be evaluated in the following order: before: API, Client, Invocation, Provider after: Provider, Invocation, Client, API error (if applicable): Provider, Invocation, Client, API finally: Provider, Invocation, Client, API If a `finally` hook abnormally terminates, evaluation MUST proceed, including the execution of any remaining `finally` hooks. In languages with try/catch semantics, this means that exceptions thrown in `finally` hooks should be caught, and not propagated up the call stack. If an `error` hook abnormally terminates, evaluation MUST proceed, including the execution of any remaining `error` hooks. In languages with try/catch semantics, this means that exceptions thrown in `error` hooks should be caught, and not propagated up the call stack. If an error occurs in the `before` or `after` hooks, the `error` hooks MUST be invoked. If an error occurs during the evaluation of `before` or `after` hooks, any remaining hooks in the `before` or `after` stages MUST NOT be invoked. If an error occurs in the `before` hooks, the default value MUST be returned. Before hooks can impact evaluation by various means, such as mutating the `evaluation context`. Therefore, an error in the `before` hooks is considered abnormal execution, and the default should be returned. Usage might look something like: ```python val = client.getbooleanvalue('my-key', False, evaluation_options={ 'hooks': new MyHook(), 'hook_hints': {'side-item': 'onion rings'} }) ``` see: `Flag evaluation options` MAY contain `hook hints`, a map of data to be provided to hook invocations. `hook hints` MUST be passed to each hook. The hook MUST NOT alter the `hook hints` structure.