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
@@ -1,867 +1,293 @@
1
- # UC-017: Local Development
1
+ # UC-017: Local Development with e11y-devtools
2
2
 
3
- **Status:** MVP Feature
4
- **Complexity:** Beginner
5
- **Setup Time:** 5-10 minutes
6
- **Target Users:** All Developers
3
+ **Status:** Implemented
4
+ **Complexity:** Beginner
5
+ **Setup Time:** 2 minutes
6
+ **Target Users:** All Rails Developers
7
+ **Related ADR:** ADR-010
7
8
 
8
9
  ---
9
10
 
10
- ## 📋 Overview
11
+ ## Overview
11
12
 
12
- ### Problem Statement
13
+ During local development, e11y automatically registers a **DevLog adapter** that writes all events to a local log file (default: `log/e11y_dev.jsonl`). No configuration is required — the Railtie activates the adapter in `development` and `test` environments on startup.
13
14
 
14
- **The local development pain:**
15
- ```ruby
16
- # ❌ BEFORE: Poor development experience
17
- # - Events go to production backends (Loki, Sentry)
18
- # - Can't see events in console (hidden in logs)
19
- # - No colored output (hard to read)
20
- # - No pretty-printing (JSON blobs)
21
- # - Debug events flood console
22
- # - Can't easily filter what you see
23
-
24
- # Terminal output:
25
- # {"event":"order.created","order_id":"123","timestamp":"2026-01-12T10:00:00Z"}
26
- # {"event":"payment.processing","order_id":"123","timestamp":"2026-01-12T10:00:01Z"}
27
- # {"event":"debug.sql","query":"SELECT...","timestamp":"2026-01-12T10:00:02Z"}
28
- # → Hard to read! 😞
29
- ```
30
-
31
- ### E11y Solution
15
+ Three complementary interfaces let you inspect those events:
32
16
 
33
- **Developer-friendly local setup:**
34
- ```ruby
35
- # AFTER: Beautiful, readable output
36
- E11y.configure do |config|
37
- if Rails.env.development?
38
- # Beautiful colored console output
39
- config.adapters = [
40
- E11y::Adapters::ConsoleAdapter.new(
41
- colored: true,
42
- pretty: true,
43
- show_payload: true,
44
- show_context: true
45
- )
46
- ]
47
-
48
- # Show all severities (including debug)
49
- config.severity = :debug
50
-
51
- # No rate limiting in dev
52
- config.rate_limiting.enabled = false
53
- end
54
- end
17
+ | Interface | How to access | Best for |
18
+ |-----------|--------------|----------|
19
+ | TUI (terminal) | `bundle exec e11y` | Browsing interactions, drilling into traces |
20
+ | Browser Overlay | Included with `e11y-devtools` gem | Checking events for the page you just loaded |
21
+ | MCP Server | `bundle exec e11y mcp` | AI-assisted debugging in Cursor / Claude Code |
55
22
 
56
- # Terminal output (beautiful! 🎨):
57
- # ╭─────────────────────────────────────────────────────────╮
58
- # │ 🎉 order.created [SUCCESS] 10:00:00 │
59
- # ├─────────────────────────────────────────────────────────┤
60
- # │ order_id: 123 │
61
- # │ user_id: 456 │
62
- # │ amount: $99.99 │
63
- # │ trace_id: abc-123-def │
64
- # ╰─────────────────────────────────────────────────────────╯
65
- ```
23
+ **Debug buffer note:** debug-severity events are held in memory during a request and flushed to the DevLog only when the request fails. A successful request discards the debug buffer, keeping the log free of noise. Error events always write immediately.
66
24
 
67
25
  ---
68
26
 
