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.
Files changed (288) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +130 -10
  3. data/CHANGELOG.md +80 -1
  4. data/CLAUDE.md +168 -0
  5. data/CONTRIBUTING.md +640 -0
  6. data/README.md +165 -701
  7. data/RELEASE.md +41 -12
  8. data/Rakefile +249 -57
  9. data/config/README.md +1 -1
  10. data/config/loki-local-config.yaml +12 -0
  11. data/config/otel-collector-config.yaml +44 -0
  12. data/cucumber.yml +1 -0
  13. data/docker-compose.yml +18 -2
  14. data/docs/ADAPTERS.md +76 -0
  15. data/docs/ADAPTIVE_SAMPLING.md +59 -0
  16. data/docs/COMPARISON.md +104 -0
  17. data/docs/CONFIGURATION.md +52 -0
  18. data/docs/DISTRIBUTED_TRACING.md +44 -0
  19. data/docs/LIMITATIONS.md +13 -0
  20. data/docs/METRICS_DSL.md +84 -0
  21. data/docs/PERFORMANCE.md +60 -0
  22. data/docs/PII_FILTERING.md +40 -0
  23. data/docs/PRESETS.md +65 -0
  24. data/docs/QUICK-START.md +546 -587
  25. data/docs/RAILS_INTEGRATION.md +79 -0
  26. data/docs/SCHEMA_VALIDATION.md +63 -0
  27. data/docs/SLO-PROMQL-ALERTS.md +161 -0
  28. data/docs/TESTING.md +69 -0
  29. data/docs/{ADR-001-architecture.md → architecture/ADR-001-architecture.md} +36 -65
  30. data/docs/{ADR-002-metrics-yabeda.md → architecture/ADR-002-metrics-yabeda.md} +62 -236
  31. data/docs/architecture/ADR-003-slo-observability.md +1402 -0
  32. data/docs/{ADR-004-adapter-architecture.md → architecture/ADR-004-adapter-architecture.md} +163 -146
  33. data/docs/{ADR-005-tracing-context.md → architecture/ADR-005-tracing-context.md} +10 -9
  34. data/docs/{ADR-006-security-compliance.md → architecture/ADR-006-security-compliance.md} +184 -191
  35. data/docs/{ADR-007-opentelemetry-integration.md → architecture/ADR-007-opentelemetry-integration.md} +3 -21
  36. data/docs/{ADR-008-rails-integration.md → architecture/ADR-008-rails-integration.md} +182 -743
  37. data/docs/{ADR-009-cost-optimization.md → architecture/ADR-009-cost-optimization.md} +45 -54
  38. data/docs/architecture/ADR-010-developer-experience.md +522 -0
  39. data/docs/{ADR-011-testing-strategy.md → architecture/ADR-011-testing-strategy.md} +44 -86
  40. data/docs/{ADR-012-event-evolution.md → architecture/ADR-012-event-evolution.md} +11 -11
  41. data/docs/{ADR-013-reliability-error-handling.md → architecture/ADR-013-reliability-error-handling.md} +37 -12
  42. data/docs/{ADR-014-event-driven-slo.md → architecture/ADR-014-event-driven-slo.md} +12 -24
  43. data/docs/{ADR-015-middleware-order.md → architecture/ADR-015-middleware-order.md} +43 -59
  44. data/docs/{ADR-016-self-monitoring-slo.md → architecture/ADR-016-self-monitoring-slo.md} +58 -355
  45. data/docs/{ADR-017-multi-rails-compatibility.md → architecture/ADR-017-multi-rails-compatibility.md} +4 -11
  46. data/docs/architecture/ADR-018-memory-optimization.md +366 -0
  47. data/docs/{ADR-INDEX.md → architecture/ADR-INDEX.md} +11 -6
  48. data/docs/plans/2026-03-20-browser-overlay-svelte.md +281 -0
  49. data/docs/{00-ICP-AND-TIMELINE.md → prd/00-ICP-AND-TIMELINE.md} +6 -6
  50. data/docs/{01-SCALE-REQUIREMENTS.md → prd/01-SCALE-REQUIREMENTS.md} +6 -6
  51. data/docs/prd/01-overview-vision.md +19 -14
  52. data/docs/use_cases/README.md +22 -23
  53. data/docs/use_cases/UC-001-request-scoped-debug-buffering.md +50 -44
  54. data/docs/use_cases/UC-002-business-event-tracking.md +26 -95
  55. data/docs/use_cases/UC-003-event-metrics.md +66 -0
  56. data/docs/use_cases/UC-004-zero-config-slo-tracking.md +33 -684
  57. data/docs/use_cases/UC-005-sentry-integration.md +13 -15
  58. data/docs/use_cases/UC-006-trace-context-management.md +30 -28
  59. data/docs/use_cases/UC-007-pii-filtering.md +35 -87
  60. data/docs/use_cases/UC-008-opentelemetry-integration.md +51 -89
  61. data/docs/use_cases/UC-009-multi-service-tracing.md +30 -178
  62. data/docs/use_cases/UC-010-background-job-tracking.md +24 -91
  63. data/docs/use_cases/UC-011-rate-limiting.md +95 -168
  64. data/docs/use_cases/UC-012-audit-trail.md +21 -46
  65. data/docs/use_cases/UC-013-high-cardinality-protection.md +29 -167
  66. data/docs/use_cases/UC-014-adaptive-sampling.md +2 -2
  67. data/docs/use_cases/UC-015-cost-optimization.md +46 -99
  68. data/docs/use_cases/UC-016-rails-logger-migration.md +39 -213
  69. data/docs/use_cases/UC-017-local-development.md +203 -777
  70. data/docs/use_cases/UC-018-testing-events.md +3 -3
  71. data/docs/use_cases/UC-019-retention-based-routing.md +53 -106
  72. data/docs/use_cases/UC-020-event-versioning.md +8 -9
  73. data/docs/use_cases/UC-021-error-handling-retry-dlq.md +18 -22
  74. data/docs/use_cases/UC-022-event-registry.md +15 -21
  75. data/docs/use_cases/backlog.md +119 -87
  76. data/e11y.gemspec +2 -2
  77. data/gems/e11y-devtools/README.md +158 -0
  78. data/gems/e11y-devtools/config/routes.rb +15 -0
  79. data/gems/e11y-devtools/e11y-devtools.gemspec +25 -0
  80. data/gems/e11y-devtools/exe/e11y +34 -0
  81. data/gems/e11y-devtools/frontend/.gitignore +24 -0
  82. data/gems/e11y-devtools/frontend/README.md +51 -0
  83. data/gems/e11y-devtools/frontend/index.html +14 -0
  84. data/gems/e11y-devtools/frontend/package-lock.json +3707 -0
  85. data/gems/e11y-devtools/frontend/package.json +28 -0
  86. data/gems/e11y-devtools/frontend/public/mocks/v1/events/recent.json +4205 -0
  87. data/gems/e11y-devtools/frontend/public/mocks/v1/interactions.json +194 -0
  88. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/0a2e04027cfa22d014bc22e8b27cd913/events.json +86 -0
  89. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/0e1543af6a630fb3af6b52283154b3e0/events.json +169 -0
  90. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/1838b691faa49564f97db8592ff3978d/events.json +78 -0
  91. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/29f198f6588dacffb687777eb5f8f118/events.json +197 -0
  92. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/34bc3c9c0097de28a7a6f99b90a8e7bc/events.json +194 -0
  93. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/3ba6c20d068ab9cee00e51b180e66444/events.json +184 -0
  94. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/435bfd8f17b9009146a79812d7c3726d/events.json +144 -0
  95. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/4c7676e3fe668e99edb2b94d7d5678a9/events.json +222 -0
  96. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/6daf0d47974bedfc55d5de7004a3ea9f/events.json +194 -0
  97. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/8a81ada42834d15f287bb40010043605/events.json +194 -0
  98. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/8c0a98900edaae105469df8daedccf02/events.json +198 -0
  99. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/8e4f645180f8a7d1dce426b07380466b/events.json +222 -0
  100. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/93db346fa5d44a032605a13b627f4b80/events.json +128 -0
  101. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/98ff6146faf7bd9be8bd03a8275817ba/events.json +223 -0
  102. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/9997ddd0247bc7e25f2ca7a5c415c93d/events.json +197 -0
  103. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/99e35f8ef3baedd798cc4fd085980ad9/events.json +194 -0
  104. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/b4f3095c1909924cbc98889a86c83d6d/events.json +131 -0
  105. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/b54b7fc32b7575a7110de809d11ccda0/events.json +128 -0
  106. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/c0b48033fa06746bcc5886745e053cff/events.json +169 -0
  107. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/c44649ac76701b4558927cd2305ab535/events.json +169 -0
  108. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/d601ae3320057580a39dbdac2edfdf4a/events.json +248 -0
  109. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/e67e724bab422d2b52eeb49635e512e1/events.json +194 -0
  110. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/e6c72765a28f158a8485b35fa63f73da/events.json +194 -0
  111. data/gems/e11y-devtools/frontend/public/mocks/v1/traces/f541b87405c9a54819b18ebe529f6419/events.json +194 -0
  112. data/gems/e11y-devtools/frontend/scripts/generate_mocks.rb +397 -0
  113. data/gems/e11y-devtools/frontend/src/App.svelte +827 -0
  114. data/gems/e11y-devtools/frontend/src/components/Fab.svelte +19 -0
  115. data/gems/e11y-devtools/frontend/src/components/FilterBar.svelte +38 -0
  116. data/gems/e11y-devtools/frontend/src/components/FullscreenPanel.svelte +82 -0
  117. data/gems/e11y-devtools/frontend/src/components/InteractionsTimeline.svelte +264 -0
  118. data/gems/e11y-devtools/frontend/src/components/RecentHistogram.svelte +354 -0
  119. data/gems/e11y-devtools/frontend/src/lib/api.ts +37 -0
  120. data/gems/e11y-devtools/frontend/src/lib/eventIdentity.ts +12 -0
  121. data/gems/e11y-devtools/frontend/src/lib/format.ts +37 -0
  122. data/gems/e11y-devtools/frontend/src/lib/listFilter.ts +43 -0
  123. data/gems/e11y-devtools/frontend/src/lib/recentVolume.ts +80 -0
  124. data/gems/e11y-devtools/frontend/src/lib/router.ts +12 -0
  125. data/gems/e11y-devtools/frontend/src/lib/transitions.ts +34 -0
  126. data/gems/e11y-devtools/frontend/src/lib/viewportOrigin.ts +25 -0
  127. data/gems/e11y-devtools/frontend/src/main.ts +8 -0
  128. data/gems/e11y-devtools/frontend/src/overlay-entry.ts +24 -0
  129. data/gems/e11y-devtools/frontend/src/overlay.css +1080 -0
  130. data/gems/e11y-devtools/frontend/svelte.config.js +2 -0
  131. data/gems/e11y-devtools/frontend/test_puppeteer.js +41 -0
  132. data/gems/e11y-devtools/frontend/test_scale.js +3 -0
  133. data/gems/e11y-devtools/frontend/tsconfig.app.json +21 -0
  134. data/gems/e11y-devtools/frontend/tsconfig.json +7 -0
  135. data/gems/e11y-devtools/frontend/tsconfig.node.json +26 -0
  136. data/gems/e11y-devtools/frontend/vite.config.ts +36 -0
  137. data/gems/e11y-devtools/lib/e11y/devtools/mcp/server.rb +96 -0
  138. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tool_base.rb +25 -0
  139. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/clear.rb +31 -0
  140. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/errors.rb +35 -0
  141. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/event_detail.rb +33 -0
  142. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/events_by_trace.rb +33 -0
  143. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/interactions.rb +40 -0
  144. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/recent_events.rb +34 -0
  145. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/search.rb +34 -0
  146. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/stats.rb +30 -0
  147. data/gems/e11y-devtools/lib/e11y/devtools/overlay/assets/overlay.js +20 -0
  148. data/gems/e11y-devtools/lib/e11y/devtools/overlay/controller.rb +94 -0
  149. data/gems/e11y-devtools/lib/e11y/devtools/overlay/engine.rb +26 -0
  150. data/gems/e11y-devtools/lib/e11y/devtools/overlay/middleware.rb +80 -0
  151. data/gems/e11y-devtools/lib/e11y/devtools/overlay/rails_controller.rb +67 -0
  152. data/gems/e11y-devtools/lib/e11y/devtools/tui/app.rb +262 -0
  153. data/gems/e11y-devtools/lib/e11y/devtools/tui/grouping.rb +66 -0
  154. data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/event_detail.rb +62 -0
  155. data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/event_list.rb +70 -0
  156. data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/interaction_list.rb +47 -0
  157. data/gems/e11y-devtools/lib/e11y/devtools/version.rb +8 -0
  158. data/gems/e11y-devtools/lib/e11y/devtools.rb +13 -0
  159. data/gems/e11y-devtools/spec/e11y/devtools/mcp/tools_spec.rb +107 -0
  160. data/gems/e11y-devtools/spec/e11y/devtools/overlay/controller_spec.rb +91 -0
  161. data/gems/e11y-devtools/spec/e11y/devtools/overlay/middleware_spec.rb +46 -0
  162. data/gems/e11y-devtools/spec/e11y/devtools/tui/app_spec.rb +85 -0
  163. data/gems/e11y-devtools/spec/e11y/devtools/tui/grouping_spec.rb +64 -0
  164. data/gems/e11y-devtools/spec/spec_helper.rb +5 -0
  165. data/gems/e11y-devtools/spec/tui/widgets/event_list_spec.rb +44 -0
  166. data/gems/e11y-devtools/spec/tui/widgets/interaction_list_spec.rb +62 -0
  167. data/lib/e11y/adapters/audit_encrypted.rb +53 -11
  168. data/lib/e11y/adapters/base.rb +33 -34
  169. data/lib/e11y/adapters/dev_log/file_store.rb +143 -0
  170. data/lib/e11y/adapters/dev_log/query.rb +219 -0
  171. data/lib/e11y/adapters/dev_log.rb +118 -0
  172. data/lib/e11y/adapters/file.rb +3 -6
  173. data/lib/e11y/adapters/in_memory.rb +52 -5
  174. data/lib/e11y/adapters/in_memory_test.rb +29 -0
  175. data/lib/e11y/adapters/loki.rb +58 -23
  176. data/lib/e11y/adapters/null.rb +82 -0
  177. data/lib/e11y/adapters/opentelemetry_collector.rb +183 -0
  178. data/lib/e11y/adapters/otel_logs.rb +136 -23
  179. data/lib/e11y/adapters/sentry.rb +4 -7
  180. data/lib/e11y/adapters/stdout.rb +73 -7
  181. data/lib/e11y/adapters/yabeda.rb +153 -29
  182. data/lib/e11y/buffers/adaptive_buffer.rb +3 -17
  183. data/lib/e11y/buffers/{request_scoped_buffer.rb → ephemeral_buffer.rb} +72 -58
  184. data/lib/e11y/buffers/ring_buffer.rb +3 -16
  185. data/lib/e11y/configuration.rb +272 -0
  186. data/lib/e11y/console.rb +10 -17
  187. data/lib/e11y/current.rb +53 -1
  188. data/lib/e11y/debug/pipeline_inspector.rb +96 -0
  189. data/lib/e11y/documentation/generator.rb +48 -0
  190. data/lib/e11y/event/base.rb +176 -82
  191. data/lib/e11y/event/value_sampling_config.rb +1 -5
  192. data/lib/e11y/events/rails/database/query.rb +1 -4
  193. data/lib/e11y/events/rails/job/failed.rb +2 -0
  194. data/lib/e11y/instruments/active_job.rb +44 -12
  195. data/lib/e11y/instruments/rails_instrumentation.rb +49 -24
  196. data/lib/e11y/instruments/sidekiq.rb +135 -31
  197. data/lib/e11y/linters/base.rb +11 -0
  198. data/lib/e11y/linters/pii/pii_declaration_linter.rb +120 -0
  199. data/lib/e11y/linters/slo/config_consistency_linter.rb +76 -0
  200. data/lib/e11y/linters/slo/explicit_declaration_linter.rb +36 -0
  201. data/lib/e11y/linters/slo/slo_status_from_linter.rb +41 -0
  202. data/lib/e11y/logger/bridge.rb +26 -7
  203. data/lib/e11y/metrics/cardinality_protection.rb +10 -15
  204. data/lib/e11y/metrics/cardinality_tracker.rb +16 -6
  205. data/lib/e11y/metrics/registry.rb +3 -5
  206. data/lib/e11y/metrics/test_backend.rb +62 -0
  207. data/lib/e11y/metrics.rb +56 -10
  208. data/lib/e11y/middleware/adapter_resolver.rb +40 -0
  209. data/lib/e11y/middleware/audit_signing.rb +43 -6
  210. data/lib/e11y/middleware/baggage_protection.rb +75 -0
  211. data/lib/e11y/middleware/dev_log_source.rb +24 -0
  212. data/lib/e11y/middleware/event_slo.rb +23 -9
  213. data/lib/e11y/middleware/otel_span.rb +23 -0
  214. data/lib/e11y/middleware/pii_filter.rb +104 -75
  215. data/lib/e11y/middleware/rate_limiting.rb +54 -27
  216. data/lib/e11y/middleware/request.rb +70 -23
  217. data/lib/e11y/middleware/routing.rb +78 -21
  218. data/lib/e11y/middleware/sampling.rb +66 -17
  219. data/lib/e11y/middleware/self_monitoring_emit.rb +39 -0
  220. data/lib/e11y/middleware/trace_context.rb +45 -10
  221. data/lib/e11y/middleware/track_latency.rb +34 -0
  222. data/lib/e11y/middleware/validation.rb +7 -16
  223. data/lib/e11y/middleware/versioning.rb +26 -22
  224. data/lib/e11y/opentelemetry/semantic_conventions.rb +109 -0
  225. data/lib/e11y/opentelemetry/span_creator.rb +142 -0
  226. data/lib/e11y/pii/patterns.rb +12 -1
  227. data/lib/e11y/pipeline/builder.rb +4 -4
  228. data/lib/e11y/presets/audit_event.rb +13 -2
  229. data/lib/e11y/railtie.rb +52 -14
  230. data/lib/e11y/registry.rb +306 -0
  231. data/lib/e11y/reliability/circuit_breaker.rb +19 -21
  232. data/lib/e11y/reliability/dlq/base.rb +71 -0
  233. data/lib/e11y/reliability/dlq/file_adapter.rb +301 -0
  234. data/lib/e11y/reliability/dlq/file_storage.rb +63 -34
  235. data/lib/e11y/reliability/dlq/filter.rb +37 -54
  236. data/lib/e11y/reliability/retry_handler.rb +26 -29
  237. data/lib/e11y/reliability/retry_rate_limiter.rb +3 -11
  238. data/lib/e11y/sampling/error_spike_detector.rb +0 -2
  239. data/lib/e11y/sampling/load_monitor.rb +5 -9
  240. data/lib/e11y/sampling/stratified_tracker.rb +18 -0
  241. data/lib/e11y/self_monitoring/buffer_monitor.rb +2 -0
  242. data/lib/e11y/self_monitoring/performance_monitor.rb +19 -61
  243. data/lib/e11y/self_monitoring/reliability_monitor.rb +4 -74
  244. data/lib/e11y/slo/config_loader.rb +40 -0
  245. data/lib/e11y/slo/config_validator.rb +58 -0
  246. data/lib/e11y/slo/dashboard_generator.rb +122 -0
  247. data/lib/e11y/slo/event_driven.rb +8 -0
  248. data/lib/e11y/slo/tracker.rb +31 -4
  249. data/lib/e11y/testing/have_tracked_event_matcher.rb +190 -0
  250. data/lib/e11y/testing/rspec_matchers.rb +21 -0
  251. data/lib/e11y/testing/snapshot_matcher.rb +86 -0
  252. data/lib/e11y/trace_context/sampler.rb +35 -0
  253. data/lib/e11y/tracing/faraday_middleware.rb +31 -0
  254. data/lib/e11y/tracing/net_http_patch.rb +33 -0
  255. data/lib/e11y/tracing/propagator.rb +144 -0
  256. data/lib/e11y/tracing.rb +47 -0
  257. data/lib/e11y/version.rb +1 -1
  258. data/lib/e11y/versioning/version_extractor.rb +32 -0
  259. data/lib/e11y.rb +123 -266
  260. data/lib/generators/e11y/event/event_generator.rb +22 -0
  261. data/lib/generators/e11y/event/templates/event.rb.tt +16 -0
  262. data/lib/generators/e11y/grafana_dashboard/grafana_dashboard_generator.rb +30 -0
  263. data/lib/generators/e11y/grafana_dashboard/templates/e11y_dashboard.json +81 -0
  264. data/lib/generators/e11y/install/install_generator.rb +34 -0
  265. data/lib/generators/e11y/install/templates/e11y.rb +239 -0
  266. data/lib/generators/e11y/prometheus_alerts/prometheus_alerts_generator.rb +29 -0
  267. data/lib/generators/e11y/prometheus_alerts/templates/e11y_alerts.yml +28 -0
  268. data/lib/tasks/e11y_docs.rake +30 -0
  269. data/lib/tasks/e11y_events.rake +71 -0
  270. data/lib/tasks/e11y_lint.rake +91 -0
  271. data/lib/tasks/e11y_slo.rake +29 -0
  272. metadata +186 -39
  273. data/docs/ADR-003-slo-observability.md +0 -3337
  274. data/docs/ADR-010-developer-experience.md +0 -2166
  275. data/docs/API-REFERENCE-L28.md +0 -914
  276. data/docs/COMPREHENSIVE-CONFIGURATION.md +0 -2366
  277. data/docs/CONTRIBUTING.md +0 -312
  278. data/docs/IMPLEMENTATION_NOTES.md +0 -2804
  279. data/docs/IMPLEMENTATION_PLAN.md +0 -1971
  280. data/docs/IMPLEMENTATION_PLAN_ARCHITECTURE.md +0 -586
  281. data/docs/PLAN.md +0 -148
  282. data/docs/README.md +0 -296
  283. data/docs/design/00-memory-optimization.md +0 -593
  284. data/docs/guides/MIGRATION-L27-L28.md +0 -692
  285. data/docs/guides/PERFORMANCE-BENCHMARKS.md +0 -434
  286. data/docs/guides/README.md +0 -44
  287. data/docs/use_cases/UC-003-pattern-based-metrics.md +0 -1627
  288. 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. Auto-generated metrics (pattern-based)
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: Configure pattern-based metrics (config/initializers/e11y.rb)
106
- E11y.configure do |config|
107
- config.metrics do
108
- # Counter: orders.created.total
109
- counter_for pattern: 'order.created',
110
- name: 'orders.created.total',
111
- tags: [:currency]
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
- # Metrics configuration
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
- # Metrics
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, :s3_archive]
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, :s3_archive]
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, :s3_archive, :slack_business]
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
- config.register_adapter :s3_archive, E11y::Adapters::S3Adapter.new(
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: also archive to S3
1039
+ # Production: retention_period 7.years retention_until in payload; archival jobs filter by it
1086
1040
  if Rails.env.production?
1087
- adapters [:loki, :s3_archive]
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
- ### Pattern-Based Auto-Metrics
1052
+ Define metrics in each event class:
1099
1053
 
1100
1054
  ```ruby
1101
- E11y.configure do |config|
1102
- config.metrics do
1103
- # Global counter for ALL events
1104
- counter_for pattern: '*',
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("E11y.track") do
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
- # E11y.track: 100,000 i/s → ~0.01ms per call
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, :s3_archive] # Override base (add S3)
1852
+ adapters [:loki, :sentry]
1922
1853
 
1923
1854
  # Final config:
1924
1855
  # - severity: :success (from base)
1925
- # - adapters: [:loki, :sentry, :s3_archive] (event-level override)
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: Pattern-Based Metrics](./UC-003-pattern-based-metrics.md)** - Auto-generate metrics
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.