diff --git a/.github/workflows/contributor-workflow.yml b/.github/workflows/contributor-workflow.yml
index 1aabe94..541fb08 100644
--- a/.github/workflows/contributor-workflow.yml
+++ b/.github/workflows/contributor-workflow.yml
@@ -113,4 +113,4 @@ jobs:
dart-server-sdk-openfeature/info_report.txt
dart-server-sdk-openfeature/warning_report.txt
dart-server-sdk-openfeature/error_report.txt
- retention-days: 7
+ retention-days: 7
\ No newline at end of file
diff --git a/.github/workflows/notifications.yml b/.github/workflows/notifications.yml
index 8e3470d..040de79 100644
--- a/.github/workflows/notifications.yml
+++ b/.github/workflows/notifications.yml
@@ -1,7 +1,6 @@
name: Notifications
on:
- pull_request:
push:
branches:
- main
diff --git a/.gitignore b/.gitignore
index 05d0295..1801d87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
.dart_tool/
-pubspec.lock
+**/pubspec.lock
diff --git a/README.md b/README.md
index 72e3372..f8598cc 100644
--- a/README.md
+++ b/README.md
@@ -26,17 +26,17 @@
-
-
+
+
-
+
-
-
+
+
@@ -68,15 +68,15 @@ See [TBD](TBD) for the complete API documentation.
| Status | Features | Description |
| ------ |---------------------------------| --------------------------------------------------------------------------------------------------------------------------------- |
-| ❌ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
-| ❌ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
-| ❌ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
-| ❌ | [Logging](#logging) | Integrate with popular logging packages. |
-| ❌ | [Domains](#domains) | Logically bind clients with providers.|
-| ❌ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
-| ❌ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
-| ❌ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
-| ❌ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
+| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
+| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
+| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
+| ✅ | [Logging](#logging) | Integrate with popular logging packages. |
+| ✅ | [Domains](#domains) | Logically bind clients with providers.|
+| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
+| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
+| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
+| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌
diff --git a/lib/hooks.dart b/lib/hooks.dart
index 7dd6d9d..1a3166c 100644
--- a/lib/hooks.dart
+++ b/lib/hooks.dart
@@ -1,5 +1,6 @@
-// Hook interface and default hooks.
+// Hook interface with OpenTelemetry support
import 'dart:async';
+import 'dart:convert';
/// Defines the stages in the hook lifecycle
/// Used internally by the hook manager for execution ordering
@@ -7,7 +8,7 @@ enum HookStage {
BEFORE, // Before flag evaluation
AFTER, // After successful evaluation
ERROR, // When an error occurs
- FINALLY // Always executed last
+ FINALLY, // Always executed last
}
/// Hook priority levels
@@ -15,7 +16,7 @@ enum HookPriority {
CRITICAL, // Highest priority, executes first
HIGH, // High priority
NORMAL, // Default priority
- LOW // Lowest priority
+ LOW, // Lowest priority
}
/// Configuration for hook behavior
@@ -46,6 +47,25 @@ class HookMetadata {
});
}
+/// Details about the evaluation result
+class EvaluationDetails {
+ final String flagKey;
+ final dynamic value;
+ final String? variant;
+ final String reason;
+ final DateTime evaluationTime;
+ final Map? additionalDetails;
+
+ EvaluationDetails({
+ required this.flagKey,
+ required this.value,
+ this.variant,
+ this.reason = 'DEFAULT',
+ required this.evaluationTime,
+ this.additionalDetails,
+ });
+}
+
/// Context passed to hooks during execution
class HookContext {
final String flagKey;
@@ -63,6 +83,13 @@ class HookContext {
});
}
+/// Optional hints for hook execution
+class HookHints {
+ final Map hints;
+
+ const HookHints({this.hints = const {}});
+}
+
/// Interface for implementing hooks
abstract class Hook {
/// Hook metadata and configuration
@@ -77,8 +104,12 @@ abstract class Hook {
/// When an error occurs
Future error(HookContext context);
- /// Always executed at the end
- Future finally_(HookContext context);
+ /// Always executed at the end, now with evaluation details parameter
+ Future finally_(
+ HookContext context,
+ EvaluationDetails? evaluationDetails, [
+ HookHints? hints,
+ ]);
}
/// Manager for hook registration and execution
@@ -90,8 +121,8 @@ class HookManager {
HookManager({
bool failFast = false,
Duration defaultTimeout = const Duration(seconds: 5),
- }) : _failFast = failFast,
- _defaultTimeout = defaultTimeout;
+ }) : _failFast = failFast,
+ _defaultTimeout = defaultTimeout;
/// Register a new hook
void addHook(Hook hook) {
@@ -106,6 +137,8 @@ class HookManager {
Map? context, {
dynamic result,
Exception? error,
+ EvaluationDetails? evaluationDetails,
+ HookHints? hints,
}) async {
final hookContext = HookContext(
flagKey: flagKey,
@@ -121,6 +154,8 @@ class HookManager {
stage,
hookContext,
hook.metadata.config.timeout,
+ evaluationDetails,
+ hints,
);
} catch (e) {
if (_failFast || !hook.metadata.config.continueOnError) {
@@ -133,8 +168,9 @@ class HookManager {
/// Sort hooks by priority
void _sortHooks() {
- _hooks.sort((a, b) =>
- a.metadata.priority.index.compareTo(b.metadata.priority.index));
+ _hooks.sort(
+ (a, b) => a.metadata.priority.index.compareTo(b.metadata.priority.index),
+ );
}
/// Execute a single hook with timeout
@@ -143,6 +179,8 @@ class HookManager {
HookStage stage,
HookContext context,
Duration? timeout,
+ EvaluationDetails? evaluationDetails,
+ HookHints? hints,
) async {
final effectiveTimeout = timeout ?? _defaultTimeout;
@@ -158,7 +196,7 @@ class HookManager {
hookExecution = hook.error(context);
break;
case HookStage.FINALLY:
- hookExecution = hook.finally_(context);
+ hookExecution = hook.finally_(context, evaluationDetails, hints);
break;
}
@@ -172,3 +210,269 @@ class HookManager {
);
}
}
+
+/// A base hook implementation with empty methods
+abstract class BaseHook implements Hook {
+ @override
+ final HookMetadata metadata;
+
+ BaseHook({required this.metadata});
+
+ @override
+ Future before(HookContext context) async {}
+
+ @override
+ Future after(HookContext context) async {}
+
+ @override
+ Future error(HookContext context) async {}
+
+ @override
+ Future finally_(
+ HookContext context,
+ EvaluationDetails? evaluationDetails, [
+ HookHints? hints,
+ ]) async {}
+}
+
+//
+// OpenTelemetry Support
+//
+
+/// OpenTelemetry semantic conventions for feature flags
+/// Based on https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-spans/
+class OTelFeatureFlagConstants {
+ /// Common attributes
+ static const String FEATURE_FLAG = 'feature_flag';
+ static const String FLAG_KEY = 'feature_flag.key';
+ static const String FLAG_PROVIDER_NAME = 'feature_flag.provider_name';
+ static const String FLAG_VARIANT = 'feature_flag.variant';
+
+ /// Value type specific attributes
+ static const String FLAG_EVALUATED = 'feature_flag.evaluated';
+ static const String FLAG_VALUE_TYPE = 'feature_flag.value_type';
+ static const String FLAG_VALUE_BOOLEAN = 'feature_flag.value.boolean';
+ static const String FLAG_VALUE_STRING = 'feature_flag.value.string';
+ static const String FLAG_VALUE_INT = 'feature_flag.value.int';
+ static const String FLAG_VALUE_FLOAT = 'feature_flag.value.float';
+
+ /// Reason constants
+ static const String REASON = 'feature_flag.reason';
+ static const String REASON_DEFAULT = 'DEFAULT';
+ static const String REASON_TARGETING_MATCH = 'TARGETING_MATCH';
+ static const String REASON_SPLIT = 'SPLIT';
+ static const String REASON_CACHED = 'CACHED';
+ static const String REASON_ERROR = 'ERROR';
+ static const String REASON_DISABLED = 'DISABLED';
+ static const String REASON_UNKNOWN = 'UNKNOWN';
+
+ /// Value types
+ static const String TYPE_BOOLEAN = 'BOOLEAN';
+ static const String TYPE_STRING = 'STRING';
+ static const String TYPE_INT = 'INTEGER';
+ static const String TYPE_DOUBLE = 'FLOAT';
+ static const String TYPE_OBJECT = 'OBJECT';
+}
+
+/// Represents an OpenTelemetry attribute
+class OTelAttribute {
+ final String key;
+ final dynamic value;
+
+ const OTelAttribute(this.key, this.value);
+
+ Map toJson() => {key: value};
+}
+
+/// A collection of OpenTelemetry attributes
+class OTelAttributes {
+ final List attributes;
+
+ const OTelAttributes(this.attributes);
+
+ Map toJson() {
+ final result = {};
+ for (final attr in attributes) {
+ result.addAll(attr.toJson());
+ }
+ return result;
+ }
+
+ @override
+ String toString() => jsonEncode(toJson());
+}
+
+/// Utility class for generating OpenTelemetry-compatible telemetry from feature flag evaluations
+class OpenTelemetryUtil {
+ /// Creates OpenTelemetry-compatible attributes for a feature flag evaluation
+ ///
+ /// These attributes follow the OpenTelemetry semantic conventions for feature flags.
+ /// They can be used with any OpenTelemetry-compatible telemetry system.
+ static OTelAttributes createOTelAttributes({
+ required String flagKey,
+ required dynamic value,
+ String? providerName,
+ String? variant,
+ String reason = OTelFeatureFlagConstants.REASON_DEFAULT,
+ Map? evaluationContext,
+ }) {
+ final attributes = [];
+
+ // Add common attributes
+ attributes.add(OTelAttribute(OTelFeatureFlagConstants.FLAG_KEY, flagKey));
+ attributes.add(
+ OTelAttribute(OTelFeatureFlagConstants.FLAG_EVALUATED, true),
+ );
+
+ if (providerName != null && providerName.isNotEmpty) {
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_PROVIDER_NAME,
+ providerName,
+ ),
+ );
+ }
+
+ if (variant != null && variant.isNotEmpty) {
+ attributes.add(
+ OTelAttribute(OTelFeatureFlagConstants.FLAG_VARIANT, variant),
+ );
+ }
+
+ attributes.add(OTelAttribute(OTelFeatureFlagConstants.REASON, reason));
+
+ // Add value and determine type
+ if (value != null) {
+ if (value is bool) {
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_VALUE_TYPE,
+ OTelFeatureFlagConstants.TYPE_BOOLEAN,
+ ),
+ );
+ attributes.add(
+ OTelAttribute(OTelFeatureFlagConstants.FLAG_VALUE_BOOLEAN, value),
+ );
+ } else if (value is String) {
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_VALUE_TYPE,
+ OTelFeatureFlagConstants.TYPE_STRING,
+ ),
+ );
+ attributes.add(
+ OTelAttribute(OTelFeatureFlagConstants.FLAG_VALUE_STRING, value),
+ );
+ } else if (value is int) {
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_VALUE_TYPE,
+ OTelFeatureFlagConstants.TYPE_INT,
+ ),
+ );
+ attributes.add(
+ OTelAttribute(OTelFeatureFlagConstants.FLAG_VALUE_INT, value),
+ );
+ } else if (value is double) {
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_VALUE_TYPE,
+ OTelFeatureFlagConstants.TYPE_DOUBLE,
+ ),
+ );
+ attributes.add(
+ OTelAttribute(OTelFeatureFlagConstants.FLAG_VALUE_FLOAT, value),
+ );
+ } else {
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_VALUE_TYPE,
+ OTelFeatureFlagConstants.TYPE_OBJECT,
+ ),
+ );
+ // For non-primitive types, we convert to a string representation
+ attributes.add(
+ OTelAttribute(
+ OTelFeatureFlagConstants.FLAG_VALUE_STRING,
+ value.toString(),
+ ),
+ );
+ }
+ }
+
+ return OTelAttributes(attributes);
+ }
+
+ /// Creates OpenTelemetry-compatible attributes from EvaluationDetails
+ ///
+ /// This is a convenience method for use in hooks, especially the finally_ hook.
+ static OTelAttributes fromEvaluationDetails(
+ EvaluationDetails details, {
+ String? providerName,
+ }) {
+ return createOTelAttributes(
+ flagKey: details.flagKey,
+ value: details.value,
+ providerName: providerName,
+ variant: details.variant,
+ reason: details.reason,
+ );
+ }
+
+ /// Creates OpenTelemetry-compatible attributes from HookContext
+ ///
+ /// This is a convenience method for use in hooks when EvaluationDetails is not available.
+ static OTelAttributes fromHookContext(
+ HookContext context, {
+ String? providerName,
+ String? reason,
+ }) {
+ return createOTelAttributes(
+ flagKey: context.flagKey,
+ value: context.result,
+ providerName: providerName,
+ reason:
+ reason ??
+ (context.error != null
+ ? OTelFeatureFlagConstants.REASON_ERROR
+ : OTelFeatureFlagConstants.REASON_DEFAULT),
+ evaluationContext: context.evaluationContext,
+ );
+ }
+}
+
+/// A hook that generates OpenTelemetry-compatible telemetry
+class OpenTelemetryHook extends BaseHook {
+ final String providerName;
+ final void Function(OTelAttributes)? telemetryCallback;
+
+ OpenTelemetryHook({
+ required this.providerName,
+ this.telemetryCallback,
+ HookPriority priority = HookPriority.NORMAL,
+ }) : super(
+ metadata: HookMetadata(name: 'OpenTelemetryHook', priority: priority),
+ );
+
+ @override
+ Future finally_(
+ HookContext context,
+ EvaluationDetails? evaluationDetails, [
+ HookHints? hints,
+ ]) async {
+ // Generate OpenTelemetry attributes
+ final otelAttributes =
+ evaluationDetails != null
+ ? OpenTelemetryUtil.fromEvaluationDetails(
+ evaluationDetails,
+ providerName: providerName,
+ )
+ : OpenTelemetryUtil.fromHookContext(
+ context,
+ providerName: providerName,
+ );
+
+ // Call the telemetry callback if provided
+ telemetryCallback?.call(otelAttributes);
+ }
+}
diff --git a/pubspec.lock b/pubspec.lock
deleted file mode 100644
index 3358167..0000000
--- a/pubspec.lock
+++ /dev/null
@@ -1,474 +0,0 @@
-# Generated by pub
-# See https://dart.dev/tools/pub/glossary#lockfile
-packages:
- _fe_analyzer_shared:
- dependency: transitive
- description:
- name: _fe_analyzer_shared
- sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
- url: "https://pub.dev"
- source: hosted
- version: "76.0.0"
- _macros:
- dependency: transitive
- description: dart
- source: sdk
- version: "0.3.3"
- analyzer:
- dependency: transitive
- description:
- name: analyzer
- sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
- url: "https://pub.dev"
- source: hosted
- version: "6.11.0"
- args:
- dependency: transitive
- description:
- name: args
- sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
- url: "https://pub.dev"
- source: hosted
- version: "2.6.0"
- async:
- dependency: transitive
- description:
- name: async
- sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
- url: "https://pub.dev"
- source: hosted
- version: "2.12.0"
- boolean_selector:
- dependency: transitive
- description:
- name: boolean_selector
- sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.2"
- build:
- dependency: transitive
- description:
- name: build
- sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
- url: "https://pub.dev"
- source: hosted
- version: "2.4.2"
- built_collection:
- dependency: transitive
- description:
- name: built_collection
- sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
- url: "https://pub.dev"
- source: hosted
- version: "5.1.1"
- built_value:
- dependency: transitive
- description:
- name: built_value
- sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
- url: "https://pub.dev"
- source: hosted
- version: "8.9.2"
- code_builder:
- dependency: transitive
- description:
- name: code_builder
- sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
- url: "https://pub.dev"
- source: hosted
- version: "4.10.1"
- collection:
- dependency: "direct main"
- description:
- name: collection
- sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
- url: "https://pub.dev"
- source: hosted
- version: "1.19.1"
- convert:
- dependency: transitive
- description:
- name: convert
- sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
- url: "https://pub.dev"
- source: hosted
- version: "3.1.2"
- coverage:
- dependency: transitive
- description:
- name: coverage
- sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43
- url: "https://pub.dev"
- source: hosted
- version: "1.11.1"
- crypto:
- dependency: transitive
- description:
- name: crypto
- sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.6"
- dart_style:
- dependency: transitive
- description:
- name: dart_style
- sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
- url: "https://pub.dev"
- source: hosted
- version: "2.3.7"
- file:
- dependency: transitive
- description:
- name: file
- sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
- url: "https://pub.dev"
- source: hosted
- version: "7.0.1"
- fixnum:
- dependency: transitive
- description:
- name: fixnum
- sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
- url: "https://pub.dev"
- source: hosted
- version: "1.1.1"
- frontend_server_client:
- dependency: transitive
- description:
- name: frontend_server_client
- sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
- url: "https://pub.dev"
- source: hosted
- version: "4.0.0"
- git_hooks:
- dependency: "direct dev"
- description:
- name: git_hooks
- sha256: f379143e5c710057e78a49b6016b000661ddd07aa0e56df9a7def3bbff5a98e9
- url: "https://pub.dev"
- source: hosted
- version: "1.0.2"
- glob:
- dependency: transitive
- description:
- name: glob
- sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.2"
- http_multi_server:
- dependency: transitive
- description:
- name: http_multi_server
- sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
- url: "https://pub.dev"
- source: hosted
- version: "3.2.2"
- http_parser:
- dependency: transitive
- description:
- name: http_parser
- sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
- url: "https://pub.dev"
- source: hosted
- version: "4.1.1"
- io:
- dependency: transitive
- description:
- name: io
- sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
- url: "https://pub.dev"
- source: hosted
- version: "1.0.5"
- js:
- dependency: transitive
- description:
- name: js
- sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
- url: "https://pub.dev"
- source: hosted
- version: "0.7.1"
- lints:
- dependency: "direct dev"
- description:
- name: lints
- sha256: "4a16b3f03741e1252fda5de3ce712666d010ba2122f8e912c94f9f7b90e1a4c3"
- url: "https://pub.dev"
- source: hosted
- version: "5.1.0"
- logging:
- dependency: "direct main"
- description:
- name: logging
- sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
- url: "https://pub.dev"
- source: hosted
- version: "1.3.0"
- macros:
- dependency: transitive
- description:
- name: macros
- sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
- url: "https://pub.dev"
- source: hosted
- version: "0.1.3-main.0"
- matcher:
- dependency: transitive
- description:
- name: matcher
- sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
- url: "https://pub.dev"
- source: hosted
- version: "0.12.16+1"
- meta:
- dependency: "direct main"
- description:
- name: meta
- sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
- url: "https://pub.dev"
- source: hosted
- version: "1.16.0"
- mime:
- dependency: transitive
- description:
- name: mime
- sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
- url: "https://pub.dev"
- source: hosted
- version: "2.0.0"
- mockito:
- dependency: "direct dev"
- description:
- name: mockito
- sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917"
- url: "https://pub.dev"
- source: hosted
- version: "5.4.4"
- node_preamble:
- dependency: transitive
- description:
- name: node_preamble
- sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
- url: "https://pub.dev"
- source: hosted
- version: "2.0.2"
- package_config:
- dependency: transitive
- description:
- name: package_config
- sha256: "92d4488434b520a62570293fbd33bb556c7d49230791c1b4bbd973baf6d2dc67"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.1"
- path:
- dependency: transitive
- description:
- name: path
- sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
- url: "https://pub.dev"
- source: hosted
- version: "1.9.1"
- pool:
- dependency: transitive
- description:
- name: pool
- sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
- url: "https://pub.dev"
- source: hosted
- version: "1.5.1"
- pub_semver:
- dependency: transitive
- description:
- name: pub_semver
- sha256: "7b3cfbf654f3edd0c6298ecd5be782ce997ddf0e00531b9464b55245185bbbbd"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.5"
- shelf:
- dependency: transitive
- description:
- name: shelf
- sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
- url: "https://pub.dev"
- source: hosted
- version: "1.4.2"
- shelf_packages_handler:
- dependency: transitive
- description:
- name: shelf_packages_handler
- sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.2"
- shelf_static:
- dependency: transitive
- description:
- name: shelf_static
- sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
- url: "https://pub.dev"
- source: hosted
- version: "1.1.3"
- shelf_web_socket:
- dependency: transitive
- description:
- name: shelf_web_socket
- sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
- url: "https://pub.dev"
- source: hosted
- version: "2.0.1"
- source_gen:
- dependency: transitive
- description:
- name: source_gen
- sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
- url: "https://pub.dev"
- source: hosted
- version: "1.5.0"
- source_map_stack_trace:
- dependency: transitive
- description:
- name: source_map_stack_trace
- sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
- url: "https://pub.dev"
- source: hosted
- version: "2.1.2"
- source_maps:
- dependency: transitive
- description:
- name: source_maps
- sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
- url: "https://pub.dev"
- source: hosted
- version: "0.10.13"
- source_span:
- dependency: transitive
- description:
- name: source_span
- sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
- url: "https://pub.dev"
- source: hosted
- version: "1.10.1"
- stack_trace:
- dependency: transitive
- description:
- name: stack_trace
- sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
- url: "https://pub.dev"
- source: hosted
- version: "1.12.0"
- stream_channel:
- dependency: transitive
- description:
- name: stream_channel
- sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
- url: "https://pub.dev"
- source: hosted
- version: "2.1.2"
- string_scanner:
- dependency: transitive
- description:
- name: string_scanner
- sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
- url: "https://pub.dev"
- source: hosted
- version: "1.4.1"
- term_glyph:
- dependency: transitive
- description:
- name: term_glyph
- sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
- url: "https://pub.dev"
- source: hosted
- version: "1.2.2"
- test:
- dependency: "direct dev"
- description:
- name: test
- sha256: "22eb7769bee38c7e032d532e8daa2e1cc901b799f603550a4db8f3a5f5173ea2"
- url: "https://pub.dev"
- source: hosted
- version: "1.25.12"
- test_api:
- dependency: transitive
- description:
- name: test_api
- sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
- url: "https://pub.dev"
- source: hosted
- version: "0.7.4"
- test_core:
- dependency: transitive
- description:
- name: test_core
- sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
- url: "https://pub.dev"
- source: hosted
- version: "0.6.8"
- typed_data:
- dependency: transitive
- description:
- name: typed_data
- sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
- url: "https://pub.dev"
- source: hosted
- version: "1.4.0"
- vm_service:
- dependency: transitive
- description:
- name: vm_service
- sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
- url: "https://pub.dev"
- source: hosted
- version: "15.0.0"
- watcher:
- dependency: transitive
- description:
- name: watcher
- sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
- url: "https://pub.dev"
- source: hosted
- version: "1.1.1"
- web:
- dependency: transitive
- description:
- name: web
- sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
- url: "https://pub.dev"
- source: hosted
- version: "1.1.0"
- web_socket:
- dependency: transitive
- description:
- name: web_socket
- sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
- url: "https://pub.dev"
- source: hosted
- version: "0.1.6"
- web_socket_channel:
- dependency: transitive
- description:
- name: web_socket_channel
- sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.1"
- webkit_inspection_protocol:
- dependency: transitive
- description:
- name: webkit_inspection_protocol
- sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
- url: "https://pub.dev"
- source: hosted
- version: "1.2.1"
- yaml:
- dependency: transitive
- description:
- name: yaml
- sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
- url: "https://pub.dev"
- source: hosted
- version: "3.1.2"
-sdks:
- dart: ">=3.7.2 <4.0.0"
diff --git a/test.txt b/test.txt
deleted file mode 100644
index 7581981..0000000
--- a/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-Testing for pipeline trigger. Add content to test
\ No newline at end of file
diff --git a/test/hooks_test.dart b/test/hooks_test.dart
index f54d8fc..e0b03ea 100644
--- a/test/hooks_test.dart
+++ b/test/hooks_test.dart
@@ -5,14 +5,13 @@ import '../lib/hooks.dart';
class TestHook implements Hook {
final List executionOrder = [];
final HookPriority _priority;
+ bool receivedEvaluationDetails = false;
TestHook([this._priority = HookPriority.NORMAL]);
@override
- HookMetadata get metadata => HookMetadata(
- name: 'TestHook',
- priority: _priority,
- );
+ HookMetadata get metadata =>
+ HookMetadata(name: 'TestHook', priority: _priority);
@override
Future before(HookContext context) async {
@@ -30,46 +29,49 @@ class TestHook implements Hook {
}
@override
- Future finally_(HookContext context) async {
+ Future finally_(
+ HookContext context,
+ EvaluationDetails? evaluationDetails, [
+ HookHints? hints,
+ ]) async {
executionOrder.add('finally');
+ if (evaluationDetails != null) {
+ receivedEvaluationDetails = true;
+ }
+ if (hints != null) {
+ executionOrder.add('with_hints');
+ }
}
}
-class ErrorHook implements Hook {
- @override
- HookMetadata get metadata => HookMetadata(name: 'ErrorHook');
-
- @override
- Future before(HookContext context) async {
- throw Exception('Test error');
- }
-
- @override
- Future after(HookContext context) async {}
- @override
- Future error(HookContext context) async {}
- @override
- Future finally_(HookContext context) async {}
-}
+class OTelTestHook extends OpenTelemetryHook {
+ final List