e11y 0.2.0 → 1.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 +4 -4
- data/.rubocop.yml +130 -10
- data/CHANGELOG.md +80 -1
- data/CLAUDE.md +168 -0
- data/CONTRIBUTING.md +640 -0
- data/README.md +165 -701
- data/RELEASE.md +41 -12
- data/Rakefile +249 -57
- 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 +79 -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} +36 -65
- data/docs/{ADR-002-metrics-yabeda.md → architecture/ADR-002-metrics-yabeda.md} +62 -236
- data/docs/architecture/ADR-003-slo-observability.md +1402 -0
- 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} +182 -743
- 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} +44 -86
- data/docs/{ADR-012-event-evolution.md → architecture/ADR-012-event-evolution.md} +11 -11
- 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} +43 -59
- data/docs/{ADR-016-self-monitoring-slo.md → architecture/ADR-016-self-monitoring-slo.md} +58 -355
- 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/plans/2026-03-20-browser-overlay-svelte.md +281 -0
- 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 +33 -684
- 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 +30 -178
- data/docs/use_cases/UC-010-background-job-tracking.md +24 -91
- 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 +158 -0
- data/gems/e11y-devtools/config/routes.rb +15 -0
- data/gems/e11y-devtools/e11y-devtools.gemspec +25 -0
- data/gems/e11y-devtools/exe/e11y +34 -0
- data/gems/e11y-devtools/frontend/.gitignore +24 -0
- data/gems/e11y-devtools/frontend/README.md +51 -0
- data/gems/e11y-devtools/frontend/index.html +14 -0
- data/gems/e11y-devtools/frontend/package-lock.json +3707 -0
- data/gems/e11y-devtools/frontend/package.json +28 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/events/recent.json +4205 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/interactions.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/0a2e04027cfa22d014bc22e8b27cd913/events.json +86 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/0e1543af6a630fb3af6b52283154b3e0/events.json +169 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/1838b691faa49564f97db8592ff3978d/events.json +78 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/29f198f6588dacffb687777eb5f8f118/events.json +197 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/34bc3c9c0097de28a7a6f99b90a8e7bc/events.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/3ba6c20d068ab9cee00e51b180e66444/events.json +184 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/435bfd8f17b9009146a79812d7c3726d/events.json +144 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/4c7676e3fe668e99edb2b94d7d5678a9/events.json +222 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/6daf0d47974bedfc55d5de7004a3ea9f/events.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/8a81ada42834d15f287bb40010043605/events.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/8c0a98900edaae105469df8daedccf02/events.json +198 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/8e4f645180f8a7d1dce426b07380466b/events.json +222 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/93db346fa5d44a032605a13b627f4b80/events.json +128 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/98ff6146faf7bd9be8bd03a8275817ba/events.json +223 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/9997ddd0247bc7e25f2ca7a5c415c93d/events.json +197 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/99e35f8ef3baedd798cc4fd085980ad9/events.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/b4f3095c1909924cbc98889a86c83d6d/events.json +131 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/b54b7fc32b7575a7110de809d11ccda0/events.json +128 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/c0b48033fa06746bcc5886745e053cff/events.json +169 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/c44649ac76701b4558927cd2305ab535/events.json +169 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/d601ae3320057580a39dbdac2edfdf4a/events.json +248 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/e67e724bab422d2b52eeb49635e512e1/events.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/e6c72765a28f158a8485b35fa63f73da/events.json +194 -0
- data/gems/e11y-devtools/frontend/public/mocks/v1/traces/f541b87405c9a54819b18ebe529f6419/events.json +194 -0
- data/gems/e11y-devtools/frontend/scripts/generate_mocks.rb +397 -0
- data/gems/e11y-devtools/frontend/src/App.svelte +827 -0
- data/gems/e11y-devtools/frontend/src/components/Fab.svelte +19 -0
- data/gems/e11y-devtools/frontend/src/components/FilterBar.svelte +38 -0
- data/gems/e11y-devtools/frontend/src/components/FullscreenPanel.svelte +82 -0
- data/gems/e11y-devtools/frontend/src/components/InteractionsTimeline.svelte +264 -0
- data/gems/e11y-devtools/frontend/src/components/RecentHistogram.svelte +354 -0
- data/gems/e11y-devtools/frontend/src/lib/api.ts +37 -0
- data/gems/e11y-devtools/frontend/src/lib/eventIdentity.ts +12 -0
- data/gems/e11y-devtools/frontend/src/lib/format.ts +37 -0
- data/gems/e11y-devtools/frontend/src/lib/listFilter.ts +43 -0
- data/gems/e11y-devtools/frontend/src/lib/recentVolume.ts +80 -0
- data/gems/e11y-devtools/frontend/src/lib/router.ts +12 -0
- data/gems/e11y-devtools/frontend/src/lib/transitions.ts +34 -0
- data/gems/e11y-devtools/frontend/src/lib/viewportOrigin.ts +25 -0
- data/gems/e11y-devtools/frontend/src/main.ts +8 -0
- data/gems/e11y-devtools/frontend/src/overlay-entry.ts +24 -0
- data/gems/e11y-devtools/frontend/src/overlay.css +1080 -0
- data/gems/e11y-devtools/frontend/svelte.config.js +2 -0
- data/gems/e11y-devtools/frontend/test_puppeteer.js +41 -0
- data/gems/e11y-devtools/frontend/test_scale.js +3 -0
- data/gems/e11y-devtools/frontend/tsconfig.app.json +21 -0
- data/gems/e11y-devtools/frontend/tsconfig.json +7 -0
- data/gems/e11y-devtools/frontend/tsconfig.node.json +26 -0
- data/gems/e11y-devtools/frontend/vite.config.ts +36 -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 +20 -0
- data/gems/e11y-devtools/lib/e11y/devtools/overlay/controller.rb +94 -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 +67 -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 +91 -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 +44 -12
- data/lib/e11y/instruments/rails_instrumentation.rb +49 -24
- data/lib/e11y/instruments/sidekiq.rb +135 -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 +4 -4
- data/lib/e11y/presets/audit_event.rb +13 -2
- data/lib/e11y/railtie.rb +52 -14
- 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 +144 -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 +123 -266
- 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 +186 -39
- data/docs/ADR-003-slo-observability.md +0 -3337
- 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
|
@@ -42,7 +42,7 @@ Events::OrderPaid.track(
|
|
|
42
42
|
|
|
43
43
|
# Result:
|
|
44
44
|
# 1. Structured log in ELK/Loki (JSON)
|
|
45
|
-
# 2.
|
|
45
|
+
# 2. Event metrics (from metrics do block)
|
|
46
46
|
# 3. Trace context (automatic correlation)
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -102,22 +102,13 @@ class OrdersController < ApplicationController
|
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
# Step 3:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
# Histogram: orders.created.amount
|
|
114
|
-
histogram_for pattern: 'order.created',
|
|
115
|
-
name: 'orders.created.amount',
|
|
116
|
-
value: ->(e) { e.payload[:total_amount] },
|
|
117
|
-
tags: [:currency],
|
|
118
|
-
buckets: [10, 50, 100, 500, 1000, 5000]
|
|
119
|
-
end
|
|
120
|
-
end
|
|
105
|
+
# Step 3: Add metrics in event class
|
|
106
|
+
# class Events::OrderCreated < E11y::Event::Base
|
|
107
|
+
# metrics do
|
|
108
|
+
# counter :orders_created_total, tags: [:currency]
|
|
109
|
+
# histogram :orders_created_amount, value: :total_amount, tags: [:currency], buckets: [10, 50, 100, 500]
|
|
110
|
+
# end
|
|
111
|
+
# end
|
|
121
112
|
```
|
|
122
113
|
|
|
123
114
|
**Result in Logs (Loki/ELK):**
|
|
@@ -231,21 +222,7 @@ class RegistrationsController < ApplicationController
|
|
|
231
222
|
end
|
|
232
223
|
end
|
|
233
224
|
|
|
234
|
-
#
|
|
235
|
-
E11y.configure do |config|
|
|
236
|
-
config.metrics do
|
|
237
|
-
# Funnel counter
|
|
238
|
-
counter_for pattern: 'registration.*',
|
|
239
|
-
name: 'registration.funnel.total',
|
|
240
|
-
tags: [:event_name, :source]
|
|
241
|
-
|
|
242
|
-
# Time to first login
|
|
243
|
-
histogram_for pattern: 'first.login',
|
|
244
|
-
name: 'registration.time_to_first_login_hours',
|
|
245
|
-
value: ->(e) { e.payload[:time_since_registration_hours] },
|
|
246
|
-
buckets: [1, 6, 12, 24, 48, 72, 168] # hours
|
|
247
|
-
end
|
|
248
|
-
end
|
|
225
|
+
# Add metrics do in each event class (Events::RegistrationStarted, Events::EmailVerified, etc.)
|
|
249
226
|
```
|
|
250
227
|
|
|
251
228
|
**Funnel Analysis (Grafana/Prometheus):**
|
|
@@ -353,28 +330,7 @@ class ProcessPaymentJob < ApplicationJob
|
|
|
353
330
|
end
|
|
354
331
|
end
|
|
355
332
|
|
|
356
|
-
#
|
|
357
|
-
E11y.configure do |config|
|
|
358
|
-
config.metrics do
|
|
359
|
-
# Success rate (critical metric!)
|
|
360
|
-
success_rate_for pattern: 'payment.*',
|
|
361
|
-
name: 'payments.success_rate',
|
|
362
|
-
tags: [:payment_method]
|
|
363
|
-
# Auto-calculates: succeeded / (succeeded + failed) * 100
|
|
364
|
-
|
|
365
|
-
# Payment duration (performance)
|
|
366
|
-
histogram_for pattern: 'payment.succeeded',
|
|
367
|
-
value: ->(e) { e.duration_ms },
|
|
368
|
-
name: 'payments.duration_ms',
|
|
369
|
-
tags: [:payment_method],
|
|
370
|
-
buckets: [100, 250, 500, 1000, 2000, 5000]
|
|
371
|
-
|
|
372
|
-
# Failed payments by error code (debugging)
|
|
373
|
-
counter_for pattern: 'payment.failed',
|
|
374
|
-
name: 'payments.failed.total',
|
|
375
|
-
tags: [:error_code, :payment_method]
|
|
376
|
-
end
|
|
377
|
-
end
|
|
333
|
+
# Add metrics do in PaymentSucceeded, PaymentFailed event classes
|
|
378
334
|
```
|
|
379
335
|
|
|
380
336
|
**Alerts (Prometheus):**
|
|
@@ -505,7 +461,7 @@ module Events
|
|
|
505
461
|
rate_limit 1000
|
|
506
462
|
sample_rate 1.0 # Never sample payments (high-value)
|
|
507
463
|
retention 7.years # Financial records
|
|
508
|
-
adapters [:loki, :sentry
|
|
464
|
+
adapters [:loki, :sentry]
|
|
509
465
|
|
|
510
466
|
# Common PII filtering
|
|
511
467
|
contains_pii true
|
|
@@ -605,7 +561,7 @@ module E11y
|
|
|
605
561
|
rate_limit 10_000
|
|
606
562
|
sample_rate 1.0 # Never sample
|
|
607
563
|
retention 7.years
|
|
608
|
-
adapters [:loki, :sentry
|
|
564
|
+
adapters [:loki, :sentry]
|
|
609
565
|
end
|
|
610
566
|
end
|
|
611
567
|
|
|
@@ -669,7 +625,7 @@ module Events
|
|
|
669
625
|
rate_limit 5000
|
|
670
626
|
sample_rate 1.0
|
|
671
627
|
retention 7.years
|
|
672
|
-
adapters [:loki, :elasticsearch, :
|
|
628
|
+
adapters [:loki, :elasticsearch, :slack_business]
|
|
673
629
|
|
|
674
630
|
metric :counter,
|
|
675
631
|
name: 'critical_business_events.total',
|
|
@@ -1051,9 +1007,7 @@ E11y.configure do |config|
|
|
|
1051
1007
|
config.register_adapter :loki, E11y::Adapters::LokiAdapter.new(
|
|
1052
1008
|
url: ENV['LOKI_URL']
|
|
1053
1009
|
)
|
|
1054
|
-
|
|
1055
|
-
bucket: 'payment-archive'
|
|
1056
|
-
)
|
|
1010
|
+
# Archival: external jobs filter Loki by retention_until (ISO8601) for tier migration
|
|
1057
1011
|
config.default_adapters = [:loki]
|
|
1058
1012
|
|
|
1059
1013
|
when 'staging'
|
|
@@ -1082,9 +1036,9 @@ module Events
|
|
|
1082
1036
|
required(:amount).filled(:decimal)
|
|
1083
1037
|
end
|
|
1084
1038
|
|
|
1085
|
-
# Production:
|
|
1039
|
+
# Production: retention_period 7.years → retention_until in payload; archival jobs filter by it
|
|
1086
1040
|
if Rails.env.production?
|
|
1087
|
-
adapters [:loki
|
|
1041
|
+
adapters [:loki]
|
|
1088
1042
|
end
|
|
1089
1043
|
# Other envs: use default_adapters
|
|
1090
1044
|
end
|
|
@@ -1095,36 +1049,13 @@ end
|
|
|
1095
1049
|
|
|
1096
1050
|
## 📊 Metrics Configuration
|
|
1097
1051
|
|
|
1098
|
-
|
|
1052
|
+
Define metrics in each event class:
|
|
1099
1053
|
|
|
1100
1054
|
```ruby
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
name: 'business_events.total',
|
|
1106
|
-
tags: [:event_name, :severity]
|
|
1107
|
-
|
|
1108
|
-
# Domain-specific counters
|
|
1109
|
-
counter_for pattern: 'order.*',
|
|
1110
|
-
name: 'orders.events.total',
|
|
1111
|
-
tags: [:event_name]
|
|
1112
|
-
|
|
1113
|
-
counter_for pattern: 'user.*',
|
|
1114
|
-
name: 'users.events.total',
|
|
1115
|
-
tags: [:event_name]
|
|
1116
|
-
|
|
1117
|
-
# Histograms for amounts/durations
|
|
1118
|
-
histogram_for pattern: '*.paid',
|
|
1119
|
-
name: 'payments.amount',
|
|
1120
|
-
value: ->(e) { e.payload[:amount] },
|
|
1121
|
-
tags: [:currency],
|
|
1122
|
-
buckets: [10, 50, 100, 500, 1000, 5000, 10000]
|
|
1123
|
-
|
|
1124
|
-
# Success rate (special metric type)
|
|
1125
|
-
success_rate_for pattern: 'payment.*',
|
|
1126
|
-
name: 'payments.success_rate'
|
|
1127
|
-
# Automatically calculates from :success and :error events
|
|
1055
|
+
class Events::OrderCreated < E11y::Event::Base
|
|
1056
|
+
metrics do
|
|
1057
|
+
counter :orders_created_total, tags: [:currency]
|
|
1058
|
+
histogram :order_amount, value: :amount, tags: [:currency], buckets: [10, 50, 100, 500]
|
|
1128
1059
|
end
|
|
1129
1060
|
end
|
|
1130
1061
|
```
|
|
@@ -1542,7 +1473,7 @@ E11y is designed for **high-performance production environments** with strict SL
|
|
|
1542
1473
|
```ruby
|
|
1543
1474
|
# Benchmark: 1000 events/sec
|
|
1544
1475
|
Benchmark.ips do |x|
|
|
1545
|
-
x.report("
|
|
1476
|
+
x.report("EventClass.track") do
|
|
1546
1477
|
Events::OrderPaid.track(
|
|
1547
1478
|
order_id: 'ORD-123',
|
|
1548
1479
|
amount: 99.99
|
|
@@ -1551,7 +1482,7 @@ Benchmark.ips do |x|
|
|
|
1551
1482
|
end
|
|
1552
1483
|
|
|
1553
1484
|
# Results:
|
|
1554
|
-
#
|
|
1485
|
+
# EventClass.track: 100,000 i/s → ~0.01ms per call
|
|
1555
1486
|
# p99 latency: <1ms ✅
|
|
1556
1487
|
```
|
|
1557
1488
|
|
|
@@ -1918,11 +1849,11 @@ end
|
|
|
1918
1849
|
class Events::CriticalPayment < Events::BasePaymentEvent
|
|
1919
1850
|
include E11y::Presets::HighValueEvent
|
|
1920
1851
|
|
|
1921
|
-
adapters [:loki, :sentry
|
|
1852
|
+
adapters [:loki, :sentry]
|
|
1922
1853
|
|
|
1923
1854
|
# Final config:
|
|
1924
1855
|
# - severity: :success (from base)
|
|
1925
|
-
# - adapters: [:loki, :sentry
|
|
1856
|
+
# - adapters: [:loki, :sentry] (event-level override)
|
|
1926
1857
|
# - sample_rate: 1.0 (from base)
|
|
1927
1858
|
# - rate_limit: 10_000 (from preset)
|
|
1928
1859
|
# - retention: 7.years (from preset)
|
|
@@ -1943,7 +1874,7 @@ end
|
|
|
1943
1874
|
## 📚 Related Use Cases
|
|
1944
1875
|
|
|
1945
1876
|
- **[UC-001: Request-Scoped Debug Buffering](./UC-001-request-scoped-debug-buffering.md)** - Debug vs business events
|
|
1946
|
-
- **[UC-003:
|
|
1877
|
+
- **[UC-003: Event Metrics](./UC-003-event-metrics.md)** - Metrics in event classes
|
|
1947
1878
|
- **[UC-005: PII Filtering](./UC-005-pii-filtering.md)** - Secure event data
|
|
1948
1879
|
|
|
1949
1880
|
---
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# UC-003: Event Metrics
|
|
2
|
+
|
|
3
|
+
**Status:** Implemented
|
|
4
|
+
**Complexity:** Intermediate
|
|
5
|
+
**Setup Time:** 15-30 minutes
|
|
6
|
+
**Target Users:** DevOps, SRE, Backend Developers
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Define metrics directly in event classes. Metrics are registered at boot and updated automatically when events are tracked.
|
|
13
|
+
|
|
14
|
+
### Event-Level Metrics DSL
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
class Events::OrderPaid < E11y::Event::Base
|
|
18
|
+
schema do
|
|
19
|
+
required(:order_id).filled(:string)
|
|
20
|
+
required(:amount).filled(:float)
|
|
21
|
+
required(:currency).filled(:string)
|
|
22
|
+
required(:payment_method).filled(:string)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
metrics do
|
|
26
|
+
counter :orders_paid_total, tags: [:currency, :payment_method]
|
|
27
|
+
histogram :orders_paid_amount, value: :amount, tags: [:currency], buckets: [10, 50, 100, 500, 1000, 5000]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
Events::OrderPaid.track(order_id: '123', amount: 99.99, currency: 'USD', payment_method: 'stripe')
|
|
32
|
+
# → orders_paid_total{currency="USD",payment_method="stripe"} += 1
|
|
33
|
+
# → orders_paid_amount_bucket{currency="USD",le="100"} += 1
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Metric Types
|
|
37
|
+
|
|
38
|
+
- **counter** — monotonically increasing
|
|
39
|
+
- **histogram** — distribution (requires `value:` field, optional `buckets:`)
|
|
40
|
+
- **gauge** — point-in-time value (requires `value:`)
|
|
41
|
+
|
|
42
|
+
### Boot-Time Validation
|
|
43
|
+
|
|
44
|
+
E11y validates metrics at Rails boot: label conflicts, type conflicts. Non-Rails: call `E11y::Metrics::Registry.instance.validate_all!` after loading events.
|
|
45
|
+
|
|
46
|
+
### Shared Metrics via Inheritance
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
class BaseOrderEvent < E11y::Event::Base
|
|
50
|
+
metrics do
|
|
51
|
+
counter :orders_total, tags: [:currency, :status]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Events::OrderPaid < BaseOrderEvent
|
|
56
|
+
metrics do
|
|
57
|
+
histogram :order_amount, value: :amount, tags: [:currency]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Yabeda Integration
|
|
65
|
+
|
|
66
|
+
Register Yabeda adapter in `config.adapters`. Metrics flow to Prometheus via Yabeda.
|