Module: Magick::Rails::Events
- Defined in:
- lib/magick/rails/events.rb
Constant Summary collapse
- EVENT_PREFIX =
Event names (using Rails 8.1 structured event format)
'magick.feature_flag'- EVENTS =
{ changed: "#{EVENT_PREFIX}.changed", enabled: "#{EVENT_PREFIX}.enabled", disabled: "#{EVENT_PREFIX}.disabled", enabled_globally: "#{EVENT_PREFIX}.enabled_globally", disabled_globally: "#{EVENT_PREFIX}.disabled_globally", dependency_added: "#{EVENT_PREFIX}.dependency_added", dependency_removed: "#{EVENT_PREFIX}.dependency_removed", variant_set: "#{EVENT_PREFIX}.variant_set", variant_selected: "#{EVENT_PREFIX}.variant_selected", targeting_added: "#{EVENT_PREFIX}.targeting_added", targeting_removed: "#{EVENT_PREFIX}.targeting_removed", version_saved: "#{EVENT_PREFIX}.version_saved", rollback: "#{EVENT_PREFIX}.rollback", exported: "#{EVENT_PREFIX}.exported", imported: "#{EVENT_PREFIX}.imported", audit_logged: "#{EVENT_PREFIX}.audit_logged", usage_tracked: "#{EVENT_PREFIX}.usage_tracked", deprecated_warning: "#{EVENT_PREFIX}.deprecated_warning", adapter_write_failed: "#{EVENT_PREFIX}.adapter_write_failed" }.freeze
Class Method Summary collapse
-
.adapter_write_failed(feature_name, backend:, operation:, error_class: nil, error_message: nil, reason: nil, **metadata) ⇒ Object
A write to a shared backend (Redis / ActiveRecord) failed or was dropped.
-
.audit_logged(feature_name, action:, user_id: nil, changes: {}, **metadata) ⇒ Object
Audit log entry created.
-
.dependency_added(feature_name, dependency_name, **metadata) ⇒ Object
Dependency added.
-
.dependency_removed(feature_name, dependency_name, **metadata) ⇒ Object
Dependency removed.
-
.deprecated_warning(feature_name, **metadata) ⇒ Object
Deprecation warning.
-
.exported(format:, feature_count:, **metadata) ⇒ Object
Export performed.
-
.feature_changed(feature_name, changes:, user_id: nil, **metadata) ⇒ Object
Feature flag changed (value, status, etc.).
-
.feature_disabled(feature_name, context: {}, **metadata) ⇒ Object
Feature disabled.
-
.feature_disabled_globally(feature_name, user_id: nil, **metadata) ⇒ Object
Feature disabled globally (no targeting).
-
.feature_enabled(feature_name, context: {}, **metadata) ⇒ Object
Feature enabled.
-
.feature_enabled_globally(feature_name, user_id: nil, **metadata) ⇒ Object
Feature enabled globally (no targeting).
-
.imported(format:, feature_count:, **metadata) ⇒ Object
Import performed.
- .notify(event_name, payload = {}) ⇒ Object
-
.rails81? ⇒ Boolean
Check if Rails 8.1+ structured events are available.
-
.rails8? ⇒ Boolean
Backward compatibility alias.
-
.rollback(feature_name, version:, **metadata) ⇒ Object
Rollback performed.
-
.targeting_added(feature_name, targeting_type:, targeting_value:, **metadata) ⇒ Object
Targeting added.
-
.targeting_removed(feature_name, targeting_type:, targeting_value: nil, **metadata) ⇒ Object
Targeting removed.
-
.usage_tracked(feature_name, operation:, duration:, success: true, **metadata) ⇒ Object
Usage tracked.
-
.variant_selected(feature_name, variant_name:, context: {}, **metadata) ⇒ Object
Variant selected.
-
.variant_set(feature_name, variants:, **metadata) ⇒ Object
Variants set.
-
.version_saved(feature_name, version:, created_by: nil, **metadata) ⇒ Object
Version saved.
Class Method Details
.adapter_write_failed(feature_name, backend:, operation:, error_class: nil, error_message: nil, reason: nil, **metadata) ⇒ Object
A write to a shared backend (Redis / ActiveRecord) failed or was dropped. Memory has already been updated and is never rolled back, so this process is now serving a value the rest of the fleet does not have. Subscribe to alert on backend divergence.
236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/magick/rails/events.rb', line 236 def self.adapter_write_failed(feature_name, backend:, operation:, error_class: nil, error_message: nil, reason: nil, **) notify(:adapter_write_failed, { feature_name: feature_name.to_s, backend: backend.to_s, operation: operation.to_s, error_class: error_class, error_message: , reason: reason, timestamp: Time.now.iso8601, ** }) end |
.audit_logged(feature_name, action:, user_id: nil, changes: {}, **metadata) ⇒ Object
Audit log entry created
209 210 211 212 213 214 215 216 217 218 |
# File 'lib/magick/rails/events.rb', line 209 def self.audit_logged(feature_name, action:, user_id: nil, changes: {}, **) notify(:audit_logged, { feature_name: feature_name.to_s, action: action.to_s, user_id: user_id, changes: changes, timestamp: Time.now.iso8601, ** }) end |
.dependency_added(feature_name, dependency_name, **metadata) ⇒ Object
Dependency added
105 106 107 108 109 110 111 112 |
# File 'lib/magick/rails/events.rb', line 105 def self.dependency_added(feature_name, dependency_name, **) notify(:dependency_added, { feature_name: feature_name.to_s, dependency_name: dependency_name.to_s, timestamp: Time.now.iso8601, ** }) end |
.dependency_removed(feature_name, dependency_name, **metadata) ⇒ Object
Dependency removed
115 116 117 118 119 120 121 122 |
# File 'lib/magick/rails/events.rb', line 115 def self.dependency_removed(feature_name, dependency_name, **) notify(:dependency_removed, { feature_name: feature_name.to_s, dependency_name: dependency_name.to_s, timestamp: Time.now.iso8601, ** }) end |
.deprecated_warning(feature_name, **metadata) ⇒ Object
Deprecation warning
251 252 253 254 255 256 257 |
# File 'lib/magick/rails/events.rb', line 251 def self.deprecated_warning(feature_name, **) notify(:deprecated_warning, { feature_name: feature_name.to_s, timestamp: Time.now.iso8601, ** }) end |
.exported(format:, feature_count:, **metadata) ⇒ Object
Export performed
189 190 191 192 193 194 195 196 |
# File 'lib/magick/rails/events.rb', line 189 def self.exported(format:, feature_count:, **) notify(:exported, { format: format.to_s, feature_count: feature_count, timestamp: Time.now.iso8601, ** }) end |
.feature_changed(feature_name, changes:, user_id: nil, **metadata) ⇒ Object
Feature flag changed (value, status, etc.)
54 55 56 57 58 59 60 61 62 |
# File 'lib/magick/rails/events.rb', line 54 def self.feature_changed(feature_name, changes:, user_id: nil, **) notify(:changed, { feature_name: feature_name.to_s, changes: changes, user_id: user_id, timestamp: Time.now.iso8601, ** }) end |
.feature_disabled(feature_name, context: {}, **metadata) ⇒ Object
Feature disabled
75 76 77 78 79 80 81 82 |
# File 'lib/magick/rails/events.rb', line 75 def self.feature_disabled(feature_name, context: {}, **) notify(:disabled, { feature_name: feature_name.to_s, context: context, timestamp: Time.now.iso8601, ** }) end |
.feature_disabled_globally(feature_name, user_id: nil, **metadata) ⇒ Object
Feature disabled globally (no targeting)
95 96 97 98 99 100 101 102 |
# File 'lib/magick/rails/events.rb', line 95 def self.feature_disabled_globally(feature_name, user_id: nil, **) notify(:disabled_globally, { feature_name: feature_name.to_s, user_id: user_id, timestamp: Time.now.iso8601, ** }) end |
.feature_enabled(feature_name, context: {}, **metadata) ⇒ Object
Feature enabled
65 66 67 68 69 70 71 72 |
# File 'lib/magick/rails/events.rb', line 65 def self.feature_enabled(feature_name, context: {}, **) notify(:enabled, { feature_name: feature_name.to_s, context: context, timestamp: Time.now.iso8601, ** }) end |
.feature_enabled_globally(feature_name, user_id: nil, **metadata) ⇒ Object
Feature enabled globally (no targeting)
85 86 87 88 89 90 91 92 |
# File 'lib/magick/rails/events.rb', line 85 def self.feature_enabled_globally(feature_name, user_id: nil, **) notify(:enabled_globally, { feature_name: feature_name.to_s, user_id: user_id, timestamp: Time.now.iso8601, ** }) end |
.imported(format:, feature_count:, **metadata) ⇒ Object
Import performed
199 200 201 202 203 204 205 206 |
# File 'lib/magick/rails/events.rb', line 199 def self.imported(format:, feature_count:, **) notify(:imported, { format: format.to_s, feature_count: feature_count, timestamp: Time.now.iso8601, ** }) end |
.notify(event_name, payload = {}) ⇒ Object
41 42 43 44 45 46 |
# File 'lib/magick/rails/events.rb', line 41 def self.notify(event_name, payload = {}) return unless rails81? event_name_str = EVENTS[event_name] || event_name.to_s ::Rails.event.notify(event_name_str, payload) end |
.rails81? ⇒ Boolean
Check if Rails 8.1+ structured events are available.
::Rails is spelled out on purpose: this module is nested inside
Magick::Rails, so a bare Rails resolves lexically to the enclosing
Magick::Rails module and never to the framework — which silently made
every event in this file a no-op inside a real Rails app.
12 13 14 |
# File 'lib/magick/rails/events.rb', line 12 def self.rails81? defined?(::Rails) && ::Rails.respond_to?(:event) && ::Rails.event.respond_to?(:notify) end |
.rails8? ⇒ Boolean
Backward compatibility alias
49 50 51 |
# File 'lib/magick/rails/events.rb', line 49 def self.rails8? rails81? end |
.rollback(feature_name, version:, **metadata) ⇒ Object
Rollback performed
179 180 181 182 183 184 185 186 |
# File 'lib/magick/rails/events.rb', line 179 def self.rollback(feature_name, version:, **) notify(:rollback, { feature_name: feature_name.to_s, version: version, timestamp: Time.now.iso8601, ** }) end |
.targeting_added(feature_name, targeting_type:, targeting_value:, **metadata) ⇒ Object
Targeting added
146 147 148 149 150 151 152 153 154 |
# File 'lib/magick/rails/events.rb', line 146 def self.targeting_added(feature_name, targeting_type:, targeting_value:, **) notify(:targeting_added, { feature_name: feature_name.to_s, targeting_type: targeting_type.to_s, targeting_value: targeting_value, timestamp: Time.now.iso8601, ** }) end |
.targeting_removed(feature_name, targeting_type:, targeting_value: nil, **metadata) ⇒ Object
Targeting removed
157 158 159 160 161 162 163 164 165 |
# File 'lib/magick/rails/events.rb', line 157 def self.targeting_removed(feature_name, targeting_type:, targeting_value: nil, **) notify(:targeting_removed, { feature_name: feature_name.to_s, targeting_type: targeting_type.to_s, targeting_value: targeting_value, timestamp: Time.now.iso8601, ** }) end |
.usage_tracked(feature_name, operation:, duration:, success: true, **metadata) ⇒ Object
Usage tracked
221 222 223 224 225 226 227 228 229 230 |
# File 'lib/magick/rails/events.rb', line 221 def self.usage_tracked(feature_name, operation:, duration:, success: true, **) notify(:usage_tracked, { feature_name: feature_name.to_s, operation: operation.to_s, duration: duration, success: success, timestamp: Time.now.iso8601, ** }) end |
.variant_selected(feature_name, variant_name:, context: {}, **metadata) ⇒ Object
Variant selected
135 136 137 138 139 140 141 142 143 |
# File 'lib/magick/rails/events.rb', line 135 def self.variant_selected(feature_name, variant_name:, context: {}, **) notify(:variant_selected, { feature_name: feature_name.to_s, variant_name: variant_name.to_s, context: context, timestamp: Time.now.iso8601, ** }) end |
.variant_set(feature_name, variants:, **metadata) ⇒ Object
Variants set
125 126 127 128 129 130 131 132 |
# File 'lib/magick/rails/events.rb', line 125 def self.variant_set(feature_name, variants:, **) notify(:variant_set, { feature_name: feature_name.to_s, variants: variants.is_a?(Array) ? variants.map(&:to_h) : variants, timestamp: Time.now.iso8601, ** }) end |
.version_saved(feature_name, version:, created_by: nil, **metadata) ⇒ Object
Version saved
168 169 170 171 172 173 174 175 176 |
# File 'lib/magick/rails/events.rb', line 168 def self.version_saved(feature_name, version:, created_by: nil, **) notify(:version_saved, { feature_name: feature_name.to_s, version: version, created_by: created_by, timestamp: Time.now.iso8601, ** }) end |