openfeature-sdk 0.6.4 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/.ruby-version +1 -1
- data/.simplecov +1 -0
- data/.tool-versions +1 -1
- data/.yardopts +5 -0
- data/CHANGELOG.md +7 -0
- data/CLAUDE.md +3 -0
- data/CONTRIBUTING.md +15 -1
- data/Gemfile +17 -2
- data/Gemfile.lock +72 -13
- data/README.md +14 -2
- data/Rakefile +14 -0
- data/SECURITY.md +10 -0
- data/Steepfile +7 -0
- data/examples/basic_usage.rb +22 -0
- data/examples/custom_provider.rb +56 -0
- data/examples/rails_integration.rb +60 -0
- data/lib/open_feature/sdk/version.rb +1 -1
- data/openfeature-sdk.gemspec +34 -0
- data/rbs_collection.lock.yaml +292 -0
- data/rbs_collection.yaml +14 -0
- data/sig/open_feature/sdk/api.rbs +35 -0
- data/sig/open_feature/sdk/client.rbs +49 -0
- data/sig/open_feature/sdk/client_metadata.rbs +11 -0
- data/sig/open_feature/sdk/configuration.rbs +43 -0
- data/sig/open_feature/sdk/evaluation_context.rbs +19 -0
- data/sig/open_feature/sdk/evaluation_context_builder.rbs +7 -0
- data/sig/open_feature/sdk/evaluation_details.rbs +19 -0
- data/sig/open_feature/sdk/event_dispatcher.rbs +24 -0
- data/sig/open_feature/sdk/hooks/hints.rbs +30 -0
- data/sig/open_feature/sdk/hooks/hook.rbs +19 -0
- data/sig/open_feature/sdk/hooks/hook_context.rbs +18 -0
- data/sig/open_feature/sdk/hooks/hook_executor.rbs +20 -0
- data/sig/open_feature/sdk/hooks/logging_hook.rbs +25 -0
- data/sig/open_feature/sdk/provider/error_code.rbs +16 -0
- data/sig/open_feature/sdk/provider/event_emitter.rbs +16 -0
- data/sig/open_feature/sdk/provider/in_memory_provider.rbs +35 -0
- data/sig/open_feature/sdk/provider/no_op_provider.rbs +25 -0
- data/sig/open_feature/sdk/provider/provider_metadata.rbs +11 -0
- data/sig/open_feature/sdk/provider/reason.rbs +17 -0
- data/sig/open_feature/sdk/provider/resolution_details.rbs +19 -0
- data/sig/open_feature/sdk/provider.rbs +24 -0
- data/sig/open_feature/sdk/provider_event.rbs +12 -0
- data/sig/open_feature/sdk/provider_initialization_error.rbs +11 -0
- data/sig/open_feature/sdk/provider_state.rbs +13 -0
- data/sig/open_feature/sdk/provider_state_registry.rbs +22 -0
- data/sig/open_feature/sdk/telemetry.rbs +29 -0
- data/sig/open_feature/sdk/thread_local_transaction_context_propagator.rbs +12 -0
- data/sig/open_feature/sdk/tracking_event_details.rbs +10 -0
- data/sig/open_feature/sdk/transaction_context_propagator.rbs +11 -0
- data/sig/open_feature/sdk/version.rbs +5 -0
- data/sig/open_feature/sdk.rbs +22 -0
- metadata +52 -139
- data/docs/plans/2026-03-07-telemetry-utility-design.md +0 -98
- data/docs/plans/2026-03-07-telemetry-utility-plan.md +0 -578
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
module Provider
|
|
4
|
+
class InMemoryProvider
|
|
5
|
+
include Provider::EventEmitter
|
|
6
|
+
|
|
7
|
+
NAME: String
|
|
8
|
+
|
|
9
|
+
attr_reader metadata: ProviderMetadata
|
|
10
|
+
|
|
11
|
+
def initialize: (?Hash[String, untyped] flags) -> void
|
|
12
|
+
|
|
13
|
+
def init: (?EvaluationContext? evaluation_context) -> void
|
|
14
|
+
def shutdown: () -> void
|
|
15
|
+
|
|
16
|
+
def add_flag: (flag_key: String, value: untyped) -> void
|
|
17
|
+
def update_flags: (Hash[String, untyped] new_flags) -> void
|
|
18
|
+
|
|
19
|
+
def fetch_boolean_value: (flag_key: String, default_value: bool, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
20
|
+
def fetch_string_value: (flag_key: String, default_value: String, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
21
|
+
def fetch_number_value: (flag_key: String, default_value: Numeric, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
22
|
+
def fetch_integer_value: (flag_key: String, default_value: Integer, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
23
|
+
def fetch_float_value: (flag_key: String, default_value: Float, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
24
|
+
def fetch_object_value: (flag_key: String, default_value: Array[untyped] | Hash[untyped, untyped], ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
attr_reader flags: Hash[String, untyped]
|
|
29
|
+
|
|
30
|
+
def fetch_value: (flag_key: String, default_value: untyped, evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
31
|
+
def emit_provider_changed: (Array[String] flag_keys) -> void
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
module Provider
|
|
4
|
+
class NoOpProvider
|
|
5
|
+
REASON_NO_OP: String
|
|
6
|
+
NAME: String
|
|
7
|
+
|
|
8
|
+
attr_reader metadata: ProviderMetadata
|
|
9
|
+
|
|
10
|
+
def initialize: () -> void
|
|
11
|
+
|
|
12
|
+
def fetch_boolean_value: (flag_key: String, default_value: bool, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
13
|
+
def fetch_string_value: (flag_key: String, default_value: String, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
14
|
+
def fetch_number_value: (flag_key: String, default_value: Numeric, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
15
|
+
def fetch_integer_value: (flag_key: String, default_value: Integer, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
16
|
+
def fetch_float_value: (flag_key: String, default_value: Float, ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
17
|
+
def fetch_object_value: (flag_key: String, default_value: Array[untyped] | Hash[untyped, untyped], ?evaluation_context: EvaluationContext?) -> ResolutionDetails
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def no_op: (untyped default_value) -> ResolutionDetails
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
module Provider
|
|
4
|
+
module Reason
|
|
5
|
+
STATIC: String
|
|
6
|
+
DEFAULT: String
|
|
7
|
+
TARGETING_MATCH: String
|
|
8
|
+
SPLIT: String
|
|
9
|
+
CACHED: String
|
|
10
|
+
DISABLED: String
|
|
11
|
+
UNKNOWN: String
|
|
12
|
+
STALE: String
|
|
13
|
+
ERROR: String
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
module Provider
|
|
4
|
+
EMPTY_FLAG_METADATA: Hash[String, untyped]
|
|
5
|
+
|
|
6
|
+
class ResolutionDetails < Struct[untyped]
|
|
7
|
+
attr_accessor value: untyped
|
|
8
|
+
attr_accessor reason: String?
|
|
9
|
+
attr_accessor variant: String?
|
|
10
|
+
attr_accessor error_code: String?
|
|
11
|
+
attr_accessor error_message: String?
|
|
12
|
+
|
|
13
|
+
def initialize: (?value: untyped, ?reason: String?, ?variant: String?, ?error_code: String?, ?error_message: String?, ?flag_metadata: Hash[String, untyped]?) -> void
|
|
14
|
+
|
|
15
|
+
def flag_metadata: () -> Hash[String, untyped]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
module Provider
|
|
4
|
+
interface _Provider
|
|
5
|
+
def fetch_boolean_value: (flag_key: String, default_value: bool, ?evaluation_context: EvaluationContext?) -> Provider::ResolutionDetails
|
|
6
|
+
def fetch_string_value: (flag_key: String, default_value: String, ?evaluation_context: EvaluationContext?) -> Provider::ResolutionDetails
|
|
7
|
+
def fetch_number_value: (flag_key: String, default_value: Numeric, ?evaluation_context: EvaluationContext?) -> Provider::ResolutionDetails
|
|
8
|
+
def fetch_integer_value: (flag_key: String, default_value: Integer, ?evaluation_context: EvaluationContext?) -> Provider::ResolutionDetails
|
|
9
|
+
def fetch_float_value: (flag_key: String, default_value: Float, ?evaluation_context: EvaluationContext?) -> Provider::ResolutionDetails
|
|
10
|
+
def fetch_object_value: (flag_key: String, default_value: Array[untyped] | Hash[untyped, untyped], ?evaluation_context: EvaluationContext?) -> Provider::ResolutionDetails
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
interface _LifecycleProvider
|
|
14
|
+
def init: (?EvaluationContext? evaluation_context) -> void
|
|
15
|
+
def shutdown: () -> void
|
|
16
|
+
def metadata: () -> ProviderMetadata
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
interface _TrackableProvider
|
|
20
|
+
def track: (String tracking_event_name, ?evaluation_context: EvaluationContext?, ?tracking_event_details: TrackingEventDetails?) -> void
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
class ProviderInitializationError < StandardError
|
|
4
|
+
attr_reader provider: untyped
|
|
5
|
+
attr_reader original_error: Exception?
|
|
6
|
+
attr_reader error_code: String
|
|
7
|
+
|
|
8
|
+
def initialize: (String message, ?provider: untyped, ?original_error: Exception?, ?error_code: String) -> void
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
class ProviderStateRegistry
|
|
4
|
+
def initialize: () -> void
|
|
5
|
+
|
|
6
|
+
def set_initial_state: (untyped provider, ?String state) -> void
|
|
7
|
+
def update_state_from_event: (untyped provider, String event_type, ?Hash[Symbol, untyped]? event_details) -> String
|
|
8
|
+
def get_state: (untyped provider) -> String
|
|
9
|
+
def get_details: (untyped provider) -> Hash[Symbol, untyped]
|
|
10
|
+
def remove_provider: (untyped provider) -> void
|
|
11
|
+
def tracked?: (untyped provider) -> bool
|
|
12
|
+
def ready?: (untyped provider) -> bool
|
|
13
|
+
def error?: (untyped provider) -> bool
|
|
14
|
+
def clear: () -> void
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def state_from_event: (String event_type, ?Hash[Symbol, untyped]? event_details) -> String?
|
|
19
|
+
def state_from_error_event: (Hash[Symbol, untyped]? event_details) -> String
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
module Telemetry
|
|
4
|
+
EVENT_NAME: String
|
|
5
|
+
|
|
6
|
+
FLAG_KEY: String
|
|
7
|
+
CONTEXT_ID_KEY: String
|
|
8
|
+
ERROR_MESSAGE_KEY: String
|
|
9
|
+
ERROR_TYPE_KEY: String
|
|
10
|
+
PROVIDER_NAME_KEY: String
|
|
11
|
+
RESULT_REASON_KEY: String
|
|
12
|
+
RESULT_VALUE_KEY: String
|
|
13
|
+
RESULT_VARIANT_KEY: String
|
|
14
|
+
FLAG_SET_ID_KEY: String
|
|
15
|
+
VERSION_KEY: String
|
|
16
|
+
|
|
17
|
+
METADATA_KEY_MAP: Hash[String, String]
|
|
18
|
+
|
|
19
|
+
class EvaluationEvent < Struct[untyped]
|
|
20
|
+
attr_accessor name: String
|
|
21
|
+
attr_accessor attributes: Hash[String, untyped]
|
|
22
|
+
|
|
23
|
+
def initialize: (?name: String, ?attributes: Hash[String, untyped]) -> void
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.create_evaluation_event: (hook_context: Hooks::HookContext, evaluation_details: EvaluationDetails?) -> EvaluationEvent
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
class ThreadLocalTransactionContextPropagator
|
|
4
|
+
include TransactionContextPropagator
|
|
5
|
+
|
|
6
|
+
THREAD_KEY: Symbol
|
|
7
|
+
|
|
8
|
+
def set_transaction_context: (EvaluationContext evaluation_context) -> void
|
|
9
|
+
def get_transaction_context: () -> EvaluationContext?
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
interface _TransactionContextPropagator
|
|
4
|
+
def set_transaction_context: (EvaluationContext evaluation_context) -> void
|
|
5
|
+
def get_transaction_context: () -> EvaluationContext?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module TransactionContextPropagator : _TransactionContextPropagator
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module OpenFeature
|
|
2
|
+
module SDK
|
|
3
|
+
# Delegated to API.instance via method_missing
|
|
4
|
+
def self.configure: () { (Configuration) -> void } -> void
|
|
5
|
+
def self.build_client: (?domain: String?, ?evaluation_context: EvaluationContext?) -> Client
|
|
6
|
+
def self.configuration: () -> Configuration
|
|
7
|
+
def self.provider: (?domain: String?) -> untyped?
|
|
8
|
+
def self.set_provider: (untyped provider, ?domain: String?) -> void
|
|
9
|
+
def self.set_provider_and_wait: (untyped provider, ?domain: String?) -> void
|
|
10
|
+
def self.hooks: () -> Array[untyped]
|
|
11
|
+
def self.add_hooks: (*Array[untyped] new_hooks) -> void
|
|
12
|
+
def self.evaluation_context: () -> EvaluationContext?
|
|
13
|
+
def self.add_handler: (String event_type, _ToProc handler) -> void
|
|
14
|
+
def self.remove_handler: (String event_type, _ToProc handler) -> void
|
|
15
|
+
def self.logger: () -> untyped?
|
|
16
|
+
def self.logger=: (untyped? new_logger) -> void
|
|
17
|
+
def self.set_transaction_context_propagator: (_TransactionContextPropagator propagator) -> void
|
|
18
|
+
def self.set_transaction_context: (EvaluationContext evaluation_context) -> void
|
|
19
|
+
def self.shutdown: () -> void
|
|
20
|
+
def self.provider_metadata: (?domain: String?) -> Provider::ProviderMetadata?
|
|
21
|
+
end
|
|
22
|
+
end
|
metadata
CHANGED
|
@@ -1,142 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openfeature-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenFeature Authors
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
-
dependencies:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - ">="
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0'
|
|
19
|
-
type: :development
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - ">="
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0'
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: markly
|
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
|
29
|
-
requirements:
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0'
|
|
33
|
-
type: :development
|
|
34
|
-
prerelease: false
|
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
-
requirements:
|
|
37
|
-
- - ">="
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0'
|
|
40
|
-
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: rake
|
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - "~>"
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '13.0'
|
|
47
|
-
type: :development
|
|
48
|
-
prerelease: false
|
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - "~>"
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '13.0'
|
|
54
|
-
- !ruby/object:Gem::Dependency
|
|
55
|
-
name: rspec
|
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
|
57
|
-
requirements:
|
|
58
|
-
- - "~>"
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: 3.12.0
|
|
61
|
-
type: :development
|
|
62
|
-
prerelease: false
|
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - "~>"
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: 3.12.0
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: standard
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - ">="
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '0'
|
|
75
|
-
type: :development
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - ">="
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '0'
|
|
82
|
-
- !ruby/object:Gem::Dependency
|
|
83
|
-
name: standard-performance
|
|
84
|
-
requirement: !ruby/object:Gem::Requirement
|
|
85
|
-
requirements:
|
|
86
|
-
- - ">="
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version: '0'
|
|
89
|
-
type: :development
|
|
90
|
-
prerelease: false
|
|
91
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - ">="
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0'
|
|
96
|
-
- !ruby/object:Gem::Dependency
|
|
97
|
-
name: simplecov
|
|
98
|
-
requirement: !ruby/object:Gem::Requirement
|
|
99
|
-
requirements:
|
|
100
|
-
- - "~>"
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
version: 0.22.0
|
|
103
|
-
type: :development
|
|
104
|
-
prerelease: false
|
|
105
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
-
requirements:
|
|
107
|
-
- - "~>"
|
|
108
|
-
- !ruby/object:Gem::Version
|
|
109
|
-
version: 0.22.0
|
|
110
|
-
- !ruby/object:Gem::Dependency
|
|
111
|
-
name: simplecov-cobertura
|
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
|
113
|
-
requirements:
|
|
114
|
-
- - "~>"
|
|
115
|
-
- !ruby/object:Gem::Version
|
|
116
|
-
version: '3.0'
|
|
117
|
-
type: :development
|
|
118
|
-
prerelease: false
|
|
119
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
-
requirements:
|
|
121
|
-
- - "~>"
|
|
122
|
-
- !ruby/object:Gem::Version
|
|
123
|
-
version: '3.0'
|
|
124
|
-
- !ruby/object:Gem::Dependency
|
|
125
|
-
name: timecop
|
|
126
|
-
requirement: !ruby/object:Gem::Requirement
|
|
127
|
-
requirements:
|
|
128
|
-
- - "~>"
|
|
129
|
-
- !ruby/object:Gem::Version
|
|
130
|
-
version: 0.9.10
|
|
131
|
-
type: :development
|
|
132
|
-
prerelease: false
|
|
133
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
-
requirements:
|
|
135
|
-
- - "~>"
|
|
136
|
-
- !ruby/object:Gem::Version
|
|
137
|
-
version: 0.9.10
|
|
138
|
-
description: Ruby SDK for an the specifications for the open standard of feature flag
|
|
139
|
-
management
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Ruby SDK for the OpenFeature specification, an open standard for feature
|
|
13
|
+
flag management
|
|
140
14
|
email:
|
|
141
15
|
- cncf-openfeature-contributors@lists.cncf.io
|
|
142
16
|
executables: []
|
|
@@ -149,6 +23,7 @@ files:
|
|
|
149
23
|
- ".simplecov"
|
|
150
24
|
- ".standard.yml"
|
|
151
25
|
- ".tool-versions"
|
|
26
|
+
- ".yardopts"
|
|
152
27
|
- CHANGELOG.md
|
|
153
28
|
- CLAUDE.md
|
|
154
29
|
- CODEOWNERS
|
|
@@ -159,9 +34,12 @@ files:
|
|
|
159
34
|
- LICENSE
|
|
160
35
|
- README.md
|
|
161
36
|
- Rakefile
|
|
37
|
+
- SECURITY.md
|
|
38
|
+
- Steepfile
|
|
162
39
|
- cucumber.yml
|
|
163
|
-
-
|
|
164
|
-
-
|
|
40
|
+
- examples/basic_usage.rb
|
|
41
|
+
- examples/custom_provider.rb
|
|
42
|
+
- examples/rails_integration.rb
|
|
165
43
|
- lib/open_feature/sdk.rb
|
|
166
44
|
- lib/open_feature/sdk/api.rb
|
|
167
45
|
- lib/open_feature/sdk/client.rb
|
|
@@ -194,17 +72,52 @@ files:
|
|
|
194
72
|
- lib/open_feature/sdk/tracking_event_details.rb
|
|
195
73
|
- lib/open_feature/sdk/transaction_context_propagator.rb
|
|
196
74
|
- lib/open_feature/sdk/version.rb
|
|
75
|
+
- openfeature-sdk.gemspec
|
|
76
|
+
- rbs_collection.lock.yaml
|
|
77
|
+
- rbs_collection.yaml
|
|
197
78
|
- release-please-config.json
|
|
198
79
|
- renovate.json
|
|
199
|
-
|
|
80
|
+
- sig/open_feature/sdk.rbs
|
|
81
|
+
- sig/open_feature/sdk/api.rbs
|
|
82
|
+
- sig/open_feature/sdk/client.rbs
|
|
83
|
+
- sig/open_feature/sdk/client_metadata.rbs
|
|
84
|
+
- sig/open_feature/sdk/configuration.rbs
|
|
85
|
+
- sig/open_feature/sdk/evaluation_context.rbs
|
|
86
|
+
- sig/open_feature/sdk/evaluation_context_builder.rbs
|
|
87
|
+
- sig/open_feature/sdk/evaluation_details.rbs
|
|
88
|
+
- sig/open_feature/sdk/event_dispatcher.rbs
|
|
89
|
+
- sig/open_feature/sdk/hooks/hints.rbs
|
|
90
|
+
- sig/open_feature/sdk/hooks/hook.rbs
|
|
91
|
+
- sig/open_feature/sdk/hooks/hook_context.rbs
|
|
92
|
+
- sig/open_feature/sdk/hooks/hook_executor.rbs
|
|
93
|
+
- sig/open_feature/sdk/hooks/logging_hook.rbs
|
|
94
|
+
- sig/open_feature/sdk/provider.rbs
|
|
95
|
+
- sig/open_feature/sdk/provider/error_code.rbs
|
|
96
|
+
- sig/open_feature/sdk/provider/event_emitter.rbs
|
|
97
|
+
- sig/open_feature/sdk/provider/in_memory_provider.rbs
|
|
98
|
+
- sig/open_feature/sdk/provider/no_op_provider.rbs
|
|
99
|
+
- sig/open_feature/sdk/provider/provider_metadata.rbs
|
|
100
|
+
- sig/open_feature/sdk/provider/reason.rbs
|
|
101
|
+
- sig/open_feature/sdk/provider/resolution_details.rbs
|
|
102
|
+
- sig/open_feature/sdk/provider_event.rbs
|
|
103
|
+
- sig/open_feature/sdk/provider_initialization_error.rbs
|
|
104
|
+
- sig/open_feature/sdk/provider_state.rbs
|
|
105
|
+
- sig/open_feature/sdk/provider_state_registry.rbs
|
|
106
|
+
- sig/open_feature/sdk/telemetry.rbs
|
|
107
|
+
- sig/open_feature/sdk/thread_local_transaction_context_propagator.rbs
|
|
108
|
+
- sig/open_feature/sdk/tracking_event_details.rbs
|
|
109
|
+
- sig/open_feature/sdk/transaction_context_propagator.rbs
|
|
110
|
+
- sig/open_feature/sdk/version.rbs
|
|
111
|
+
homepage: https://github.com/open-feature/ruby-sdk
|
|
200
112
|
licenses:
|
|
201
113
|
- Apache-2.0
|
|
202
114
|
metadata:
|
|
203
|
-
homepage_uri: https://github.com/open-feature/
|
|
204
|
-
source_code_uri: https://github.com/open-feature/
|
|
205
|
-
changelog_uri: https://github.com/open-feature/
|
|
206
|
-
bug_tracker_uri: https://github.com/open-feature/
|
|
207
|
-
documentation_uri: https://github.com/open-feature/
|
|
115
|
+
homepage_uri: https://github.com/open-feature/ruby-sdk
|
|
116
|
+
source_code_uri: https://github.com/open-feature/ruby-sdk
|
|
117
|
+
changelog_uri: https://github.com/open-feature/ruby-sdk/blob/main/CHANGELOG.md
|
|
118
|
+
bug_tracker_uri: https://github.com/open-feature/ruby-sdk/issues
|
|
119
|
+
documentation_uri: https://github.com/open-feature/ruby-sdk#readme
|
|
120
|
+
rubygems_mfa_required: 'true'
|
|
208
121
|
rdoc_options: []
|
|
209
122
|
require_paths:
|
|
210
123
|
- lib
|
|
@@ -219,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
219
132
|
- !ruby/object:Gem::Version
|
|
220
133
|
version: '0'
|
|
221
134
|
requirements: []
|
|
222
|
-
rubygems_version: 4.0.
|
|
135
|
+
rubygems_version: 4.0.6
|
|
223
136
|
specification_version: 4
|
|
224
137
|
summary: OpenFeature SDK for Ruby
|
|
225
138
|
test_files: []
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# Telemetry Utility Design
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Add an OTel-compatible telemetry utility to the OpenFeature Ruby SDK that creates
|
|
6
|
-
structured evaluation events from hook context and evaluation details. This utility
|
|
7
|
-
is dependency-free (no OTel gem required) and follows the pattern established by
|
|
8
|
-
the Go SDK's `telemetry` package.
|
|
9
|
-
|
|
10
|
-
Addresses: https://github.com/open-feature/ruby-sdk/issues/176
|
|
11
|
-
|
|
12
|
-
## References
|
|
13
|
-
|
|
14
|
-
- [OpenFeature Spec Appendix D (Observability)](https://openfeature.dev/specification/appendix-d/)
|
|
15
|
-
- [OTel Semantic Conventions for Feature Flags](https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/)
|
|
16
|
-
- [Go SDK telemetry package](https://github.com/open-feature/go-sdk/tree/main/openfeature/telemetry)
|
|
17
|
-
- [JS SDK reference PR](https://github.com/open-feature/js-sdk/pull/1120)
|
|
18
|
-
|
|
19
|
-
## Design Decisions
|
|
20
|
-
|
|
21
|
-
1. **Single public method** accepting `hook_context:` and `evaluation_details:` keyword
|
|
22
|
-
arguments — mirrors the `finally` hook stage signature for zero-friction integration.
|
|
23
|
-
2. **Returns a Struct** (`EvaluationEvent`) with `name` and `attributes` fields — matches
|
|
24
|
-
the SDK's existing Struct conventions (`ResolutionDetails`, `ClientMetadata`, etc.).
|
|
25
|
-
3. **Constants in the Telemetry module directly** — flat namespace matching Go SDK and
|
|
26
|
-
existing Ruby SDK patterns (e.g., `Provider::Reason`).
|
|
27
|
-
4. **Hard-coded metadata mappings only** — maps `contextId`, `flagSetId`, `version` from
|
|
28
|
-
flag metadata to OTel keys. Unknown metadata keys are ignored. Custom attributes can
|
|
29
|
-
be added via hooks in ruby-sdk-contrib.
|
|
30
|
-
5. **No third-party dependencies** — pure data transformation using only standard library.
|
|
31
|
-
|
|
32
|
-
## File Structure
|
|
33
|
-
|
|
34
|
-
- `lib/open_feature/sdk/telemetry.rb` — module with constants, struct, and utility function
|
|
35
|
-
- `spec/open_feature/sdk/telemetry_spec.rb` — tests
|
|
36
|
-
- `lib/open_feature/sdk.rb` — add `require_relative "sdk/telemetry"`
|
|
37
|
-
|
|
38
|
-
## Constants
|
|
39
|
-
|
|
40
|
-
```ruby
|
|
41
|
-
EVENT_NAME = "feature_flag.evaluation"
|
|
42
|
-
|
|
43
|
-
FLAG_KEY = "feature_flag.key"
|
|
44
|
-
CONTEXT_ID_KEY = "feature_flag.context.id"
|
|
45
|
-
ERROR_MESSAGE_KEY = "error.message"
|
|
46
|
-
ERROR_TYPE_KEY = "error.type"
|
|
47
|
-
PROVIDER_NAME_KEY = "feature_flag.provider.name"
|
|
48
|
-
RESULT_REASON_KEY = "feature_flag.result.reason"
|
|
49
|
-
RESULT_VALUE_KEY = "feature_flag.result.value"
|
|
50
|
-
RESULT_VARIANT_KEY = "feature_flag.result.variant"
|
|
51
|
-
FLAG_SET_ID_KEY = "feature_flag.set.id"
|
|
52
|
-
VERSION_KEY = "feature_flag.version"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Public API
|
|
56
|
-
|
|
57
|
-
```ruby
|
|
58
|
-
OpenFeature::SDK::Telemetry.create_evaluation_event(
|
|
59
|
-
hook_context:, # Hooks::HookContext
|
|
60
|
-
evaluation_details: # EvaluationDetails or nil
|
|
61
|
-
) # => EvaluationEvent
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Returns `EvaluationEvent = Struct.new(:name, :attributes, keyword_init: true)`.
|
|
65
|
-
|
|
66
|
-
## Attribute Population Rules
|
|
67
|
-
|
|
68
|
-
| Attribute | Source | Condition |
|
|
69
|
-
|-----------|--------|-----------|
|
|
70
|
-
| `feature_flag.key` | `hook_context.flag_key` | Always |
|
|
71
|
-
| `feature_flag.provider.name` | `hook_context.provider_metadata.name` | When present |
|
|
72
|
-
| `feature_flag.result.variant` | `evaluation_details.variant` | When present (takes precedence over value) |
|
|
73
|
-
| `feature_flag.result.value` | `evaluation_details.value` | Only when variant is nil |
|
|
74
|
-
| `feature_flag.result.reason` | `evaluation_details.reason.downcase` | When present |
|
|
75
|
-
| `error.type` | `evaluation_details.error_code.downcase` | When error occurred |
|
|
76
|
-
| `error.message` | `evaluation_details.error_message` | When error occurred |
|
|
77
|
-
| `feature_flag.context.id` | `targeting_key` or metadata `contextId` | Metadata takes precedence |
|
|
78
|
-
| `feature_flag.set.id` | metadata `flagSetId` | When present in flag_metadata |
|
|
79
|
-
| `feature_flag.version` | metadata `version` | When present in flag_metadata |
|
|
80
|
-
|
|
81
|
-
## Error Handling
|
|
82
|
-
|
|
83
|
-
No defensive `rescue` in the utility — it is a pure data transformation. Nil inputs
|
|
84
|
-
are handled via guard clauses. The calling hook is responsible for exception safety
|
|
85
|
-
(consistent with the existing hook executor pattern).
|
|
86
|
-
|
|
87
|
-
## Test Plan
|
|
88
|
-
|
|
89
|
-
1. Happy path with all attributes populated
|
|
90
|
-
2. Variant vs value precedence
|
|
91
|
-
3. Enum downcasing (reason and error_code)
|
|
92
|
-
4. Error attributes present only on error
|
|
93
|
-
5. Nil evaluation_details
|
|
94
|
-
6. Nil/empty flag_metadata
|
|
95
|
-
7. Metadata contextId overrides targeting_key
|
|
96
|
-
8. Targeting key fallback when no contextId
|
|
97
|
-
9. Unknown metadata keys ignored
|
|
98
|
-
10. Return type verification
|