e11y 0.1.0
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 +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +69 -0
- data/CHANGELOG.md +26 -0
- data/CODE_OF_CONDUCT.md +64 -0
- data/LICENSE.txt +21 -0
- data/README.md +179 -0
- data/Rakefile +37 -0
- data/benchmarks/run_all.rb +33 -0
- data/config/README.md +83 -0
- data/config/loki-local-config.yaml +35 -0
- data/config/prometheus.yml +15 -0
- data/docker-compose.yml +78 -0
- data/docs/00-ICP-AND-TIMELINE.md +483 -0
- data/docs/01-SCALE-REQUIREMENTS.md +858 -0
- data/docs/ADR-001-architecture.md +2617 -0
- data/docs/ADR-002-metrics-yabeda.md +1395 -0
- data/docs/ADR-003-slo-observability.md +3337 -0
- data/docs/ADR-004-adapter-architecture.md +2385 -0
- data/docs/ADR-005-tracing-context.md +1372 -0
- data/docs/ADR-006-security-compliance.md +4143 -0
- data/docs/ADR-007-opentelemetry-integration.md +1385 -0
- data/docs/ADR-008-rails-integration.md +1911 -0
- data/docs/ADR-009-cost-optimization.md +2993 -0
- data/docs/ADR-010-developer-experience.md +2166 -0
- data/docs/ADR-011-testing-strategy.md +1836 -0
- data/docs/ADR-012-event-evolution.md +958 -0
- data/docs/ADR-013-reliability-error-handling.md +2750 -0
- data/docs/ADR-014-event-driven-slo.md +1533 -0
- data/docs/ADR-015-middleware-order.md +1061 -0
- data/docs/ADR-016-self-monitoring-slo.md +1234 -0
- data/docs/API-REFERENCE-L28.md +914 -0
- data/docs/COMPREHENSIVE-CONFIGURATION.md +2366 -0
- data/docs/IMPLEMENTATION_NOTES.md +2804 -0
- data/docs/IMPLEMENTATION_PLAN.md +1971 -0
- data/docs/IMPLEMENTATION_PLAN_ARCHITECTURE.md +586 -0
- data/docs/PLAN.md +148 -0
- data/docs/QUICK-START.md +934 -0
- data/docs/README.md +296 -0
- data/docs/design/00-memory-optimization.md +593 -0
- data/docs/guides/MIGRATION-L27-L28.md +692 -0
- data/docs/guides/PERFORMANCE-BENCHMARKS.md +434 -0
- data/docs/guides/README.md +44 -0
- data/docs/prd/01-overview-vision.md +440 -0
- data/docs/use_cases/README.md +119 -0
- data/docs/use_cases/UC-001-request-scoped-debug-buffering.md +813 -0
- data/docs/use_cases/UC-002-business-event-tracking.md +1953 -0
- data/docs/use_cases/UC-003-pattern-based-metrics.md +1627 -0
- data/docs/use_cases/UC-004-zero-config-slo-tracking.md +728 -0
- data/docs/use_cases/UC-005-sentry-integration.md +759 -0
- data/docs/use_cases/UC-006-trace-context-management.md +905 -0
- data/docs/use_cases/UC-007-pii-filtering.md +2648 -0
- data/docs/use_cases/UC-008-opentelemetry-integration.md +1153 -0
- data/docs/use_cases/UC-009-multi-service-tracing.md +1043 -0
- data/docs/use_cases/UC-010-background-job-tracking.md +1018 -0
- data/docs/use_cases/UC-011-rate-limiting.md +1906 -0
- data/docs/use_cases/UC-012-audit-trail.md +2301 -0
- data/docs/use_cases/UC-013-high-cardinality-protection.md +2127 -0
- data/docs/use_cases/UC-014-adaptive-sampling.md +1940 -0
- data/docs/use_cases/UC-015-cost-optimization.md +735 -0
- data/docs/use_cases/UC-016-rails-logger-migration.md +785 -0
- data/docs/use_cases/UC-017-local-development.md +867 -0
- data/docs/use_cases/UC-018-testing-events.md +1081 -0
- data/docs/use_cases/UC-019-tiered-storage-migration.md +562 -0
- data/docs/use_cases/UC-020-event-versioning.md +708 -0
- data/docs/use_cases/UC-021-error-handling-retry-dlq.md +956 -0
- data/docs/use_cases/UC-022-event-registry.md +648 -0
- data/docs/use_cases/backlog.md +226 -0
- data/e11y.gemspec +76 -0
- data/lib/e11y/adapters/adaptive_batcher.rb +207 -0
- data/lib/e11y/adapters/audit_encrypted.rb +239 -0
- data/lib/e11y/adapters/base.rb +580 -0
- data/lib/e11y/adapters/file.rb +224 -0
- data/lib/e11y/adapters/in_memory.rb +216 -0
- data/lib/e11y/adapters/loki.rb +333 -0
- data/lib/e11y/adapters/otel_logs.rb +203 -0
- data/lib/e11y/adapters/registry.rb +141 -0
- data/lib/e11y/adapters/sentry.rb +230 -0
- data/lib/e11y/adapters/stdout.rb +108 -0
- data/lib/e11y/adapters/yabeda.rb +370 -0
- data/lib/e11y/buffers/adaptive_buffer.rb +339 -0
- data/lib/e11y/buffers/base_buffer.rb +40 -0
- data/lib/e11y/buffers/request_scoped_buffer.rb +246 -0
- data/lib/e11y/buffers/ring_buffer.rb +267 -0
- data/lib/e11y/buffers.rb +14 -0
- data/lib/e11y/console.rb +122 -0
- data/lib/e11y/current.rb +48 -0
- data/lib/e11y/event/base.rb +894 -0
- data/lib/e11y/event/value_sampling_config.rb +84 -0
- data/lib/e11y/events/base_audit_event.rb +43 -0
- data/lib/e11y/events/base_payment_event.rb +33 -0
- data/lib/e11y/events/rails/cache/delete.rb +21 -0
- data/lib/e11y/events/rails/cache/read.rb +23 -0
- data/lib/e11y/events/rails/cache/write.rb +22 -0
- data/lib/e11y/events/rails/database/query.rb +45 -0
- data/lib/e11y/events/rails/http/redirect.rb +21 -0
- data/lib/e11y/events/rails/http/request.rb +26 -0
- data/lib/e11y/events/rails/http/send_file.rb +21 -0
- data/lib/e11y/events/rails/http/start_processing.rb +26 -0
- data/lib/e11y/events/rails/job/completed.rb +22 -0
- data/lib/e11y/events/rails/job/enqueued.rb +22 -0
- data/lib/e11y/events/rails/job/failed.rb +22 -0
- data/lib/e11y/events/rails/job/scheduled.rb +23 -0
- data/lib/e11y/events/rails/job/started.rb +22 -0
- data/lib/e11y/events/rails/log.rb +56 -0
- data/lib/e11y/events/rails/view/render.rb +23 -0
- data/lib/e11y/events.rb +18 -0
- data/lib/e11y/instruments/active_job.rb +201 -0
- data/lib/e11y/instruments/rails_instrumentation.rb +141 -0
- data/lib/e11y/instruments/sidekiq.rb +175 -0
- data/lib/e11y/logger/bridge.rb +205 -0
- data/lib/e11y/metrics/cardinality_protection.rb +172 -0
- data/lib/e11y/metrics/cardinality_tracker.rb +134 -0
- data/lib/e11y/metrics/registry.rb +234 -0
- data/lib/e11y/metrics/relabeling.rb +226 -0
- data/lib/e11y/metrics.rb +102 -0
- data/lib/e11y/middleware/audit_signing.rb +174 -0
- data/lib/e11y/middleware/base.rb +140 -0
- data/lib/e11y/middleware/event_slo.rb +167 -0
- data/lib/e11y/middleware/pii_filter.rb +266 -0
- data/lib/e11y/middleware/pii_filtering.rb +280 -0
- data/lib/e11y/middleware/rate_limiting.rb +214 -0
- data/lib/e11y/middleware/request.rb +163 -0
- data/lib/e11y/middleware/routing.rb +157 -0
- data/lib/e11y/middleware/sampling.rb +254 -0
- data/lib/e11y/middleware/slo.rb +168 -0
- data/lib/e11y/middleware/trace_context.rb +131 -0
- data/lib/e11y/middleware/validation.rb +118 -0
- data/lib/e11y/middleware/versioning.rb +132 -0
- data/lib/e11y/middleware.rb +12 -0
- data/lib/e11y/pii/patterns.rb +90 -0
- data/lib/e11y/pii.rb +13 -0
- data/lib/e11y/pipeline/builder.rb +155 -0
- data/lib/e11y/pipeline/zone_validator.rb +110 -0
- data/lib/e11y/pipeline.rb +12 -0
- data/lib/e11y/presets/audit_event.rb +65 -0
- data/lib/e11y/presets/debug_event.rb +34 -0
- data/lib/e11y/presets/high_value_event.rb +51 -0
- data/lib/e11y/presets.rb +19 -0
- data/lib/e11y/railtie.rb +138 -0
- data/lib/e11y/reliability/circuit_breaker.rb +216 -0
- data/lib/e11y/reliability/dlq/file_storage.rb +277 -0
- data/lib/e11y/reliability/dlq/filter.rb +117 -0
- data/lib/e11y/reliability/retry_handler.rb +207 -0
- data/lib/e11y/reliability/retry_rate_limiter.rb +117 -0
- data/lib/e11y/sampling/error_spike_detector.rb +225 -0
- data/lib/e11y/sampling/load_monitor.rb +161 -0
- data/lib/e11y/sampling/stratified_tracker.rb +92 -0
- data/lib/e11y/sampling/value_extractor.rb +82 -0
- data/lib/e11y/self_monitoring/buffer_monitor.rb +79 -0
- data/lib/e11y/self_monitoring/performance_monitor.rb +97 -0
- data/lib/e11y/self_monitoring/reliability_monitor.rb +146 -0
- data/lib/e11y/slo/event_driven.rb +150 -0
- data/lib/e11y/slo/tracker.rb +119 -0
- data/lib/e11y/version.rb +9 -0
- data/lib/e11y.rb +283 -0
- metadata +452 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Event
|
|
5
|
+
# Configuration for value-based sampling at event class level (FEAT-4848)
|
|
6
|
+
#
|
|
7
|
+
# Allows events to define sampling thresholds based on payload values.
|
|
8
|
+
#
|
|
9
|
+
# @example High-value payment events
|
|
10
|
+
# class PaymentEvent < E11y::Event::Base
|
|
11
|
+
# sample_by_value :amount, greater_than: 1000
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# @example Range-based sampling
|
|
15
|
+
# class OrderEvent < E11y::Event::Base
|
|
16
|
+
# sample_by_value :total, in_range: 100..500
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# @example Multiple conditions (OR logic)
|
|
20
|
+
# class TransactionEvent < E11y::Event::Base
|
|
21
|
+
# sample_by_value :amount, greater_than: 5000
|
|
22
|
+
# sample_by_value :status, equals: "vip"
|
|
23
|
+
# end
|
|
24
|
+
class ValueSamplingConfig
|
|
25
|
+
attr_reader :field, :comparisons
|
|
26
|
+
|
|
27
|
+
# Initialize value sampling configuration
|
|
28
|
+
#
|
|
29
|
+
# @param field [String, Symbol] Field to extract value from
|
|
30
|
+
# @param comparisons [Hash] Comparison rules
|
|
31
|
+
# @option comparisons [Numeric] :greater_than (>) Sample if value > threshold
|
|
32
|
+
# @option comparisons [Numeric] :less_than (<) Sample if value < threshold
|
|
33
|
+
# @option comparisons [Object] :equals (==) Sample if value == threshold
|
|
34
|
+
# @option comparisons [Range] :in_range Sample if value in range
|
|
35
|
+
def initialize(field, comparisons = {})
|
|
36
|
+
@field = field
|
|
37
|
+
@comparisons = comparisons
|
|
38
|
+
validate_comparisons!
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Check if event_data matches sampling criteria
|
|
42
|
+
#
|
|
43
|
+
# @param event_data [Hash] Event payload
|
|
44
|
+
# @param extractor [E11y::Sampling::ValueExtractor] Value extractor
|
|
45
|
+
# @return [Boolean] true if value matches any comparison
|
|
46
|
+
def matches?(event_data, extractor)
|
|
47
|
+
value = extractor.extract(event_data, field)
|
|
48
|
+
|
|
49
|
+
comparisons.any? do |comparison_type, threshold|
|
|
50
|
+
case comparison_type
|
|
51
|
+
when :greater_than
|
|
52
|
+
value > threshold
|
|
53
|
+
when :less_than
|
|
54
|
+
value < threshold
|
|
55
|
+
when :equals
|
|
56
|
+
value == threshold
|
|
57
|
+
when :in_range
|
|
58
|
+
threshold.cover?(value)
|
|
59
|
+
else
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def validate_comparisons!
|
|
68
|
+
raise ArgumentError, "At least one comparison required" if comparisons.empty?
|
|
69
|
+
|
|
70
|
+
comparisons.each do |type, threshold|
|
|
71
|
+
unless %i[greater_than less_than equals in_range].include?(type)
|
|
72
|
+
raise ArgumentError, "Invalid comparison type: #{type}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
raise ArgumentError, "in_range requires a Range" if type == :in_range && !threshold.is_a?(Range)
|
|
76
|
+
|
|
77
|
+
if %i[greater_than less_than].include?(type) && !threshold.is_a?(Numeric)
|
|
78
|
+
raise ArgumentError, "#{type} requires a Numeric threshold"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
# Base class for audit events
|
|
6
|
+
#
|
|
7
|
+
# Audit events are compliance-critical events that must never be lost.
|
|
8
|
+
# They use the audit pipeline (Phase 4) which:
|
|
9
|
+
# - Signs events for non-repudiation
|
|
10
|
+
# - Encrypts sensitive data
|
|
11
|
+
# - Routes to audit-specific storage
|
|
12
|
+
# - Skips PII filtering (original data must be preserved)
|
|
13
|
+
#
|
|
14
|
+
# IMPORTANT: This base class does NOT set a default severity.
|
|
15
|
+
# Users must explicitly set severity based on the event's criticality:
|
|
16
|
+
# - :info for routine audit logging (e.g., "user viewed document")
|
|
17
|
+
# - :warn for suspicious actions (e.g., "unauthorized access attempt")
|
|
18
|
+
# - :error for violations (e.g., "failed authentication after 5 attempts")
|
|
19
|
+
# - :fatal for critical security events (e.g., "security breach detected")
|
|
20
|
+
#
|
|
21
|
+
# @example Audit event with explicit severity
|
|
22
|
+
# class UserLoginAudit < E11y::Events::BaseAuditEvent
|
|
23
|
+
# severity :info # Explicitly set based on criticality
|
|
24
|
+
#
|
|
25
|
+
# schema do
|
|
26
|
+
# required(:user_id).filled(:integer)
|
|
27
|
+
# required(:ip_address).filled(:string)
|
|
28
|
+
# required(:timestamp).filled(:time)
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# UserLoginAudit.track(user_id: 123, ip_address: "192.168.1.1", timestamp: Time.now)
|
|
33
|
+
class BaseAuditEvent < E11y::Event::Base
|
|
34
|
+
include E11y::Presets::AuditEvent
|
|
35
|
+
|
|
36
|
+
# Audit events use the audit pipeline (Phase 4)
|
|
37
|
+
# For now, this is a marker - audit pipeline will be implemented later
|
|
38
|
+
def self.audit_event?
|
|
39
|
+
true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
# Base class for payment and high-value events
|
|
6
|
+
#
|
|
7
|
+
# Payment events require special handling:
|
|
8
|
+
# - 100% sampling (never miss a payment)
|
|
9
|
+
# - Unlimited rate limit (never drop payment events)
|
|
10
|
+
# - Multiple adapters (Loki + Sentry for alerting)
|
|
11
|
+
# - High-priority tracking
|
|
12
|
+
#
|
|
13
|
+
# @example Creating a payment event
|
|
14
|
+
# class PaymentProcessed < E11y::Events::BasePaymentEvent
|
|
15
|
+
# schema do
|
|
16
|
+
# required(:payment_id).filled(:integer)
|
|
17
|
+
# required(:amount).filled(:float)
|
|
18
|
+
# required(:currency).filled(:string)
|
|
19
|
+
# required(:user_id).filled(:integer)
|
|
20
|
+
# end
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# PaymentProcessed.track(
|
|
24
|
+
# payment_id: 123,
|
|
25
|
+
# amount: 99.99,
|
|
26
|
+
# currency: "USD",
|
|
27
|
+
# user_id: 456
|
|
28
|
+
# )
|
|
29
|
+
class BasePaymentEvent < E11y::Event::Base
|
|
30
|
+
include E11y::Presets::HighValueEvent
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Cache
|
|
7
|
+
# Built-in event for cache deletes (cache_delete.active_support)
|
|
8
|
+
class Delete < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:key).maybe(:string)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
severity :debug
|
|
16
|
+
sample_rate 0.1 # Sample cache deletes at 10%
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Cache
|
|
7
|
+
# Built-in event for cache reads (cache_read.active_support)
|
|
8
|
+
class Read < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:key).maybe(:string)
|
|
13
|
+
optional(:hit).maybe(:bool)
|
|
14
|
+
optional(:super_operation).maybe(:string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
severity :debug
|
|
18
|
+
sample_rate 0.01 # Sample cache reads at 1% (very high volume)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Cache
|
|
7
|
+
# Built-in event for cache writes (cache_write.active_support)
|
|
8
|
+
class Write < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:key).maybe(:string)
|
|
13
|
+
optional(:super_operation).maybe(:string)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
severity :debug
|
|
17
|
+
sample_rate 0.01 # Sample cache writes at 1%
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Database
|
|
7
|
+
# Built-in event for SQL queries (sql.active_record)
|
|
8
|
+
#
|
|
9
|
+
# Tracks database queries from ActiveRecord with timing and connection info.
|
|
10
|
+
#
|
|
11
|
+
# @example Usage (automatic via Rails Instrumentation)
|
|
12
|
+
# # Automatically tracked when Rails executes SQL:
|
|
13
|
+
# User.where(email: 'user@example.com').first
|
|
14
|
+
# # → Events::Rails::Database::Query tracked
|
|
15
|
+
#
|
|
16
|
+
# @example Custom override
|
|
17
|
+
# # config/initializers/e11y.rb
|
|
18
|
+
# E11y.configure do |config|
|
|
19
|
+
# config.rails_instrumentation.event_class_for(
|
|
20
|
+
# 'sql.active_record',
|
|
21
|
+
# MyApp::CustomDatabaseQuery
|
|
22
|
+
# )
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# @see ADR-008 §4.3 (Built-in Event Classes)
|
|
26
|
+
class Query < E11y::Event::Base
|
|
27
|
+
schema do
|
|
28
|
+
required(:event_name).filled(:string)
|
|
29
|
+
required(:duration).filled(:float)
|
|
30
|
+
optional(:name).maybe(:string)
|
|
31
|
+
optional(:sql).maybe(:string)
|
|
32
|
+
optional(:connection_id).maybe(:integer)
|
|
33
|
+
optional(:binds).maybe(:array)
|
|
34
|
+
optional(:allocations).maybe(:integer)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
severity :debug # SQL queries are debug-level by default
|
|
38
|
+
|
|
39
|
+
# Sample SQL queries at 10% (can be overridden)
|
|
40
|
+
sample_rate 0.1
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Http
|
|
7
|
+
# Built-in event for redirects (redirect_to.action_controller)
|
|
8
|
+
class Redirect < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:location).maybe(:string)
|
|
13
|
+
optional(:status).maybe(:integer)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
severity :info
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Http
|
|
7
|
+
# Built-in event for HTTP requests (process_action.action_controller)
|
|
8
|
+
class Request < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:controller).maybe(:string)
|
|
13
|
+
optional(:action).maybe(:string)
|
|
14
|
+
optional(:format).maybe(:string)
|
|
15
|
+
optional(:status).maybe(:integer)
|
|
16
|
+
optional(:view_runtime).maybe(:float)
|
|
17
|
+
optional(:db_runtime).maybe(:float)
|
|
18
|
+
optional(:allocations).maybe(:integer)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
severity :info
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Http
|
|
7
|
+
# Built-in event for file sending (send_file.action_controller)
|
|
8
|
+
class SendFile < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:path).maybe(:string)
|
|
13
|
+
optional(:filename).maybe(:string)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
severity :info
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Http
|
|
7
|
+
# Event for `start_processing.action_controller` ASN notification
|
|
8
|
+
#
|
|
9
|
+
# Fired when Rails starts processing a controller action.
|
|
10
|
+
#
|
|
11
|
+
# @see https://guides.rubyonrails.org/active_support_instrumentation.html#start-processing-action-controller
|
|
12
|
+
class StartProcessing < E11y::Event::Base
|
|
13
|
+
schema do
|
|
14
|
+
required(:controller).filled(:string)
|
|
15
|
+
required(:action).filled(:string)
|
|
16
|
+
required(:method).filled(:string)
|
|
17
|
+
required(:path).filled(:string)
|
|
18
|
+
required(:format).filled(:string)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
severity :debug
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Job
|
|
7
|
+
# Built-in event for completed jobs (perform.active_job)
|
|
8
|
+
class Completed < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:job_class).maybe(:string)
|
|
13
|
+
optional(:job_id).maybe(:string)
|
|
14
|
+
optional(:queue).maybe(:string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
severity :info
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Job
|
|
7
|
+
# Built-in event for enqueued jobs (enqueue.active_job)
|
|
8
|
+
class Enqueued < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:job_class).maybe(:string)
|
|
13
|
+
optional(:job_id).maybe(:string)
|
|
14
|
+
optional(:queue).maybe(:string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
severity :info
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Job
|
|
7
|
+
# Built-in event for failed jobs
|
|
8
|
+
class Failed < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:job_class).maybe(:string)
|
|
13
|
+
optional(:job_id).maybe(:string)
|
|
14
|
+
optional(:queue).maybe(:string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
severity :error
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Job
|
|
7
|
+
# Built-in event for scheduled jobs (enqueue_at.active_job)
|
|
8
|
+
class Scheduled < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:job_class).maybe(:string)
|
|
13
|
+
optional(:job_id).maybe(:string)
|
|
14
|
+
optional(:queue).maybe(:string)
|
|
15
|
+
optional(:scheduled_at).maybe(:time)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
severity :info
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module Job
|
|
7
|
+
# Built-in event for started jobs (perform_start.active_job)
|
|
8
|
+
class Started < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:job_class).maybe(:string)
|
|
13
|
+
optional(:job_id).maybe(:string)
|
|
14
|
+
optional(:queue).maybe(:string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
severity :info
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "e11y/event/base"
|
|
4
|
+
|
|
5
|
+
module E11y
|
|
6
|
+
module Events
|
|
7
|
+
module Rails
|
|
8
|
+
# Base class for all Rails.logger events
|
|
9
|
+
#
|
|
10
|
+
# This is an ABSTRACT class - use specific severity classes instead:
|
|
11
|
+
# - Events::Rails::Log::Debug
|
|
12
|
+
# - Events::Rails::Log::Info
|
|
13
|
+
# - Events::Rails::Log::Warn
|
|
14
|
+
# - Events::Rails::Log::Error
|
|
15
|
+
# - Events::Rails::Log::Fatal
|
|
16
|
+
#
|
|
17
|
+
# @see E11y::Logger::Bridge
|
|
18
|
+
class Log < E11y::Event::Base
|
|
19
|
+
schema do
|
|
20
|
+
required(:message).filled(:string)
|
|
21
|
+
optional(:caller_location).filled(:string)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Debug logs (verbose, typically disabled in production)
|
|
25
|
+
class Debug < Log
|
|
26
|
+
severity :debug
|
|
27
|
+
adapters [:logs]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Info logs (general information)
|
|
31
|
+
class Info < Log
|
|
32
|
+
severity :info
|
|
33
|
+
adapters [:logs]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Warning logs (potential issues)
|
|
37
|
+
class Warn < Log
|
|
38
|
+
severity :warn
|
|
39
|
+
adapters [:logs]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Error logs (errors that need attention)
|
|
43
|
+
class Error < Log
|
|
44
|
+
severity :error
|
|
45
|
+
adapters %i[logs errors_tracker] # Send to Sentry!
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Fatal logs (critical errors, system-breaking)
|
|
49
|
+
class Fatal < Log
|
|
50
|
+
severity :fatal
|
|
51
|
+
adapters %i[logs errors_tracker] # Send to Sentry!
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
module Events
|
|
5
|
+
module Rails
|
|
6
|
+
module View
|
|
7
|
+
# Built-in event for view rendering (render_template.action_view)
|
|
8
|
+
class Render < E11y::Event::Base
|
|
9
|
+
schema do
|
|
10
|
+
required(:event_name).filled(:string)
|
|
11
|
+
required(:duration).filled(:float)
|
|
12
|
+
optional(:identifier).maybe(:string)
|
|
13
|
+
optional(:layout).maybe(:string)
|
|
14
|
+
optional(:allocations).maybe(:integer)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
severity :debug
|
|
18
|
+
sample_rate 0.1 # Sample view renders at 10%
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/e11y/events.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module E11y
|
|
4
|
+
# Base event classes for common patterns
|
|
5
|
+
#
|
|
6
|
+
# These classes provide pre-configured base classes for typical event types.
|
|
7
|
+
# Users can inherit from these instead of E11y::Event::Base for less boilerplate.
|
|
8
|
+
#
|
|
9
|
+
# @example Using a base event class
|
|
10
|
+
# class UserLoginAudit < E11y::Events::BaseAuditEvent
|
|
11
|
+
# schema do
|
|
12
|
+
# required(:user_id).filled(:integer)
|
|
13
|
+
# required(:ip_address).filled(:string)
|
|
14
|
+
# end
|
|
15
|
+
# end
|
|
16
|
+
module Events
|
|
17
|
+
end
|
|
18
|
+
end
|