69
- ## 🎯 Features
70
-
71
- > **Implementation:** See [ADR-010: Developer Experience](../ADR-010-developer-experience.md) for complete architecture, including [Section 3: Console Output](../ADR-010-developer-experience.md#3-console-output), [Section 4: Web UI](../ADR-010-developer-experience.md#4-web-ui), [Section 5: Event Registry](../ADR-010-developer-experience.md#5-event-registry), and [Section 6: Debug Helpers](../ADR-010-developer-experience.md#6-debug-helpers).
27
+ ## Setup
72
28
 
73
- ### 1. Console Adapter (Pretty Output)
29
+ Add the devtools gem to your `Gemfile`:
74
30
 
75
- **Beautiful colored terminal output:**
76
31
  ```ruby
77
- # config/environments/development.rb
78
- Rails.application.configure do
79
- config.after_initialize do
80
- E11y.configure do |config|
81
- config.adapters = [
82
- E11y::Adapters::ConsoleAdapter.new(
83
- # Colors
84
- colored: true,
85
- color_scheme: :solarized, # :default, :solarized, :monokai
86
-
87
- # Formatting
88
- pretty: true,
89
- compact: false,
90
-
91
- # What to show
92
- show_payload: true,
93
- show_context: true,
94
- show_metadata: false, # timestamps, etc.
95
- show_trace_id: true,
96
-
97
- # Filtering
98
- severity_filter: :debug, # Show all
99
- event_filter: nil, # Show all events
100
-
101
- # Grouping
102
- group_by_trace_id: true, # Group events with same trace_id
103
-
104
- # Performance
105
- max_payload_length: 1000, # Truncate long payloads
106
- max_array_items: 10 # Limit array display
107
- )
108
- ]
109
- end
110
- end
32
+ # Gemfile
33
+ group :development, :test do
34
+ gem "e11y-devtools"
111
35
  end
112
-
113
- # Output examples:
114
- # ✅ SUCCESS event (green)
115
- # 🎉 order.created [SUCCESS] 10:00:00
116
- # order_id: 123
117
- # amount: $99.99
118
- # ⚡ Duration: 45ms
119
-
120
- # ⚠️ WARN event (yellow)
121
- # ⚠️ payment.retry [WARN] 10:00:05
122
- # order_id: 123
123
- # attempt: 2
124
- # reason: "Card declined"
125
-
126
- # ❌ ERROR event (red)
127
- # ❌ payment.failed [ERROR] 10:00:10
128
- # order_id: 123
129
- # error: "Insufficient funds"
130
- # trace_id: abc-123-def
131
36
  ```
132
37
 
133
- ---
38
+ Run `bundle install`. That is all — no `config/environments/development.rb` changes needed.
134
39
 
135
- ### 2. Event Inspector (Interactive)
40
+ The Railtie auto-registers the DevLog adapter and respects three ENV vars:
136
41
 
137
- **Interactive console for exploring events:**
138
- ```ruby
139
- # rails console
140
- > E11y::Inspector.start
141
- E11y Inspector started. Type 'help' for commands.
142
-
143
- # Watch events in real-time
144
- e11y> watch
145
- Watching events... (Ctrl+C to stop)
146
- [10:00:00] order.created { order_id: 123 }
147
- [10:00:01] payment.processing { order_id: 123 }
148
- [10:00:02] payment.succeeded { transaction_id: 'tx_123' }
149
-
150
- # Filter by pattern
151
- e11y> watch pattern: 'order.*'
152
- Watching events matching 'order.*'...
153
- [10:00:00] order.created { order_id: 123 }
154
- [10:00:05] order.shipped { order_id: 123, tracking: 'TRACK123' }
155
-
156
- # Filter by severity
157
- e11y> watch severity: :error
158
- Watching ERROR events...
159
- [10:00:10] payment.failed { error: "Card declined" }
160
-
161
- # Show last N events
162
- e11y> last 10
163
- Showing last 10 events:
164
- 1. [10:00:00] order.created
165
- 2. [10:00:01] payment.processing
166
- 3. [10:00:02] payment.succeeded
167
- ...
168
-
169
- # Search events
170
- e11y> search order_id: '123'
171
- Found 5 events:
172
- 1. [10:00:00] order.created
173
- 2. [10:00:01] payment.processing
174
- 3. [10:00:02] payment.succeeded
175
- 4. [10:00:05] order.shipped
176
- 5. [10:00:10] order.delivered
177
-
178
- # Show event details
179
- e11y> show 1
180
- Event: order.created
181
- Severity: SUCCESS
182
- Timestamp: 2026-01-12 10:00:00
183
- Trace ID: abc-123-def
184
- Payload:
185
- order_id: 123
186
- user_id: 456
187
- amount: 99.99
188
- currency: USD
189
- Context:
190
- request_id: req-789
191
- user_agent: Mozilla/5.0...
192
- Duration: 45ms
42
+ ```bash
43
+ bundle exec rails server
44
+ # DevLog active: log/e11y_dev.jsonl (max 10 000 events, 50 MB)
193
45
  ```
194
46
 
195
47
  ---
196
48
 
197
- ### 3. Debug Helper
49
+ ## TUI Interactive Log Viewer
198
50
 
199
- **Quick debugging methods:**
200
- ```ruby
201
- # app/controllers/orders_controller.rb
202
- class OrdersController < ApplicationController
203
- def create
204
- # Quick debug (only in development!)
205
- E11y.debug("Creating order", order_params)
206
- # → Pretty-printed to console immediately
207
-
208
- order = Order.create!(order_params)
209
-
210
- # Breakpoint with context
211
- E11y.breakpoint(
212
- "Order created",
213
- order: order.attributes,
214
- user: current_user.attributes
215
- )
216
- # → Pauses execution, shows data, waits for Enter
217
-
218
- # Measure block
219
- result = E11y.measure("Payment processing") do
220
- process_payment(order)
221
- end
222
- # → Logs duration automatically
223
-
224
- render json: order
225
- end
226
- end
51
+ Launch the terminal UI from your project root:
227
52
 
228
- # Console output:
229
- # 🔍 [DEBUG] Creating order
230
- # user_id: 456
231
- # items: [...]
232
- # total: 99.99
233
- #
234
- # ⏸️ [BREAKPOINT] Order created
235
- # order: { id: 123, status: "pending", ... }
236
- # user: { id: 456, email: "user@example.com", ... }
237
- # Press Enter to continue...
238
- #
239
- # ⏱️ [MEASURE] Payment processing → 1.2s
53
+ ```bash
54
+ bundle exec e11y
240
55
  ```
241
56
 
242
- ---
57
+ ### Views
243
58
 
244
- ### 4. Event Recorder (Playback)
59
+ The TUI has three nested views. Navigation is always the same two keys: Enter to drill in, Esc or `b` to go back.
245
60
 
246
- **Record and replay events for testing:**
247
- ```ruby
248
- # Record events during a request
249
- # rails console
250
- > recorder = E11y::Recorder.new
251
- > recorder.start
252
- Recording events...
253
-
254
- # Make request
255
- > app.post '/orders', params: { order: {...} }
256
-
257
- > recorder.stop
258
- Recorded 15 events
259
- Saved to tmp/e11y_recordings/2026-01-12_10-00-00.json
260
-
261
- # Replay events
262
- > recorder.replay('tmp/e11y_recordings/2026-01-12_10-00-00.json')
263
- Replaying 15 events...
264
- [1/15] order.creation.started
265
- [2/15] inventory.checked
266
- [3/15] payment.processing
267
- ...
268
- [15/15] order.created
269
-
270
- # Compare recordings (regression testing)
271
- > diff = E11y::Recorder.diff(
272
- 'recordings/baseline.json',
273
- 'recordings/current.json'
274
- )
275
- > puts diff
276
- + payment.retry (NEW in current)
277
- - payment.succeeded (MISSING in current)
278
- ~ payment.processing.duration_ms: 120ms → 1500ms (12.5x slower!)
279
61
  ```
280
-
281
- ---
282
-
283
- ### 5. Visual Timeline (Web UI)
284
-
285
- **Mini web UI for development:**
286
- ```ruby
287
- # config/routes.rb (development only)
288
- Rails.application.routes.draw do
289
- if Rails.env.development?
290
- mount E11y::Web => '/e11y'
291
- end
292
- end
293
-
294
- # Visit: http://localhost:3000/e11y
295
- # Features:
296
- # - Real-time event stream
297
- # - Timeline view (Gantt chart)
298
- # - Filtering by severity, pattern
299
- # - Trace visualization
300
- # - Event details modal
301
- # - Export to JSON/CSV
302
- # - Search & filter
303
-
304
- # Example UI:
305
- # ╔══════════════════════════════════════════════════════════╗
306
- # ║ E11y Event Dashboard 🔄 Auto-refresh ║
307
- # ╠══════════════════════════════════════════════════════════╣
308
- # ║ Filters: [All Severities ▾] [All Events ▾] [Search...] ║
309
- # ╠══════════════════════════════════════════════════════════╣
310
- # ║ Timeline (Last 5 minutes) ║
311
- # ║ ┌────────────────────────────────────────────────────┐ ║
312
- # ║ │ 10:00:00 ████ order.created │ ║
313
- # ║ │ 10:00:01 ███████ payment.processing │ ║
314
- # ║ │ 10:00:02 ██ payment.succeeded │ ║
315
- # ║ │ 10:00:05 ████ shipment.created │ ║
316
- # ║ └────────────────────────────────────────────────────┘ ║
317
- # ╠══════════════════════════════════════════════════════════╣
318
- # ║ Recent Events ║
319
- # ║ ✅ order.created 10:00:00 trace: abc-123 ║
320
- # ║ ⏳ payment.processing 10:00:01 trace: abc-123 ║
321
- # ║ ✅ payment.succeeded 10:00:02 trace: abc-123 ║
322
- # ╚══════════════════════════════════════════════════════════╝
62
+ :interactions → :events → :detail
323
63
  ```
324
64
 
325
- ---
326
-
327
- ### 6. Environment-Specific Configuration Recommendations (C14)
65
+ ### Interactions view (default)
328
66
 
329
- > **Implementation:** See [ADR-010 Section 2: Development vs Production](../ADR-010-developer-experience.md#2-development-vs-production-configuration) for detailed architecture rationale.
67
+ Parallel traces that start within 500 ms are grouped into one row. A red dot () means the interaction contains at least one error; a gray dot (○) means it is clean.
330
68
 
331
- **Critical differences between development and production configurations:**
69
+ ```
70
+ e11y [w] web [j] jobs [a] all r=reload q=quit
71
+ ────────────────────────────────────────────────────────────────────
72
+ # time source dur events status
73
+ ────────────────────────────────────────────────────────────────────
74
+ 1 10:04:12 web 312ms 14 ○ GET /orders
75
+ 2 10:03:58 web 89ms 6 ○ GET /orders/123
76
+ 3 10:03:41 web 541ms 22 ● POST /checkout
77
+ 4 10:02:15 jobs 2.1s 8 ○ OrderFulfillmentJob
78
+ 5 10:01:07 web 73ms 3 ○ GET /products
79
+ ────────────────────────────────────────────────────────────────────
80
+ ↓/↑ navigate Enter drill-in
81
+ ```
332
82
 
333
- **Development: Immediate Feedback (Zero Delay)**
83
+ ### Events view (after Enter on an interaction)
334
84
 
335
- ```ruby
336
- # config/environments/development.rb
337
- E11y.configure do |config|
338
- # === BUFFERING: DISABLED (immediate writes) ===
339
- # ✅ Events appear INSTANTLY in console
340
- # ✅ No need to wait for flush
341
- # ⚠️ Trade-off: Slightly slower per-request performance (acceptable in dev)
342
- config.buffering.enabled = false
343
-
344
- # OR: Very short interval (near-immediate)
345
- # config.buffering do
346
- # enabled true
347
- # flush_interval 0.1.seconds # Flush every 100ms
348
- # end
349
-
350
- # === SAMPLING: DISABLED (keep all events) ===
351
- # ✅ See EVERY event for complete debugging
352
- # ✅ No data loss during development
353
- # ⚠️ Trade-off: More console noise (filter with ignore_events)
354
- config.sampling.enabled = false
355
-
356
- # === RATE LIMITING: DISABLED (no throttling) ===
357
- # ✅ Rapid testing won't hit limits
358
- config.rate_limiting.enabled = false
359
-
360
- # === PII FILTERING: DISABLED (optional) ===
361
- # ✅ See real data for easier debugging
362
- # ⚠️ Only disable if you're NOT using production data in dev!
363
- config.pii_filtering.enabled = false
364
-
365
- # === FLUSH HELPER: Available for manual testing ===
366
- # Sometimes you want to force-flush buffered events:
367
- # E11y.flush # ← Forces immediate flush
368
- end
85
+ ```
86
+ e11y > POST /checkout (trace: f3a9b2c1)
87
+ ────────────────────────────────────────────────────────────────────
88
+ # time severity event name
89
+ ────────────────────────────────────────────────────────────────────
90
+ 1 10:03:41 info order.validation.started
91
+ 2 10:03:41 info inventory.checked
92
+ 3 10:03:41 debug db.query (buffered shown because request failed)
93
+ 4 10:03:42 warn payment.retry
94
+ 5 10:03:42 error payment.failed
95
+ ────────────────────────────────────────────────────────────────────
96
+ ↓/↑ navigate Enter detail Esc/b back
369
97
  ```
370
98
 
371
- **Production: Performance & Cost Optimization**
99
+ ### Detail view (after Enter on an event)
372
100
 
373
- ```ruby
374
- # config/environments/production.rb
375
- E11y.configure do |config|
376
- # === BUFFERING: ENABLED (batch writes) ===
377
- # ✅ 10× performance improvement (batching)
378
- # ✅ 50% cost reduction (fewer network calls)
379
- # ⚠️ Trade-off: Events delayed by up to 10s
380
- config.buffering do
381
- enabled true
382
- flush_interval 10.seconds
383
- max_buffer_size 1000
384
- end
385
-
386
- # === SAMPLING: ENABLED (cost savings) ===
387
- # ✅ 50-80% cost reduction
388
- # ✅ Errors always kept (100% sampling)
389
- # ⚠️ Trade-off: Some success events dropped
390
- config.sampling do
391
- enabled true
392
- strategy :adaptive
393
- base_rate 0.1 # Keep 10% of success events
394
- error_rate 1.0 # Keep 100% of errors
395
- end
396
-
397
- # === RATE LIMITING: ENABLED (DDoS protection) ===
398
- # ✅ Prevents cost explosions
399
- # ✅ Protects backend from overload
400
- config.rate_limiting do
401
- enabled true
402
- limit 1000
403
- window 1.minute
404
- end
405
-
406
- # === PII FILTERING: ENABLED (GDPR compliance) ===
407
- # ✅ GDPR/CCPA compliant
408
- # ✅ Protects sensitive data
409
- config.pii_filtering.enabled true
410
- end
101
+ ```
102
+ e11y > POST /checkout > payment.failed
103
+ ────────────────────────────────────────────────────────────────────
104
+ event_name: payment.failed
105
+ severity: error
106
+ timestamp: 2026-03-18T10:03:42.317Z
107
+ trace_id: f3a9b2c1-...
108
+ duration_ms: 541
109
+
110
+ payload:
111
+ order_id: "ord_8812"
112
+ amount: 99.99
113
+ currency: "USD"
114
+ reason: "Card declined"
115
+ attempt: 2
116
+ ────────────────────────────────────────────────────────────────────
117
+ Esc/b back c=copy JSON
411
118
  ```
412
119
 
413
- **Comparison Table:**
120
+ ### Keyboard reference
414
121
 
415
- | Feature | Development | Production | Why Different? |
416
- |---------|-------------|------------|----------------|
417
- | **Buffering** | Disabled (immediate) | Enabled (10s batches) | Dev needs instant feedback, prod needs performance |
418
- | **Sampling** | Disabled (100%) | Enabled (10-50%) | Dev needs complete data, prod needs cost savings |
419
- | **Rate Limiting** | ❌ Disabled | Enabled (1000/min) | Dev needs rapid testing, prod needs DDoS protection |
420
- | **PII Filtering** | ⚠️ Optional (easier debugging) | ✅ Enabled (GDPR) | Dev may use fake data, prod has real user data |
421
- | **Flush Helper** | ✅ `E11y.flush` available | ⚠️ Available but rarely needed | Dev uses for manual testing |
122
+ | Key | Action |
123
+ |-----|--------|
124
+ | `↓` / `↑` | Navigate list |
125
+ | `Enter` | Drill into interaction or event |
126
+ | `Esc` / `b` | Go back one level |
127
+ | `w` | Filter: web requests only (default) |
128
+ | `j` | Filter: background jobs only |
129
+ | `a` | Filter: all sources |
130
+ | `r` | Reload from log file |
131
+ | `c` | Copy event JSON to clipboard (detail view) |
132
+ | `q` | Quit |
422
133
 
423
- **Manual Flush Helper (Development Testing):**
134
+ File watching polls `mtime` every 250 ms — new events appear without pressing `r`.
424
135
 
425
- ```ruby
426
- # Scenario: Testing event delivery in specs
427
- RSpec.describe 'Order creation' do
428
- it 'tracks order.created event' do
429
- # Event is buffered (not sent yet)
430
- post '/orders', params: { order: {...} }
431
-
432
- # Force immediate flush (for testing)
433
- E11y.flush
434
-
435
- # Now event is available in test adapter
436
- expect(E11y.test_adapter.events).to include(
437
- hash_including(event_name: 'order.created')
438
- )
439
- end
440
- end
441
-
442
- # Rails console manual testing:
443
- > Events::OrderCreated.track(order_id: 123)
444
- # → Event buffered, not visible yet
136
+ ---
445
137
 
446
- > E11y.flush
447
- # → Forces immediate flush, event now visible in console
138
+ ## Browser Overlay
448
139
 
449
- > E11y.buffer.size
450
- # => 0 (buffer is empty after flush)
451
- ```
140
+ When `e11y-devtools` is present in the Gemfile, a lightweight JavaScript snippet is injected into every development page response. It requires no route configuration.
452
141
 
453
- **Trade-offs & Gotchas:**
142
+ ### Badge
454
143
 
455
- **⚠️ Warning: Development Production Behavior**
144
+ A small badge appears in the bottom-right corner of every page:
456
145
 
457
- ```ruby
458
- # ❌ GOTCHA: Event appears instantly in dev, delayed in prod
459
- # Development (buffering disabled):
460
- Events::OrderCreated.track(order_id: 123)
461
- # → Appears in console IMMEDIATELY ✅
462
-
463
- # Production (buffering enabled, 10s flush):
464
- Events::OrderCreated.track(order_id: 123)
465
- # → Buffered, appears after 10 seconds ⏱️
466
- # → Or when buffer full (1000 events)
467
- # → Or when E11y.flush called manually
468
-
469
- # Solution: If you need instant delivery in prod (e.g., critical alerts):
470
- Events::CriticalAlert.track(
471
- alert_type: 'payment_failure',
472
- severity: :fatal
473
- )
474
- E11y.flush # ← Force immediate delivery (bypasses buffer)
146
+ ```
147
+ ╭─────────────╮
148
+ │ e11y 14 1│
149
+ ╰─────────────╯
475
150
  ```
476
151
 
477
- **⚠️ Warning: Sampling Differences**
152
+ - The first number is the total event count for the current page's trace.
153
+ - The second number (after ●) is the error count.
154
+ - The badge border turns red when errors are present.
478
155
 
479
- ```ruby
480
- # ❌ GOTCHA: All events visible in dev, some dropped in prod
481
- # Development (sampling disabled):
482
- 100.times { Events::UserLogin.track(user_id: rand(1000)) }
483
- # → See ALL 100 events in console ✅
484
-
485
- # Production (sampling enabled, 10% rate):
486
- 100.times { Events::UserLogin.track(user_id: rand(1000)) }
487
- # → Only ~10 events reach Loki (90 dropped) ❌
488
- # → Errors ALWAYS kept (100% sampling) ✅
489
-
490
- # Solution: Test sampling behavior in staging:
491
- # config/environments/staging.rb
492
- config.sampling do
493
- enabled true # ← Test production-like sampling
494
- base_rate 0.1
495
- end
496
- ```
156
+ ### Slide-in panel
497
157
 
498
- **Staging Environment (Recommended Middle Ground):**
158
+ Clicking the badge opens a panel on the right side of the screen:
499
159
 
500
- ```ruby
501
- # config/environments/staging.rb
502
- E11y.configure do |config|
503
- # Balanced config: production-like but easier to debug
504
-
505
- # Buffering: Shorter interval (faster feedback than prod)
506
- config.buffering do
507
- enabled true
508
- flush_interval 1.second # vs 10s in prod
509
- end
510
-
511
- # Sampling: Higher rate (more data than prod)
512
- config.sampling do
513
- enabled true
514
- base_rate 0.5 # vs 0.1 in prod (keep 50% of events)
515
- error_rate 1.0 # Always keep errors
516
- end
517
-
518
- # Rate limiting: Higher limits (easier testing)
519
- config.rate_limiting do
520
- enabled true
521
- limit 10_000 # vs 1000 in prod
522
- end
523
-
524
- # PII: Enabled (test GDPR compliance)
525
- config.pii_filtering.enabled true
526
- end
160
+ ```
161
+ ╔══════════════════════════════════════════╗
162
+ ║ e11y trace: f3a9b2c1 ║
163
+ ╠══════════════════════════════════════════╣
164
+ 10:03:41 info order.validation.start ║
165
+ 10:03:41 info inventory.checked ║
166
+ 10:03:42 warn payment.retry ║
167
+ ║ 10:03:42 error payment.failed ║
168
+ ╠══════════════════════════════════════════╣
169
+ [clear log] [copy trace_id] ║
170
+ ╚══════════════════════════════════════════╝
527
171
  ```
528
172
 
529
- **Key Takeaways:**
173
+ The panel shows only events that share the current page's trace ID. It auto-polls every 2 seconds.
530
174
 
531
- 1. **Development:** Disable buffering & sampling for instant, complete feedback
532
- 2. **Production:** Enable buffering & sampling for performance & cost savings
533
- 3. **Staging:** Middle ground - production-like but easier to debug
534
- 4. **Use `E11y.flush`:** For manual testing when buffering is enabled
535
- 5. **Test in staging:** Catch production behavior differences before deployment
175
+ The overlay endpoint returns 404 outside the `development` environment, so it cannot leak into staging or production.
536
176
 
537
177
  ---
538
178
 
539
- ## 💻 Implementation Examples
540
-
541
- ### Example 1: Full Development Config
179
+ ## MCP Server — AI-Assisted Debugging
542
180
 
543
- ```ruby
544
- # config/environments/development.rb
545
- Rails.application.configure do
546
- config.after_initialize do
547
- E11y.configure do |config|
548
- # === CONSOLE OUTPUT ===
549
- config.adapters = [
550
- E11y::Adapters::ConsoleAdapter.new(
551
- colored: true,
552
- pretty: true,
553
- show_payload: true,
554
- show_context: true,
555
- show_trace_id: true,
556
- group_by_trace_id: true
557
- )
558
- ]
559
-
560
- # === SEVERITY ===
561
- # Show everything in development
562
- config.severity = :debug
563
-
564
- # === FEATURES ===
565
- # Disable production features
566
- config.rate_limiting.enabled = false
567
- config.sampling.enabled = false
568
- config.pii_filtering.enabled = false # Easier debugging
569
-
570
- # === DEBUGGING ===
571
- # Enable debug helpers
572
- config.debug_mode = true
573
-
574
- # === BUFFERING ===
575
- # Immediate flush (no buffering)
576
- config.buffer.enabled = false # Or flush_interval: 0.1.seconds
577
-
578
- # === WEB UI ===
579
- config.web_ui do
580
- enabled true
581
- port 3001 # Or use Rails server
582
- auto_refresh true
583
- refresh_interval 2.seconds
584
- end
585
-
586
- # === RECORDING ===
587
- config.recording do
588
- enabled true
589
- save_path Rails.root.join('tmp', 'e11y_recordings')
590
- auto_save_on_error true
591
- end
592
-
593
- # === PERFORMANCE ===
594
- # Verbose self-monitoring
595
- config.self_monitoring do
596
- enabled true
597
- log_internal_events true
598
- end
599
- end
600
- end
601
- end
602
- ```
603
-
604
- ---
181
+ The MCP server exposes the DevLog over the Model Context Protocol so AI assistants can query your local events directly.
605
182
 
606
- ### Example 2: Debug Helpers in Code
183
+ ### Start the server
607
184
 
608
- ```ruby
609
- # app/services/order_processing_service.rb
610
- class OrderProcessingService
611
- def call(order_id)
612
- # Debug checkpoint
613
- E11y.debug("Starting order processing", order_id: order_id)
614
-
615
- order = Order.find(order_id)
616
-
617
- # Show complex data structure
618
- E11y.inspect(order, depth: 2)
619
- # → Pretty-printed with colors, max depth 2
620
-
621
- # Measure performance
622
- inventory_result = E11y.measure("Inventory check") do
623
- check_inventory(order)
624
- end
625
-
626
- # Conditional breakpoint
627
- E11y.breakpoint_if(
628
- -> { inventory_result.low_stock? },
629
- "Low stock detected!",
630
- order: order.attributes,
631
- inventory: inventory_result
632
- )
633
-
634
- # Trace execution
635
- E11y.trace("Processing payment") do
636
- process_payment(order)
637
- end
638
- # → Logs entry/exit automatically
639
-
640
- # Count invocations
641
- E11y.count("order_processing")
642
- # → Logs: "order_processing called 5 times"
643
-
644
- # Diff objects
645
- before = order.attributes
646
- order.update!(status: 'processed')
647
- E11y.diff(before, order.attributes)
648
- # → Shows: { status: "pending" → "processed" }
649
-
650
- order
651
- end
652
- end
185
+ ```bash
186
+ # Default port 3099
187
+ bundle exec e11y mcp
653
188
 
654
- # Console output:
655
- # 🔍 [DEBUG] Starting order processing
656
- # order_id: 123
657
- #
658
- # 📦 [INSPECT] Order #123
659
- # id: 123
660
- # status: "pending"
661
- # items: [
662
- # { id: 1, product_id: 456, quantity: 2 },
663
- # { id: 2, product_id: 789, quantity: 1 }
664
- # ]
665
- # total: 99.99
666
- #
667
- # ⏱️ [MEASURE] Inventory check → 45ms
668
- #
669
- # ⏸️ [BREAKPOINT] Low stock detected!
670
- # order: { ... }
671
- # inventory: { low_stock: true, product_id: 456 }
672
- # Press Enter to continue...
673
- #
674
- # 🔀 [TRACE] Processing payment
675
- # → Entered at 10:00:01
676
- # → Exited at 10:00:02 (1.2s)
677
- #
678
- # 📊 [COUNT] order_processing called 5 times
679
- #
680
- # 🔄 [DIFF] Order #123
681
- # - status: "pending"
682
- # + status: "processed"
189
+ # Custom port
190
+ bundle exec e11y mcp --port 3099
683
191
  ```
684
192
 
685
- ---
193
+ ### Available tools
194
+
195
+ | Tool | Description |
196
+ |------|-------------|
197
+ | `recent_events` | Return the N most recent events (default 50) |
198
+ | `events_by_trace` | Return all events for a given `trace_id` |
199
+ | `search` | Full-text search across event names and payload fields |
200
+ | `stats` | Event counts by severity and source for a time window |
201
+ | `interactions` | List grouped interactions (same view as TUI :interactions) |
202
+ | `event_detail` | Return full JSON for a single event by ID |
203
+ | `errors` | Return all error/fatal events since a given timestamp |
204
+ | `clear` | Truncate the DevLog (useful before reproducing a bug) |
205
+
206
+ ### Cursor configuration
207
+
208
+ Create or update `.cursor/mcp.json` in your project root:
209
+
210
+ ```json
211
+ {
212
+ "mcpServers": {
213
+ "e11y": {
214
+ "command": "bundle",
215
+ "args": ["exec", "e11y", "mcp"]
216
+ }
217
+ }
218
+ }
219
+ ```
686
220
 
687
- ### Example 3: Event Filtering
221
+ ### Claude Code configuration
688
222
 
689
- ```ruby
690
- # config/environments/development.rb
691
- E11y.configure do |config|
692
- config.adapters = [
693
- E11y::Adapters::ConsoleAdapter.new(
694
- colored: true,
695
- pretty: true,
696
-
697
- # === FILTERING ===
698
- # Only show events matching patterns
699
- event_filter: ->(event) {
700
- # Show orders & payments, hide everything else
701
- event.event_name.match?(/^(order|payment)\./)
702
- },
703
-
704
- # Only show warn/error/success
705
- severity_filter: [:warn, :error, :fatal, :success],
706
-
707
- # Hide noisy events
708
- ignore_events: [
709
- 'health_check',
710
- 'heartbeat',
711
- 'metrics.collected'
712
- ],
713
-
714
- # Hide debug SQL queries
715
- ignore_patterns: [
716
- /^debug\./,
717
- /\.sql$/
718
- ]
719
- )
720
- ]
721
- end
223
+ Create or update `.claude/mcp.json` in your project root:
722
224
 
723
- # Result:
724
- # ✅ Shows: order.created, payment.succeeded
725
- # ❌ Hides: debug.sql, health_check, heartbeat
225
+ ```json
226
+ {
227
+ "mcpServers": {
228
+ "e11y": {
229
+ "command": "bundle",
230
+ "args": ["exec", "e11y", "mcp"]
231
+ }
232
+ }
233
+ }
726
234
  ```
727
235
 
728
- ---
729
-
730
- ## 🔧 Configuration
236
+ ### Example prompts
731
237
 
732
- ### Development Config Template
733
-
734
- ```ruby
735
- # config/environments/development.rb
736
- Rails.application.configure do
737
- config.after_initialize do
738
- E11y.configure do |config|
739
- # === OUTPUT ===
740
- config.adapters = [
741
- E11y::Adapters::ConsoleAdapter.new(
742
- colored: true,
743
- pretty: true,
744
- color_scheme: :solarized,
745
- show_payload: true,
746
- show_context: true,
747
- show_trace_id: true,
748
- group_by_trace_id: true,
749
- max_payload_length: 1000
750
- )
751
- ]
752
-
753
- # === LEVEL ===
754
- config.severity = :debug
755
-
756
- # === FEATURES ===
757
- config.rate_limiting.enabled = false
758
- config.sampling.enabled = false
759
- config.buffering.enabled = false
760
-
761
- # === DEBUG ===
762
- config.debug_mode = true
763
- config.debug_helpers.enabled = true
764
-
765
- # === WEB UI ===
766
- config.web_ui.enabled = true
767
- config.web_ui.auto_refresh = true
768
-
769
- # === RECORDING ===
770
- config.recording.enabled = true
771
- config.recording.auto_save_on_error = true
772
- end
773
- end
774
- end
775
- ```
238
+ - "What errors happened in the last request?"
239
+ - "Show me all events for trace f3a9b2c1"
240
+ - "Why is the checkout slow? Look at recent interactions."
241
+ - "Compare event counts from the last two POST /checkout traces."
776
242
 
777
243
  ---
778
244
 
779
- ## 💡 Best Practices
245
+ ## Configuration Reference
780
246
 
781
- ### DO
247
+ All settings are controlled via ENV vars. No code changes are needed for the defaults.
782
248
 
783
- **1. Use colored console output**
784
- ```ruby
785
- # GOOD: Easy to read
786
- config.adapters = [
787
- E11y::Adapters::ConsoleAdapter.new(
788
- colored: true,
789
- pretty: true
790
- )
791
- ]
792
- ```
249
+ | ENV var | Default | Description |
250
+ |---------|---------|-------------|
251
+ | `E11Y_MAX_EVENTS` | `10000` | Maximum number of events retained in the DevLog (oldest are dropped) |
252
+ | `E11Y_MAX_SIZE` | `52428800` (50 MB) | Maximum DevLog file size in bytes before rotation |
253
+ | `E11Y_KEEP_ROTATED` | `5` | Number of rotated log files to retain |
793
254
 
794
- **2. Filter noise in development**
795
- ```ruby
796
- # ✅ GOOD: Hide irrelevant events
797
- config.adapters = [
798
- E11y::Adapters::ConsoleAdapter.new(
799
- ignore_events: ['health_check', 'heartbeat']
800
- )
801
- ]
802
- ```
255
+ Example: raise the cap for a long debugging session:
803
256
 
804
- **3. Use debug helpers**
805
- ```ruby
806
- # ✅ GOOD: Quick debugging
807
- E11y.debug("User logged in", user_id: user.id)
808
- E11y.breakpoint("Check this", data: complex_data)
257
+ ```bash
258
+ E11Y_MAX_EVENTS=50000 bundle exec rails server
809
259
  ```
810
260
 
811
- ---
261
+ The DevLog file is written to `log/e11y_dev.jsonl` by default. Add it to `.gitignore`:
812
262
 
813
- ### ❌ DON'T
814
-
815
- **1. Don't use production adapters**
816
- ```ruby
817
- # ❌ BAD: Production adapters in development
818
- config.adapters = [
819
- E11y::Adapters::LokiAdapter.new(...) # Slow!
820
- ]
821
-
822
- # ✅ GOOD: Console adapter
823
- config.adapters = [
824
- E11y::Adapters::ConsoleAdapter.new(...)
825
- ]
826
263
  ```
827
-
828
- **2. Don't forget to disable features**
829
- ```ruby
830
- # ❌ BAD: Production features enabled
831
- config.rate_limiting.enabled = true # Annoying in dev!
832
- config.sampling.enabled = true # Lose events!
833
-
834
- # ✅ GOOD: Disable in development
835
- config.rate_limiting.enabled = false
836
- config.sampling.enabled = false
264
+ # .gitignore
265
+ log/e11y_dev*.log
837
266
  ```
838
267
 
839
268
  ---
840
269
 
841
- ## 📚 Related Use Cases
842
-
843
- - **[UC-016: Rails Logger Migration](./UC-016-rails-logger-migration.md)** - Migration guide
844
- - **[UC-018: Testing Events](./UC-018-testing-events.md)** - Testing helpers
845
-
846
- ---
847
-
848
- ## 🎯 Summary
849
-
850
- ### Development Experience
851
-
852
- | Feature | Before | After |
853
- |---------|--------|-------|
854
- | **Output** | JSON blobs | Colored, pretty |
855
- | **Filtering** | None | By severity, pattern |
856
- | **Debugging** | `puts` | Debug helpers |
857
- | **Inspection** | Manual | Interactive inspector |
858
- | **Recording** | None | Record & replay |
859
- | **Visualization** | None | Web UI |
860
-
861
- **Setup Time:** 5-10 minutes (one-time config)
270
+ ## Acceptance Criteria
271
+
272
+ - [x] Railtie auto-registers DevLog adapter in `development` and `test` — no manual configuration required
273
+ - [x] DevLog respects `E11Y_MAX_EVENTS`, `E11Y_MAX_SIZE`, and `E11Y_KEEP_ROTATED` ENV vars
274
+ - [x] TUI launches with `bundle exec e11y` and shows the `:interactions` view by default
275
+ - [x] Interactions group parallel traces within a 500 ms window into a single row
276
+ - [x] Red dot (●) on interactions that contain at least one error; gray dot (○) otherwise
277
+ - [x] Source filter toggles: web requests (`w`), background jobs (`j`), all (`a`)
278
+ - [x] TUI supports drill-down: `:interactions` → `:events` → `:detail`
279
+ - [x] Detail view provides `c` to copy event JSON to clipboard
280
+ - [x] TUI polls log `mtime` every 250 ms and refreshes automatically
281
+ - [x] Browser overlay badge appears in bottom-right corner with event count and error count
282
+ - [x] Badge border turns red when the current trace contains errors
283
+ - [x] Panel shows only events for the current page's trace ID
284
+ - [x] Panel auto-polls every 2 seconds
285
+ - [x] Browser overlay endpoint returns 404 outside `development`
286
+ - [x] MCP server starts with `bundle exec e11y mcp` (default port 3099)
287
+ - [x] MCP server exposes 8 tools: `recent_events`, `events_by_trace`, `search`, `stats`, `interactions`, `event_detail`, `errors`, `clear`
288
+ - [x] Cursor and Claude Code JSON configs work with `command: "bundle", args: ["exec", "e11y", "mcp"]`
289
+ - [x] Debug events are buffered per-request and flushed to DevLog only on request failure
862
290
 
863
291
  ---
864
292
 
865
- **Document Version:** 1.0
866
- **Last Updated:** January 12, 2026
867
- **Status:** ✅ Complete
293
+ **Related:** [ADR-010: Developer Experience](../architecture/ADR-010-developer-experience.md) | [UC-018: Testing Events](./UC-018-testing-events.md)