e11y 0.2.0 → 1.0.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 +4 -4
- data/.rubocop.yml +130 -10
- data/CHANGELOG.md +56 -1
- data/CLAUDE.md +168 -0
- data/CONTRIBUTING.md +640 -0
- data/README.md +134 -702
- data/RELEASE.md +18 -3
- data/Rakefile +108 -29
- data/config/README.md +1 -1
- data/config/loki-local-config.yaml +12 -0
- data/config/otel-collector-config.yaml +44 -0
- data/cucumber.yml +1 -0
- data/docker-compose.yml +18 -2
- data/docs/ADAPTERS.md +76 -0
- data/docs/ADAPTIVE_SAMPLING.md +59 -0
- data/docs/COMPARISON.md +104 -0
- data/docs/CONFIGURATION.md +52 -0
- data/docs/DISTRIBUTED_TRACING.md +44 -0
- data/docs/LIMITATIONS.md +13 -0
- data/docs/METRICS_DSL.md +84 -0
- data/docs/PERFORMANCE.md +60 -0
- data/docs/PII_FILTERING.md +40 -0
- data/docs/PRESETS.md +65 -0
- data/docs/QUICK-START.md +546 -587
- data/docs/RAILS_INTEGRATION.md +29 -0
- data/docs/SCHEMA_VALIDATION.md +63 -0
- data/docs/SLO-PROMQL-ALERTS.md +161 -0
- data/docs/TESTING.md +69 -0
- data/docs/{ADR-001-architecture.md → architecture/ADR-001-architecture.md} +35 -64
- data/docs/{ADR-002-metrics-yabeda.md → architecture/ADR-002-metrics-yabeda.md} +62 -236
- data/docs/{ADR-003-slo-observability.md → architecture/ADR-003-slo-observability.md} +27 -466
- data/docs/{ADR-004-adapter-architecture.md → architecture/ADR-004-adapter-architecture.md} +163 -146
- data/docs/{ADR-005-tracing-context.md → architecture/ADR-005-tracing-context.md} +10 -9
- data/docs/{ADR-006-security-compliance.md → architecture/ADR-006-security-compliance.md} +184 -191
- data/docs/{ADR-007-opentelemetry-integration.md → architecture/ADR-007-opentelemetry-integration.md} +3 -21
- data/docs/{ADR-008-rails-integration.md → architecture/ADR-008-rails-integration.md} +209 -339
- data/docs/{ADR-009-cost-optimization.md → architecture/ADR-009-cost-optimization.md} +45 -54
- data/docs/architecture/ADR-010-developer-experience.md +522 -0
- data/docs/{ADR-011-testing-strategy.md → architecture/ADR-011-testing-strategy.md} +41 -83
- data/docs/{ADR-013-reliability-error-handling.md → architecture/ADR-013-reliability-error-handling.md} +37 -12
- data/docs/{ADR-014-event-driven-slo.md → architecture/ADR-014-event-driven-slo.md} +12 -24
- data/docs/{ADR-015-middleware-order.md → architecture/ADR-015-middleware-order.md} +23 -41
- data/docs/{ADR-016-self-monitoring-slo.md → architecture/ADR-016-self-monitoring-slo.md} +52 -349
- data/docs/{ADR-017-multi-rails-compatibility.md → architecture/ADR-017-multi-rails-compatibility.md} +4 -11
- data/docs/architecture/ADR-018-memory-optimization.md +366 -0
- data/docs/{ADR-INDEX.md → architecture/ADR-INDEX.md} +11 -6
- data/docs/{00-ICP-AND-TIMELINE.md → prd/00-ICP-AND-TIMELINE.md} +6 -6
- data/docs/{01-SCALE-REQUIREMENTS.md → prd/01-SCALE-REQUIREMENTS.md} +6 -6
- data/docs/prd/01-overview-vision.md +19 -14
- data/docs/use_cases/README.md +22 -23
- data/docs/use_cases/UC-001-request-scoped-debug-buffering.md +50 -44
- data/docs/use_cases/UC-002-business-event-tracking.md +26 -95
- data/docs/use_cases/UC-003-event-metrics.md +66 -0
- data/docs/use_cases/UC-004-zero-config-slo-tracking.md +42 -101
- data/docs/use_cases/UC-005-sentry-integration.md +13 -15
- data/docs/use_cases/UC-006-trace-context-management.md +30 -28
- data/docs/use_cases/UC-007-pii-filtering.md +35 -87
- data/docs/use_cases/UC-008-opentelemetry-integration.md +51 -89
- data/docs/use_cases/UC-009-multi-service-tracing.md +4 -4
- data/docs/use_cases/UC-010-background-job-tracking.md +5 -5
- data/docs/use_cases/UC-011-rate-limiting.md +95 -168
- data/docs/use_cases/UC-012-audit-trail.md +21 -46
- data/docs/use_cases/UC-013-high-cardinality-protection.md +29 -167
- data/docs/use_cases/UC-014-adaptive-sampling.md +2 -2
- data/docs/use_cases/UC-015-cost-optimization.md +46 -99
- data/docs/use_cases/UC-016-rails-logger-migration.md +39 -213
- data/docs/use_cases/UC-017-local-development.md +203 -777
- data/docs/use_cases/UC-018-testing-events.md +3 -3
- data/docs/use_cases/UC-019-retention-based-routing.md +53 -106
- data/docs/use_cases/UC-020-event-versioning.md +8 -9
- data/docs/use_cases/UC-021-error-handling-retry-dlq.md +18 -22
- data/docs/use_cases/UC-022-event-registry.md +15 -21
- data/docs/use_cases/backlog.md +119 -87
- data/e11y.gemspec +2 -2
- data/gems/e11y-devtools/README.md +136 -0
- data/gems/e11y-devtools/config/routes.rb +8 -0
- data/gems/e11y-devtools/e11y-devtools.gemspec +25 -0
- data/gems/e11y-devtools/exe/e11y +34 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/server.rb +96 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tool_base.rb +25 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/clear.rb +31 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/errors.rb +35 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/event_detail.rb +33 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/events_by_trace.rb +33 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/interactions.rb +40 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/recent_events.rb +34 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/search.rb +34 -0
- data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/stats.rb +30 -0
- data/gems/e11y-devtools/lib/e11y/devtools/overlay/assets/overlay.js +115 -0
- data/gems/e11y-devtools/lib/e11y/devtools/overlay/controller.rb +54 -0
- data/gems/e11y-devtools/lib/e11y/devtools/overlay/engine.rb +26 -0
- data/gems/e11y-devtools/lib/e11y/devtools/overlay/middleware.rb +80 -0
- data/gems/e11y-devtools/lib/e11y/devtools/overlay/rails_controller.rb +42 -0
- data/gems/e11y-devtools/lib/e11y/devtools/tui/app.rb +262 -0
- data/gems/e11y-devtools/lib/e11y/devtools/tui/grouping.rb +66 -0
- data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/event_detail.rb +62 -0
- data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/event_list.rb +70 -0
- data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/interaction_list.rb +47 -0
- data/gems/e11y-devtools/lib/e11y/devtools/version.rb +8 -0
- data/gems/e11y-devtools/lib/e11y/devtools.rb +13 -0
- data/gems/e11y-devtools/spec/e11y/devtools/mcp/tools_spec.rb +107 -0
- data/gems/e11y-devtools/spec/e11y/devtools/overlay/controller_spec.rb +58 -0
- data/gems/e11y-devtools/spec/e11y/devtools/overlay/middleware_spec.rb +46 -0
- data/gems/e11y-devtools/spec/e11y/devtools/tui/app_spec.rb +85 -0
- data/gems/e11y-devtools/spec/e11y/devtools/tui/grouping_spec.rb +64 -0
- data/gems/e11y-devtools/spec/spec_helper.rb +5 -0
- data/gems/e11y-devtools/spec/tui/widgets/event_list_spec.rb +44 -0
- data/gems/e11y-devtools/spec/tui/widgets/interaction_list_spec.rb +62 -0
- data/lib/e11y/adapters/audit_encrypted.rb +53 -11
- data/lib/e11y/adapters/base.rb +33 -34
- data/lib/e11y/adapters/dev_log/file_store.rb +143 -0
- data/lib/e11y/adapters/dev_log/query.rb +219 -0
- data/lib/e11y/adapters/dev_log.rb +118 -0
- data/lib/e11y/adapters/file.rb +3 -6
- data/lib/e11y/adapters/in_memory.rb +52 -5
- data/lib/e11y/adapters/in_memory_test.rb +29 -0
- data/lib/e11y/adapters/loki.rb +58 -23
- data/lib/e11y/adapters/null.rb +82 -0
- data/lib/e11y/adapters/opentelemetry_collector.rb +183 -0
- data/lib/e11y/adapters/otel_logs.rb +136 -23
- data/lib/e11y/adapters/sentry.rb +4 -7
- data/lib/e11y/adapters/stdout.rb +73 -7
- data/lib/e11y/adapters/yabeda.rb +153 -29
- data/lib/e11y/buffers/adaptive_buffer.rb +3 -17
- data/lib/e11y/buffers/{request_scoped_buffer.rb → ephemeral_buffer.rb} +72 -58
- data/lib/e11y/buffers/ring_buffer.rb +3 -16
- data/lib/e11y/configuration.rb +272 -0
- data/lib/e11y/console.rb +10 -17
- data/lib/e11y/current.rb +53 -1
- data/lib/e11y/debug/pipeline_inspector.rb +96 -0
- data/lib/e11y/documentation/generator.rb +48 -0
- data/lib/e11y/event/base.rb +176 -82
- data/lib/e11y/event/value_sampling_config.rb +1 -5
- data/lib/e11y/events/rails/database/query.rb +1 -4
- data/lib/e11y/events/rails/job/failed.rb +2 -0
- data/lib/e11y/instruments/active_job.rb +46 -12
- data/lib/e11y/instruments/rails_instrumentation.rb +49 -24
- data/lib/e11y/instruments/sidekiq.rb +137 -31
- data/lib/e11y/linters/base.rb +11 -0
- data/lib/e11y/linters/pii/pii_declaration_linter.rb +120 -0
- data/lib/e11y/linters/slo/config_consistency_linter.rb +76 -0
- data/lib/e11y/linters/slo/explicit_declaration_linter.rb +36 -0
- data/lib/e11y/linters/slo/slo_status_from_linter.rb +41 -0
- data/lib/e11y/logger/bridge.rb +26 -7
- data/lib/e11y/metrics/cardinality_protection.rb +10 -15
- data/lib/e11y/metrics/cardinality_tracker.rb +16 -6
- data/lib/e11y/metrics/registry.rb +3 -5
- data/lib/e11y/metrics/test_backend.rb +62 -0
- data/lib/e11y/metrics.rb +56 -10
- data/lib/e11y/middleware/adapter_resolver.rb +40 -0
- data/lib/e11y/middleware/audit_signing.rb +43 -6
- data/lib/e11y/middleware/baggage_protection.rb +75 -0
- data/lib/e11y/middleware/dev_log_source.rb +24 -0
- data/lib/e11y/middleware/event_slo.rb +23 -9
- data/lib/e11y/middleware/otel_span.rb +23 -0
- data/lib/e11y/middleware/pii_filter.rb +104 -75
- data/lib/e11y/middleware/rate_limiting.rb +54 -27
- data/lib/e11y/middleware/request.rb +70 -23
- data/lib/e11y/middleware/routing.rb +78 -21
- data/lib/e11y/middleware/sampling.rb +66 -17
- data/lib/e11y/middleware/self_monitoring_emit.rb +39 -0
- data/lib/e11y/middleware/trace_context.rb +45 -10
- data/lib/e11y/middleware/track_latency.rb +34 -0
- data/lib/e11y/middleware/validation.rb +7 -16
- data/lib/e11y/middleware/versioning.rb +26 -22
- data/lib/e11y/opentelemetry/semantic_conventions.rb +109 -0
- data/lib/e11y/opentelemetry/span_creator.rb +142 -0
- data/lib/e11y/pii/patterns.rb +12 -1
- data/lib/e11y/pipeline/builder.rb +1 -1
- data/lib/e11y/presets/audit_event.rb +13 -2
- data/lib/e11y/railtie.rb +52 -15
- data/lib/e11y/registry.rb +306 -0
- data/lib/e11y/reliability/circuit_breaker.rb +19 -21
- data/lib/e11y/reliability/dlq/base.rb +71 -0
- data/lib/e11y/reliability/dlq/file_adapter.rb +301 -0
- data/lib/e11y/reliability/dlq/file_storage.rb +63 -34
- data/lib/e11y/reliability/dlq/filter.rb +37 -54
- data/lib/e11y/reliability/retry_handler.rb +26 -29
- data/lib/e11y/reliability/retry_rate_limiter.rb +3 -11
- data/lib/e11y/sampling/error_spike_detector.rb +0 -2
- data/lib/e11y/sampling/load_monitor.rb +5 -9
- data/lib/e11y/sampling/stratified_tracker.rb +18 -0
- data/lib/e11y/self_monitoring/buffer_monitor.rb +2 -0
- data/lib/e11y/self_monitoring/performance_monitor.rb +19 -61
- data/lib/e11y/self_monitoring/reliability_monitor.rb +4 -74
- data/lib/e11y/slo/config_loader.rb +40 -0
- data/lib/e11y/slo/config_validator.rb +58 -0
- data/lib/e11y/slo/dashboard_generator.rb +122 -0
- data/lib/e11y/slo/event_driven.rb +8 -0
- data/lib/e11y/slo/tracker.rb +31 -4
- data/lib/e11y/testing/have_tracked_event_matcher.rb +190 -0
- data/lib/e11y/testing/rspec_matchers.rb +21 -0
- data/lib/e11y/testing/snapshot_matcher.rb +86 -0
- data/lib/e11y/trace_context/sampler.rb +35 -0
- data/lib/e11y/tracing/faraday_middleware.rb +31 -0
- data/lib/e11y/tracing/net_http_patch.rb +33 -0
- data/lib/e11y/tracing/propagator.rb +116 -0
- data/lib/e11y/tracing.rb +47 -0
- data/lib/e11y/version.rb +1 -1
- data/lib/e11y/versioning/version_extractor.rb +32 -0
- data/lib/e11y.rb +141 -265
- data/lib/generators/e11y/event/event_generator.rb +22 -0
- data/lib/generators/e11y/event/templates/event.rb.tt +16 -0
- data/lib/generators/e11y/grafana_dashboard/grafana_dashboard_generator.rb +30 -0
- data/lib/generators/e11y/grafana_dashboard/templates/e11y_dashboard.json +81 -0
- data/lib/generators/e11y/install/install_generator.rb +34 -0
- data/lib/generators/e11y/install/templates/e11y.rb +239 -0
- data/lib/generators/e11y/prometheus_alerts/prometheus_alerts_generator.rb +29 -0
- data/lib/generators/e11y/prometheus_alerts/templates/e11y_alerts.yml +28 -0
- data/lib/tasks/e11y_docs.rake +30 -0
- data/lib/tasks/e11y_events.rake +71 -0
- data/lib/tasks/e11y_lint.rake +91 -0
- data/lib/tasks/e11y_slo.rake +29 -0
- metadata +129 -39
- data/docs/ADR-010-developer-experience.md +0 -2166
- data/docs/API-REFERENCE-L28.md +0 -914
- data/docs/COMPREHENSIVE-CONFIGURATION.md +0 -2366
- data/docs/CONTRIBUTING.md +0 -312
- data/docs/IMPLEMENTATION_NOTES.md +0 -2804
- data/docs/IMPLEMENTATION_PLAN.md +0 -1971
- data/docs/IMPLEMENTATION_PLAN_ARCHITECTURE.md +0 -586
- data/docs/PLAN.md +0 -148
- data/docs/README.md +0 -296
- data/docs/design/00-memory-optimization.md +0 -593
- data/docs/guides/MIGRATION-L27-L28.md +0 -692
- data/docs/guides/PERFORMANCE-BENCHMARKS.md +0 -434
- data/docs/guides/README.md +0 -44
- data/docs/use_cases/UC-003-pattern-based-metrics.md +0 -1627
- data/lib/e11y/adapters/registry.rb +0 -141
- /data/docs/{ADR-012-event-evolution.md → architecture/ADR-012-event-evolution.md} +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
## Basic Configuration
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
# config/initializers/e11y.rb
|
|
9
|
+
E11y.configure do |config|
|
|
10
|
+
# Service identification
|
|
11
|
+
config.service_name = "myapp"
|
|
12
|
+
config.environment = Rails.env
|
|
13
|
+
|
|
14
|
+
# Configure adapters
|
|
15
|
+
config.adapters[:logs] = E11y::Adapters::Loki.new(
|
|
16
|
+
url: ENV["LOKI_URL"],
|
|
17
|
+
batch_size: 100,
|
|
18
|
+
batch_timeout: 5,
|
|
19
|
+
compress: true
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
config.adapters[:errors_tracker] = E11y::Adapters::Sentry.new(
|
|
23
|
+
dsn: ENV["SENTRY_DSN"]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Default retention period
|
|
27
|
+
config.default_retention_period = 30.days
|
|
28
|
+
end
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Middleware Pipeline
|
|
32
|
+
|
|
33
|
+
Configure middleware for sampling, PII filtering, and more. Add `TrackLatency` first for self-monitoring (Event.track() latency):
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
E11y.configure do |config|
|
|
37
|
+
# Self-monitoring: track latency (must be first)
|
|
38
|
+
config.pipeline.use E11y::Middleware::TrackLatency
|
|
39
|
+
|
|
40
|
+
# Sampling middleware
|
|
41
|
+
config.pipeline.use E11y::Middleware::Sampling,
|
|
42
|
+
default_sample_rate: 0.1,
|
|
43
|
+
error_based_adaptive: true,
|
|
44
|
+
load_based_adaptive: true
|
|
45
|
+
|
|
46
|
+
# PII filtering middleware
|
|
47
|
+
config.pipeline.use E11y::Middleware::PIIFilter
|
|
48
|
+
|
|
49
|
+
# Trace context middleware
|
|
50
|
+
config.pipeline.use E11y::Middleware::TraceContext
|
|
51
|
+
end
|
|
52
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Distributed Tracing
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
E11y automatically attaches W3C Trace Context headers to incoming requests via the `TraceContext` middleware and propagates trace/span IDs through the event pipeline.
|
|
6
|
+
|
|
7
|
+
## Incoming Trace Context
|
|
8
|
+
|
|
9
|
+
Incoming `traceparent` / `tracestate` headers are extracted automatically:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
E11y.configure do |config|
|
|
13
|
+
config.pipeline.use E11y::Middleware::TraceContext
|
|
14
|
+
end
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Events tracked during a request will include `trace_id` and `span_id` from the incoming context.
|
|
18
|
+
|
|
19
|
+
## Outgoing HTTP Trace Propagation (Manual — v1.0)
|
|
20
|
+
|
|
21
|
+
> **Note:** Automatic outgoing trace context injection (Faraday / Net::HTTP middleware) is planned for v1.1.
|
|
22
|
+
> Until then, use the helper below to propagate W3C Trace Context manually:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# Helper: build W3C traceparent header from current context
|
|
26
|
+
def traceparent_header
|
|
27
|
+
return {} unless E11y::Current.trace_id
|
|
28
|
+
|
|
29
|
+
span_id = E11y::Current.span_id || SecureRandom.hex(8)
|
|
30
|
+
{ "traceparent" => "00-#{E11y::Current.trace_id}-#{span_id}-01" }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Faraday — inject on each connection
|
|
34
|
+
conn = Faraday.new(url: "https://api.example.com") do |f|
|
|
35
|
+
f.headers.merge!(traceparent_header)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Net::HTTP — inject per request
|
|
39
|
+
request = Net::HTTP::Post.new("/events")
|
|
40
|
+
traceparent_header.each { |k, v| request[k] = v }
|
|
41
|
+
http.request(request)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This ensures downstream services receive a valid `traceparent` header and can correlate logs/traces back to the originating request.
|
data/docs/LIMITATIONS.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Limitations & Tradeoffs
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
E11y trades generality for Rails-specific ergonomics. Know what you're getting:
|
|
6
|
+
|
|
7
|
+
| Limitation | Detail |
|
|
8
|
+
|------------|--------|
|
|
9
|
+
| **Rails only** | No Sinatra, Hanami, or pure-Ruby support. Railtie is required. |
|
|
10
|
+
| **Ruby 3.2+** | Older projects can't use it without upgrading Ruby. |
|
|
11
|
+
| **Rails 7.0–8.0** | Rails 8.1 excluded (sqlite3 bug in test environment). |
|
|
12
|
+
| **Memory overhead** | Debug buffer holds events in RAM per request. Under heavy load with large payloads, monitor heap usage. |
|
|
13
|
+
| **No distributed tracing UI** | OTel adapter emits spans, but e11y has no built-in trace visualization. Use Grafana Tempo or Jaeger. |
|
data/docs/METRICS_DSL.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Metrics DSL
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
Define Prometheus metrics alongside events.
|
|
6
|
+
|
|
7
|
+
## Basic Example
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class OrderPaidEvent < E11y::Event::Base
|
|
11
|
+
schema do
|
|
12
|
+
required(:order_id).filled(:string)
|
|
13
|
+
required(:amount).filled(:float)
|
|
14
|
+
required(:currency).filled(:string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
metrics do
|
|
18
|
+
# Counter: Track number of paid orders
|
|
19
|
+
counter :orders_total, tags: [:currency]
|
|
20
|
+
|
|
21
|
+
# Histogram: Track order amount distribution
|
|
22
|
+
histogram :order_amount,
|
|
23
|
+
value: :amount,
|
|
24
|
+
tags: [:currency],
|
|
25
|
+
buckets: [10, 50, 100, 500, 1000]
|
|
26
|
+
|
|
27
|
+
# Gauge: Track active orders
|
|
28
|
+
gauge :active_orders, value: :active_count
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# One track() call = event + metrics
|
|
33
|
+
OrderPaidEvent.track(order_id: "123", amount: 99.99, currency: "USD")
|
|
34
|
+
# => orders_total{currency="USD"} +1
|
|
35
|
+
# => order_amount{currency="USD"} observe 99.99
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Metric Types
|
|
39
|
+
|
|
40
|
+
**Counter** - Monotonically increasing value:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
metrics do
|
|
44
|
+
counter :orders_total, tags: [:currency, :status]
|
|
45
|
+
end
|
|
46
|
+
# => orders_total{currency="USD", status="paid"} 42
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Histogram** - Distribution of values:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
metrics do
|
|
53
|
+
histogram :order_amount,
|
|
54
|
+
value: :amount,
|
|
55
|
+
tags: [:currency],
|
|
56
|
+
buckets: [10, 50, 100, 500, 1000]
|
|
57
|
+
end
|
|
58
|
+
# => order_amount_bucket{currency="USD", le="100"} 15
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Gauge** - Arbitrary value that can go up or down:
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
metrics do
|
|
65
|
+
gauge :queue_depth, value: :size, tags: [:queue_name]
|
|
66
|
+
end
|
|
67
|
+
# => queue_depth{queue_name="emails"} 37
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## How It Works
|
|
71
|
+
|
|
72
|
+
1. Define metrics in event class
|
|
73
|
+
2. Metrics registered in `E11y::Metrics::Registry` at boot time
|
|
74
|
+
3. When `track()` is called, metrics are automatically updated **if the Yabeda adapter is configured and routed to**
|
|
75
|
+
4. Metrics exported via Yabeda adapter (Prometheus format)
|
|
76
|
+
|
|
77
|
+
> **Note:** The `metrics do` DSL only registers metric definitions. Metrics are actually updated
|
|
78
|
+
> when an event is written to the `E11y::Adapters::Yabeda` adapter. If you omit the Yabeda adapter
|
|
79
|
+
> from your configuration, `track()` will send events to Loki/Sentry but metric counters will not
|
|
80
|
+
> be incremented. Make sure to add:
|
|
81
|
+
>
|
|
82
|
+
> ```ruby
|
|
83
|
+
> config.adapters[:metrics] = E11y::Adapters::Yabeda.new
|
|
84
|
+
> ```
|
data/docs/PERFORMANCE.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Performance
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
## Design Principles
|
|
6
|
+
|
|
7
|
+
E11y is designed for performance:
|
|
8
|
+
|
|
9
|
+
- **Hash-based events** - Events are Hashes, not objects, minimizing allocations
|
|
10
|
+
- **Configurable validation** - Choose validation mode based on performance needs
|
|
11
|
+
- **Batching** - Loki and other adapters support batching to reduce network overhead
|
|
12
|
+
- **Sampling** - Adaptive sampling reduces event volume under high load
|
|
13
|
+
|
|
14
|
+
## Benchmarks (Ruby 3.3, measured via `rake spec:benchmark` and `rake spec:memory`)
|
|
15
|
+
|
|
16
|
+
| Metric | Value | Notes |
|
|
17
|
+
|--------|-------|-------|
|
|
18
|
+
| Event tracking latency (p99, `:always`) | <70µs | Full dry-schema validation per event |
|
|
19
|
+
| Event tracking latency (p99, `:sampled` 1%) | <10µs | Schema runs ~1% of events |
|
|
20
|
+
| Event tracking latency (p99, `:never`) | <50µs | Pipeline overhead, no validation |
|
|
21
|
+
| Memory allocations (`:always` mode) | ~47 objects/event | Baseline; threshold ≤72 |
|
|
22
|
+
| Memory allocations (`:never` mode) | ~33 objects/event | Baseline; threshold ≤50 |
|
|
23
|
+
| Memory retained after 10K events | 0 objects | No leaks detected |
|
|
24
|
+
| Memory consumption (1K events) | <100 MB allocated | Small-scale benchmark target |
|
|
25
|
+
|
|
26
|
+
## Validation Mode Trade-offs
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
# Fastest — skip schema checks in production hot paths
|
|
30
|
+
validation_mode :never # ~33 allocs/event, <50µs p99
|
|
31
|
+
|
|
32
|
+
# Balanced — validate 1% of traffic for regression detection
|
|
33
|
+
validation_mode :sampled, sample_rate: 0.01 # <10µs p99
|
|
34
|
+
|
|
35
|
+
# Safest — validate every event (default, recommended for dev/staging)
|
|
36
|
+
validation_mode :always # ~47 allocs/event, <70µs p99
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Running Benchmarks
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
rake spec:benchmark # latency benchmarks (~44 examples)
|
|
43
|
+
rake spec:memory # allocation and leak checks
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
See `spec/e11y/event/base_benchmark_spec.rb` and `spec/e11y/memory_spec.rb` for the full test suite.
|
|
47
|
+
|
|
48
|
+
## Cardinality Protection
|
|
49
|
+
|
|
50
|
+
Optional cardinality protection prevents high-cardinality labels from overwhelming metrics systems:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
E11y::Adapters::Loki.new(
|
|
54
|
+
url: "http://loki:3100",
|
|
55
|
+
enable_cardinality_protection: true, # default
|
|
56
|
+
max_label_cardinality: 1000 # ~1000 event types
|
|
57
|
+
)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Labels = `event_name` + `severity` only. Payload (user_uuid, etc.) stays in log line — filter via LogQL: `| json | user_uuid="xxx"`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# PII Filtering
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
E11y provides PII filtering capabilities for sensitive data.
|
|
6
|
+
|
|
7
|
+
## Rails Integration
|
|
8
|
+
|
|
9
|
+
E11y can respect `Rails.application.config.filter_parameters` when configured:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
# config/application.rb
|
|
13
|
+
config.filter_parameters += [:password, :email, :ssn, :credit_card]
|
|
14
|
+
|
|
15
|
+
# E11y will filter these fields when PII filtering middleware is enabled
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Explicit PII Strategies
|
|
19
|
+
|
|
20
|
+
Configure PII filtering per event:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
class PaymentEvent < E11y::Event::Base
|
|
24
|
+
contains_pii true
|
|
25
|
+
|
|
26
|
+
pii_filtering do
|
|
27
|
+
masks :card_number # Replace with "[FILTERED]"
|
|
28
|
+
hashes :user_email # SHA256 hash (searchable)
|
|
29
|
+
allows :amount # No filtering
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Available strategies:
|
|
35
|
+
|
|
36
|
+
- `masks` - Replace with "[FILTERED]"
|
|
37
|
+
- `hashes` - SHA256 hash (preserves searchability)
|
|
38
|
+
- `partials` - Show first/last characters
|
|
39
|
+
- `redacts` - Remove completely
|
|
40
|
+
- `allows` - No filtering
|
data/docs/PRESETS.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Presets
|
|
2
|
+
|
|
3
|
+
> Back to [README](../README.md#documentation)
|
|
4
|
+
|
|
5
|
+
E11y provides presets for common event types.
|
|
6
|
+
|
|
7
|
+
## HighValueEvent
|
|
8
|
+
|
|
9
|
+
For financial transactions and critical business events:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
class PaymentProcessedEvent < E11y::Event::Base
|
|
13
|
+
include E11y::Presets::HighValueEvent
|
|
14
|
+
|
|
15
|
+
schema do
|
|
16
|
+
required(:transaction_id).filled(:string)
|
|
17
|
+
required(:amount).filled(:decimal)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Configured with:
|
|
22
|
+
# - severity: :success
|
|
23
|
+
# - sample_rate: 1.0 (always sampled)
|
|
24
|
+
# - adapters: [:logs, :errors_tracker]
|
|
25
|
+
# - rate_limit: unlimited
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## AuditEvent
|
|
29
|
+
|
|
30
|
+
For compliance and audit trails:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
class UserDeletedEvent < E11y::Event::Base
|
|
34
|
+
include E11y::Presets::AuditEvent
|
|
35
|
+
|
|
36
|
+
schema do
|
|
37
|
+
required(:user_id).filled(:string)
|
|
38
|
+
required(:deleted_by).filled(:string)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Configured with:
|
|
43
|
+
# - sample_rate: 1.0 (never sampled)
|
|
44
|
+
# - rate_limit: unlimited
|
|
45
|
+
# Note: Set severity based on event criticality
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## DebugEvent
|
|
49
|
+
|
|
50
|
+
For development and troubleshooting:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
class SlowQueryEvent < E11y::Event::Base
|
|
54
|
+
include E11y::Presets::DebugEvent
|
|
55
|
+
|
|
56
|
+
schema do
|
|
57
|
+
required(:query).filled(:string)
|
|
58
|
+
required(:duration_ms).filled(:integer)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Configured with:
|
|
63
|
+
# - severity: :debug
|
|
64
|
+
# - adapters: [:logs]
|
|
65
|
+
```
|