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.
Files changed (230) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +130 -10
  3. data/CHANGELOG.md +56 -1
  4. data/CLAUDE.md +168 -0
  5. data/CONTRIBUTING.md +640 -0
  6. data/README.md +134 -702
  7. data/RELEASE.md +18 -3
  8. data/Rakefile +108 -29
  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 +29 -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} +35 -64
  30. data/docs/{ADR-002-metrics-yabeda.md → architecture/ADR-002-metrics-yabeda.md} +62 -236
  31. data/docs/{ADR-003-slo-observability.md → architecture/ADR-003-slo-observability.md} +27 -466
  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} +209 -339
  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} +41 -83
  40. data/docs/{ADR-013-reliability-error-handling.md → architecture/ADR-013-reliability-error-handling.md} +37 -12
  41. data/docs/{ADR-014-event-driven-slo.md → architecture/ADR-014-event-driven-slo.md} +12 -24
  42. data/docs/{ADR-015-middleware-order.md → architecture/ADR-015-middleware-order.md} +23 -41
  43. data/docs/{ADR-016-self-monitoring-slo.md → architecture/ADR-016-self-monitoring-slo.md} +52 -349
  44. data/docs/{ADR-017-multi-rails-compatibility.md → architecture/ADR-017-multi-rails-compatibility.md} +4 -11
  45. data/docs/architecture/ADR-018-memory-optimization.md +366 -0
  46. data/docs/{ADR-INDEX.md → architecture/ADR-INDEX.md} +11 -6
  47. data/docs/{00-ICP-AND-TIMELINE.md → prd/00-ICP-AND-TIMELINE.md} +6 -6
  48. data/docs/{01-SCALE-REQUIREMENTS.md → prd/01-SCALE-REQUIREMENTS.md} +6 -6
  49. data/docs/prd/01-overview-vision.md +19 -14
  50. data/docs/use_cases/README.md +22 -23
  51. data/docs/use_cases/UC-001-request-scoped-debug-buffering.md +50 -44
  52. data/docs/use_cases/UC-002-business-event-tracking.md +26 -95
  53. data/docs/use_cases/UC-003-event-metrics.md +66 -0
  54. data/docs/use_cases/UC-004-zero-config-slo-tracking.md +42 -101
  55. data/docs/use_cases/UC-005-sentry-integration.md +13 -15
  56. data/docs/use_cases/UC-006-trace-context-management.md +30 -28
  57. data/docs/use_cases/UC-007-pii-filtering.md +35 -87
  58. data/docs/use_cases/UC-008-opentelemetry-integration.md +51 -89
  59. data/docs/use_cases/UC-009-multi-service-tracing.md +4 -4
  60. data/docs/use_cases/UC-010-background-job-tracking.md +5 -5
  61. data/docs/use_cases/UC-011-rate-limiting.md +95 -168
  62. data/docs/use_cases/UC-012-audit-trail.md +21 -46
  63. data/docs/use_cases/UC-013-high-cardinality-protection.md +29 -167
  64. data/docs/use_cases/UC-014-adaptive-sampling.md +2 -2
  65. data/docs/use_cases/UC-015-cost-optimization.md +46 -99
  66. data/docs/use_cases/UC-016-rails-logger-migration.md +39 -213
  67. data/docs/use_cases/UC-017-local-development.md +203 -777
  68. data/docs/use_cases/UC-018-testing-events.md +3 -3
  69. data/docs/use_cases/UC-019-retention-based-routing.md +53 -106
  70. data/docs/use_cases/UC-020-event-versioning.md +8 -9
  71. data/docs/use_cases/UC-021-error-handling-retry-dlq.md +18 -22
  72. data/docs/use_cases/UC-022-event-registry.md +15 -21
  73. data/docs/use_cases/backlog.md +119 -87
  74. data/e11y.gemspec +2 -2
  75. data/gems/e11y-devtools/README.md +136 -0
  76. data/gems/e11y-devtools/config/routes.rb +8 -0
  77. data/gems/e11y-devtools/e11y-devtools.gemspec +25 -0
  78. data/gems/e11y-devtools/exe/e11y +34 -0
  79. data/gems/e11y-devtools/lib/e11y/devtools/mcp/server.rb +96 -0
  80. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tool_base.rb +25 -0
  81. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/clear.rb +31 -0
  82. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/errors.rb +35 -0
  83. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/event_detail.rb +33 -0
  84. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/events_by_trace.rb +33 -0
  85. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/interactions.rb +40 -0
  86. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/recent_events.rb +34 -0
  87. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/search.rb +34 -0
  88. data/gems/e11y-devtools/lib/e11y/devtools/mcp/tools/stats.rb +30 -0
  89. data/gems/e11y-devtools/lib/e11y/devtools/overlay/assets/overlay.js +115 -0
  90. data/gems/e11y-devtools/lib/e11y/devtools/overlay/controller.rb +54 -0
  91. data/gems/e11y-devtools/lib/e11y/devtools/overlay/engine.rb +26 -0
  92. data/gems/e11y-devtools/lib/e11y/devtools/overlay/middleware.rb +80 -0
  93. data/gems/e11y-devtools/lib/e11y/devtools/overlay/rails_controller.rb +42 -0
  94. data/gems/e11y-devtools/lib/e11y/devtools/tui/app.rb +262 -0
  95. data/gems/e11y-devtools/lib/e11y/devtools/tui/grouping.rb +66 -0
  96. data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/event_detail.rb +62 -0
  97. data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/event_list.rb +70 -0
  98. data/gems/e11y-devtools/lib/e11y/devtools/tui/widgets/interaction_list.rb +47 -0
  99. data/gems/e11y-devtools/lib/e11y/devtools/version.rb +8 -0
  100. data/gems/e11y-devtools/lib/e11y/devtools.rb +13 -0
  101. data/gems/e11y-devtools/spec/e11y/devtools/mcp/tools_spec.rb +107 -0
  102. data/gems/e11y-devtools/spec/e11y/devtools/overlay/controller_spec.rb +58 -0
  103. data/gems/e11y-devtools/spec/e11y/devtools/overlay/middleware_spec.rb +46 -0
  104. data/gems/e11y-devtools/spec/e11y/devtools/tui/app_spec.rb +85 -0
  105. data/gems/e11y-devtools/spec/e11y/devtools/tui/grouping_spec.rb +64 -0
  106. data/gems/e11y-devtools/spec/spec_helper.rb +5 -0
  107. data/gems/e11y-devtools/spec/tui/widgets/event_list_spec.rb +44 -0
  108. data/gems/e11y-devtools/spec/tui/widgets/interaction_list_spec.rb +62 -0
  109. data/lib/e11y/adapters/audit_encrypted.rb +53 -11
  110. data/lib/e11y/adapters/base.rb +33 -34
  111. data/lib/e11y/adapters/dev_log/file_store.rb +143 -0
  112. data/lib/e11y/adapters/dev_log/query.rb +219 -0
  113. data/lib/e11y/adapters/dev_log.rb +118 -0
  114. data/lib/e11y/adapters/file.rb +3 -6
  115. data/lib/e11y/adapters/in_memory.rb +52 -5
  116. data/lib/e11y/adapters/in_memory_test.rb +29 -0
  117. data/lib/e11y/adapters/loki.rb +58 -23
  118. data/lib/e11y/adapters/null.rb +82 -0
  119. data/lib/e11y/adapters/opentelemetry_collector.rb +183 -0
  120. data/lib/e11y/adapters/otel_logs.rb +136 -23
  121. data/lib/e11y/adapters/sentry.rb +4 -7
  122. data/lib/e11y/adapters/stdout.rb +73 -7
  123. data/lib/e11y/adapters/yabeda.rb +153 -29
  124. data/lib/e11y/buffers/adaptive_buffer.rb +3 -17
  125. data/lib/e11y/buffers/{request_scoped_buffer.rb → ephemeral_buffer.rb} +72 -58
  126. data/lib/e11y/buffers/ring_buffer.rb +3 -16
  127. data/lib/e11y/configuration.rb +272 -0
  128. data/lib/e11y/console.rb +10 -17
  129. data/lib/e11y/current.rb +53 -1
  130. data/lib/e11y/debug/pipeline_inspector.rb +96 -0
  131. data/lib/e11y/documentation/generator.rb +48 -0
  132. data/lib/e11y/event/base.rb +176 -82
  133. data/lib/e11y/event/value_sampling_config.rb +1 -5
  134. data/lib/e11y/events/rails/database/query.rb +1 -4
  135. data/lib/e11y/events/rails/job/failed.rb +2 -0
  136. data/lib/e11y/instruments/active_job.rb +46 -12
  137. data/lib/e11y/instruments/rails_instrumentation.rb +49 -24
  138. data/lib/e11y/instruments/sidekiq.rb +137 -31
  139. data/lib/e11y/linters/base.rb +11 -0
  140. data/lib/e11y/linters/pii/pii_declaration_linter.rb +120 -0
  141. data/lib/e11y/linters/slo/config_consistency_linter.rb +76 -0
  142. data/lib/e11y/linters/slo/explicit_declaration_linter.rb +36 -0
  143. data/lib/e11y/linters/slo/slo_status_from_linter.rb +41 -0
  144. data/lib/e11y/logger/bridge.rb +26 -7
  145. data/lib/e11y/metrics/cardinality_protection.rb +10 -15
  146. data/lib/e11y/metrics/cardinality_tracker.rb +16 -6
  147. data/lib/e11y/metrics/registry.rb +3 -5
  148. data/lib/e11y/metrics/test_backend.rb +62 -0
  149. data/lib/e11y/metrics.rb +56 -10
  150. data/lib/e11y/middleware/adapter_resolver.rb +40 -0
  151. data/lib/e11y/middleware/audit_signing.rb +43 -6
  152. data/lib/e11y/middleware/baggage_protection.rb +75 -0
  153. data/lib/e11y/middleware/dev_log_source.rb +24 -0
  154. data/lib/e11y/middleware/event_slo.rb +23 -9
  155. data/lib/e11y/middleware/otel_span.rb +23 -0
  156. data/lib/e11y/middleware/pii_filter.rb +104 -75
  157. data/lib/e11y/middleware/rate_limiting.rb +54 -27
  158. data/lib/e11y/middleware/request.rb +70 -23
  159. data/lib/e11y/middleware/routing.rb +78 -21
  160. data/lib/e11y/middleware/sampling.rb +66 -17
  161. data/lib/e11y/middleware/self_monitoring_emit.rb +39 -0
  162. data/lib/e11y/middleware/trace_context.rb +45 -10
  163. data/lib/e11y/middleware/track_latency.rb +34 -0
  164. data/lib/e11y/middleware/validation.rb +7 -16
  165. data/lib/e11y/middleware/versioning.rb +26 -22
  166. data/lib/e11y/opentelemetry/semantic_conventions.rb +109 -0
  167. data/lib/e11y/opentelemetry/span_creator.rb +142 -0
  168. data/lib/e11y/pii/patterns.rb +12 -1
  169. data/lib/e11y/pipeline/builder.rb +1 -1
  170. data/lib/e11y/presets/audit_event.rb +13 -2
  171. data/lib/e11y/railtie.rb +52 -15
  172. data/lib/e11y/registry.rb +306 -0
  173. data/lib/e11y/reliability/circuit_breaker.rb +19 -21
  174. data/lib/e11y/reliability/dlq/base.rb +71 -0
  175. data/lib/e11y/reliability/dlq/file_adapter.rb +301 -0
  176. data/lib/e11y/reliability/dlq/file_storage.rb +63 -34
  177. data/lib/e11y/reliability/dlq/filter.rb +37 -54
  178. data/lib/e11y/reliability/retry_handler.rb +26 -29
  179. data/lib/e11y/reliability/retry_rate_limiter.rb +3 -11
  180. data/lib/e11y/sampling/error_spike_detector.rb +0 -2
  181. data/lib/e11y/sampling/load_monitor.rb +5 -9
  182. data/lib/e11y/sampling/stratified_tracker.rb +18 -0
  183. data/lib/e11y/self_monitoring/buffer_monitor.rb +2 -0
  184. data/lib/e11y/self_monitoring/performance_monitor.rb +19 -61
  185. data/lib/e11y/self_monitoring/reliability_monitor.rb +4 -74
  186. data/lib/e11y/slo/config_loader.rb +40 -0
  187. data/lib/e11y/slo/config_validator.rb +58 -0
  188. data/lib/e11y/slo/dashboard_generator.rb +122 -0
  189. data/lib/e11y/slo/event_driven.rb +8 -0
  190. data/lib/e11y/slo/tracker.rb +31 -4
  191. data/lib/e11y/testing/have_tracked_event_matcher.rb +190 -0
  192. data/lib/e11y/testing/rspec_matchers.rb +21 -0
  193. data/lib/e11y/testing/snapshot_matcher.rb +86 -0
  194. data/lib/e11y/trace_context/sampler.rb +35 -0
  195. data/lib/e11y/tracing/faraday_middleware.rb +31 -0
  196. data/lib/e11y/tracing/net_http_patch.rb +33 -0
  197. data/lib/e11y/tracing/propagator.rb +116 -0
  198. data/lib/e11y/tracing.rb +47 -0
  199. data/lib/e11y/version.rb +1 -1
  200. data/lib/e11y/versioning/version_extractor.rb +32 -0
  201. data/lib/e11y.rb +141 -265
  202. data/lib/generators/e11y/event/event_generator.rb +22 -0
  203. data/lib/generators/e11y/event/templates/event.rb.tt +16 -0
  204. data/lib/generators/e11y/grafana_dashboard/grafana_dashboard_generator.rb +30 -0
  205. data/lib/generators/e11y/grafana_dashboard/templates/e11y_dashboard.json +81 -0
  206. data/lib/generators/e11y/install/install_generator.rb +34 -0
  207. data/lib/generators/e11y/install/templates/e11y.rb +239 -0
  208. data/lib/generators/e11y/prometheus_alerts/prometheus_alerts_generator.rb +29 -0
  209. data/lib/generators/e11y/prometheus_alerts/templates/e11y_alerts.yml +28 -0
  210. data/lib/tasks/e11y_docs.rake +30 -0
  211. data/lib/tasks/e11y_events.rake +71 -0
  212. data/lib/tasks/e11y_lint.rake +91 -0
  213. data/lib/tasks/e11y_slo.rake +29 -0
  214. metadata +129 -39
  215. data/docs/ADR-010-developer-experience.md +0 -2166
  216. data/docs/API-REFERENCE-L28.md +0 -914
  217. data/docs/COMPREHENSIVE-CONFIGURATION.md +0 -2366
  218. data/docs/CONTRIBUTING.md +0 -312
  219. data/docs/IMPLEMENTATION_NOTES.md +0 -2804
  220. data/docs/IMPLEMENTATION_PLAN.md +0 -1971
  221. data/docs/IMPLEMENTATION_PLAN_ARCHITECTURE.md +0 -586
  222. data/docs/PLAN.md +0 -148
  223. data/docs/README.md +0 -296
  224. data/docs/design/00-memory-optimization.md +0 -593
  225. data/docs/guides/MIGRATION-L27-L28.md +0 -692
  226. data/docs/guides/PERFORMANCE-BENCHMARKS.md +0 -434
  227. data/docs/guides/README.md +0 -44
  228. data/docs/use_cases/UC-003-pattern-based-metrics.md +0 -1627
  229. data/lib/e11y/adapters/registry.rb +0 -141
  230. /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.
@@ -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. |
@@ -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
+ > ```
@@ -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
+ ```