magick-feature-flags 0.9.20 → 0.9.22
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/lib/magick/feature.rb +49 -3
- data/lib/magick/performance_metrics.rb +30 -15
- data/lib/magick/version.rb +1 -1
- data/lib/magick.rb +6 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 42699b3af1d542ac14b10f2b82ea4156da27b68e3e2a07e715cd528f0e3f936b
|
|
4
|
+
data.tar.gz: 0c5235c6cb220201ed0443d1a4633009325d410620d8d28ecbb836cac01bdc25
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10fb678c4aeaf5a17f721341e01ec937bf9a14042e4a90fa0bcc1aba13c5e91272aba144fa05913a020660ffd602ccf7481d216e92364338c7e4a111794e0896
|
|
7
|
+
data.tar.gz: '079e2d11d6ab0339929f965c1eb05fc934ea88522f26e268df324c366ad28268f87131233fe0f2315a5494328ae5fa18790e8e512fa550372852c3c1d61c3faf'
|
data/lib/magick/feature.rb
CHANGED
|
@@ -33,15 +33,55 @@ module Magick
|
|
|
33
33
|
# Update targeting empty cache after loading
|
|
34
34
|
@_targeting_empty = @targeting.empty?
|
|
35
35
|
# Cache performance metrics availability (check once, not on every call)
|
|
36
|
-
|
|
36
|
+
# Only enable if performance_metrics exists AND is actually being used
|
|
37
|
+
@_perf_metrics_enabled = !Magick.performance_metrics.nil?
|
|
37
38
|
# Save description and display_name to adapter if they were provided and not already in adapter
|
|
38
39
|
save_metadata_if_new
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def enabled?(context = {})
|
|
42
|
-
#
|
|
43
|
-
|
|
43
|
+
# Check performance metrics dynamically (in case enabled after feature creation)
|
|
44
|
+
# But cache the check result for performance
|
|
45
|
+
perf_metrics = Magick.performance_metrics
|
|
46
|
+
perf_metrics_enabled = !perf_metrics.nil?
|
|
47
|
+
|
|
48
|
+
# Update cached flag if it changed
|
|
49
|
+
@_perf_metrics_enabled = perf_metrics_enabled if @_perf_metrics_enabled != perf_metrics_enabled
|
|
50
|
+
|
|
51
|
+
# Fast path: if performance metrics disabled, skip all overhead
|
|
52
|
+
return check_enabled(context) unless perf_metrics_enabled
|
|
53
|
+
|
|
54
|
+
# Performance metrics enabled: measure and record
|
|
55
|
+
# Use inline timing to avoid function call overhead
|
|
56
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
57
|
+
result = check_enabled(context)
|
|
58
|
+
duration = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000 # milliseconds
|
|
59
|
+
|
|
60
|
+
# Record metrics (fast path - minimal overhead)
|
|
61
|
+
perf_metrics.record(name, 'enabled?', duration, success: true)
|
|
62
|
+
|
|
63
|
+
# Rails 8+ events (only in development or when explicitly enabled)
|
|
64
|
+
if @_rails_events_enabled
|
|
65
|
+
if result
|
|
66
|
+
Magick::Rails::Events.feature_enabled(name, context: context)
|
|
67
|
+
else
|
|
68
|
+
Magick::Rails::Events.feature_disabled(name, context: context)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Warn if deprecated (only if enabled)
|
|
73
|
+
if status == :deprecated && result && !context[:allow_deprecated] && Magick.warn_on_deprecated
|
|
74
|
+
warn "DEPRECATED: Feature '#{name}' is deprecated and will be removed."
|
|
75
|
+
Magick::Rails::Events.deprecated_warning(name) if @_rails_events_enabled
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
result
|
|
44
79
|
rescue StandardError => e
|
|
80
|
+
# Record error metrics if enabled
|
|
81
|
+
if perf_metrics_enabled && perf_metrics
|
|
82
|
+
duration = defined?(start_time) && start_time ? (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000 : 0.0
|
|
83
|
+
perf_metrics.record(name, 'enabled?', duration, success: false)
|
|
84
|
+
end
|
|
45
85
|
# Return false on any error (fail-safe)
|
|
46
86
|
warn "Magick: Error checking feature '#{name}': #{e.message}" if defined?(Rails) && Rails.env.development?
|
|
47
87
|
false
|
|
@@ -452,6 +492,10 @@ module Magick
|
|
|
452
492
|
# Reload feature state from adapter (useful when feature is changed externally)
|
|
453
493
|
def reload
|
|
454
494
|
load_from_adapter
|
|
495
|
+
# Update targeting empty cache
|
|
496
|
+
@_targeting_empty = @targeting.empty?
|
|
497
|
+
# Update performance metrics flag (in case it was enabled after feature creation)
|
|
498
|
+
@_perf_metrics_enabled = !Magick.performance_metrics.nil?
|
|
455
499
|
# Update registered feature instance if it exists
|
|
456
500
|
if Magick.features.key?(name)
|
|
457
501
|
registered = Magick.features[name]
|
|
@@ -461,6 +505,8 @@ module Magick
|
|
|
461
505
|
registered.instance_variable_set(:@description, @description)
|
|
462
506
|
registered.instance_variable_set(:@display_name, @display_name)
|
|
463
507
|
registered.instance_variable_set(:@targeting, @targeting.dup)
|
|
508
|
+
registered.instance_variable_set(:@_targeting_empty, @_targeting_empty)
|
|
509
|
+
registered.instance_variable_set(:@_perf_metrics_enabled, @_perf_metrics_enabled)
|
|
464
510
|
end
|
|
465
511
|
true
|
|
466
512
|
end
|
|
@@ -36,44 +36,59 @@ module Magick
|
|
|
36
36
|
# If redis_enabled is explicitly set, use it; otherwise default to false
|
|
37
37
|
# It will be enabled later via enable_redis_tracking if Redis adapter is available
|
|
38
38
|
@redis_enabled = redis_enabled.nil? ? false : redis_enabled
|
|
39
|
+
# Cache expensive checks for performance
|
|
40
|
+
@_rails_events_enabled = defined?(Magick::Rails::Events) && Magick::Rails::Events.rails8?
|
|
41
|
+
@_adapter_available = nil # Will be cached on first check
|
|
42
|
+
@_redis_available = nil # Will be cached on first check
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# Public accessor for redis_enabled
|
|
42
46
|
attr_reader :redis_enabled
|
|
43
47
|
|
|
44
48
|
def record(feature_name, operation, duration, success: true)
|
|
49
|
+
# Fast path: minimize work in mutex
|
|
45
50
|
feature_name_str = feature_name.to_s
|
|
46
|
-
metric = Metric.new(feature_name_str, operation, duration, success: success)
|
|
47
51
|
|
|
52
|
+
# Minimize mutex lock time - only update counters
|
|
53
|
+
pending_count = nil
|
|
54
|
+
total_pending = nil
|
|
48
55
|
@mutex.synchronize do
|
|
49
|
-
|
|
56
|
+
# Only create Metric object if we're keeping metrics in memory
|
|
57
|
+
# Most of the time we just need counters, not full metric objects
|
|
58
|
+
if @metrics.length < 1000
|
|
59
|
+
metric = Metric.new(feature_name_str, operation, duration, success: success)
|
|
60
|
+
@metrics << metric
|
|
61
|
+
end
|
|
50
62
|
@usage_count[feature_name_str] += 1
|
|
51
63
|
@pending_updates[feature_name_str] += 1
|
|
64
|
+
pending_count = @pending_updates[feature_name_str]
|
|
65
|
+
total_pending = @pending_updates.values.sum
|
|
52
66
|
# Keep only last 1000 metrics (as a safety limit)
|
|
53
|
-
# Note: Metrics are removed from memory after flushing to Redis to reduce memory usage
|
|
54
67
|
@metrics.shift if @metrics.length > 1000
|
|
55
68
|
end
|
|
56
69
|
|
|
57
|
-
# Rails 8+ event for usage tracking
|
|
58
|
-
if
|
|
70
|
+
# Rails 8+ event for usage tracking (cached check)
|
|
71
|
+
if @_rails_events_enabled
|
|
59
72
|
Magick::Rails::Events.usage_tracked(feature_name, operation: operation, duration: duration, success: success)
|
|
60
73
|
end
|
|
61
74
|
|
|
62
|
-
# Batch flush
|
|
63
|
-
|
|
75
|
+
# Batch flush check - only if we're close to batch size (avoid expensive checks)
|
|
76
|
+
# Check pending count first before doing expensive adapter checks
|
|
77
|
+
flush_to_redis_if_needed if pending_count >= @batch_size || total_pending >= @batch_size
|
|
64
78
|
|
|
65
|
-
metric
|
|
79
|
+
nil # Don't return metric object to avoid allocation overhead
|
|
66
80
|
end
|
|
67
81
|
|
|
68
82
|
def flush_to_redis_if_needed
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
# Cache adapter availability check (expensive)
|
|
84
|
+
if @_adapter_available.nil?
|
|
85
|
+
adapter = Magick.adapter_registry || Magick.default_adapter_registry
|
|
86
|
+
@_adapter_available = adapter
|
|
87
|
+
@_redis_available = adapter.is_a?(Magick::Adapters::Registry) && adapter.redis_available? if adapter
|
|
88
|
+
end
|
|
75
89
|
|
|
76
|
-
return unless
|
|
90
|
+
return unless @_adapter_available
|
|
91
|
+
return unless @_redis_available || @redis_enabled
|
|
77
92
|
return if @pending_updates.empty?
|
|
78
93
|
|
|
79
94
|
should_flush = false
|
data/lib/magick/version.rb
CHANGED
data/lib/magick.rb
CHANGED
|
@@ -38,6 +38,12 @@ module Magick
|
|
|
38
38
|
if value && adapter_registry.is_a?(Adapters::Registry) && adapter_registry.redis_available?
|
|
39
39
|
value.enable_redis_tracking(enable: true)
|
|
40
40
|
end
|
|
41
|
+
# Update all existing features to enable performance metrics tracking
|
|
42
|
+
if value
|
|
43
|
+
features.each_value do |feature|
|
|
44
|
+
feature.instance_variable_set(:@_perf_metrics_enabled, true)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
41
47
|
value
|
|
42
48
|
end
|
|
43
49
|
|