e11y 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +69 -0
- data/CHANGELOG.md +26 -0
- data/CODE_OF_CONDUCT.md +64 -0
- data/LICENSE.txt +21 -0
- data/README.md +179 -0
- data/Rakefile +37 -0
- data/benchmarks/run_all.rb +33 -0
- data/config/README.md +83 -0
- data/config/loki-local-config.yaml +35 -0
- data/config/prometheus.yml +15 -0
- data/docker-compose.yml +78 -0
- data/docs/00-ICP-AND-TIMELINE.md +483 -0
- data/docs/01-SCALE-REQUIREMENTS.md +858 -0
- data/docs/ADR-001-architecture.md +2617 -0
- data/docs/ADR-002-metrics-yabeda.md +1395 -0
- data/docs/ADR-003-slo-observability.md +3337 -0
- data/docs/ADR-004-adapter-architecture.md +2385 -0
- data/docs/ADR-005-tracing-context.md +1372 -0
- data/docs/ADR-006-security-compliance.md +4143 -0
- data/docs/ADR-007-opentelemetry-integration.md +1385 -0
- data/docs/ADR-008-rails-integration.md +1911 -0
- data/docs/ADR-009-cost-optimization.md +2993 -0
- data/docs/ADR-010-developer-experience.md +2166 -0
- data/docs/ADR-011-testing-strategy.md +1836 -0
- data/docs/ADR-012-event-evolution.md +958 -0
- data/docs/ADR-013-reliability-error-handling.md +2750 -0
- data/docs/ADR-014-event-driven-slo.md +1533 -0
- data/docs/ADR-015-middleware-order.md +1061 -0
- data/docs/ADR-016-self-monitoring-slo.md +1234 -0
- data/docs/API-REFERENCE-L28.md +914 -0
- data/docs/COMPREHENSIVE-CONFIGURATION.md +2366 -0
- data/docs/IMPLEMENTATION_NOTES.md +2804 -0
- data/docs/IMPLEMENTATION_PLAN.md +1971 -0
- data/docs/IMPLEMENTATION_PLAN_ARCHITECTURE.md +586 -0
- data/docs/PLAN.md +148 -0
- data/docs/QUICK-START.md +934 -0
- data/docs/README.md +296 -0
- data/docs/design/00-memory-optimization.md +593 -0
- data/docs/guides/MIGRATION-L27-L28.md +692 -0
- data/docs/guides/PERFORMANCE-BENCHMARKS.md +434 -0
- data/docs/guides/README.md +44 -0
- data/docs/prd/01-overview-vision.md +440 -0
- data/docs/use_cases/README.md +119 -0
- data/docs/use_cases/UC-001-request-scoped-debug-buffering.md +813 -0
- data/docs/use_cases/UC-002-business-event-tracking.md +1953 -0
- data/docs/use_cases/UC-003-pattern-based-metrics.md +1627 -0
- data/docs/use_cases/UC-004-zero-config-slo-tracking.md +728 -0
- data/docs/use_cases/UC-005-sentry-integration.md +759 -0
- data/docs/use_cases/UC-006-trace-context-management.md +905 -0
- data/docs/use_cases/UC-007-pii-filtering.md +2648 -0
- data/docs/use_cases/UC-008-opentelemetry-integration.md +1153 -0
- data/docs/use_cases/UC-009-multi-service-tracing.md +1043 -0
- data/docs/use_cases/UC-010-background-job-tracking.md +1018 -0
- data/docs/use_cases/UC-011-rate-limiting.md +1906 -0
- data/docs/use_cases/UC-012-audit-trail.md +2301 -0
- data/docs/use_cases/UC-013-high-cardinality-protection.md +2127 -0
- data/docs/use_cases/UC-014-adaptive-sampling.md +1940 -0
- data/docs/use_cases/UC-015-cost-optimization.md +735 -0
- data/docs/use_cases/UC-016-rails-logger-migration.md +785 -0
- data/docs/use_cases/UC-017-local-development.md +867 -0
- data/docs/use_cases/UC-018-testing-events.md +1081 -0
- data/docs/use_cases/UC-019-tiered-storage-migration.md +562 -0
- data/docs/use_cases/UC-020-event-versioning.md +708 -0
- data/docs/use_cases/UC-021-error-handling-retry-dlq.md +956 -0
- data/docs/use_cases/UC-022-event-registry.md +648 -0
- data/docs/use_cases/backlog.md +226 -0
- data/e11y.gemspec +76 -0
- data/lib/e11y/adapters/adaptive_batcher.rb +207 -0
- data/lib/e11y/adapters/audit_encrypted.rb +239 -0
- data/lib/e11y/adapters/base.rb +580 -0
- data/lib/e11y/adapters/file.rb +224 -0
- data/lib/e11y/adapters/in_memory.rb +216 -0
- data/lib/e11y/adapters/loki.rb +333 -0
- data/lib/e11y/adapters/otel_logs.rb +203 -0
- data/lib/e11y/adapters/registry.rb +141 -0
- data/lib/e11y/adapters/sentry.rb +230 -0
- data/lib/e11y/adapters/stdout.rb +108 -0
- data/lib/e11y/adapters/yabeda.rb +370 -0
- data/lib/e11y/buffers/adaptive_buffer.rb +339 -0
- data/lib/e11y/buffers/base_buffer.rb +40 -0
- data/lib/e11y/buffers/request_scoped_buffer.rb +246 -0
- data/lib/e11y/buffers/ring_buffer.rb +267 -0
- data/lib/e11y/buffers.rb +14 -0
- data/lib/e11y/console.rb +122 -0
- data/lib/e11y/current.rb +48 -0
- data/lib/e11y/event/base.rb +894 -0
- data/lib/e11y/event/value_sampling_config.rb +84 -0
- data/lib/e11y/events/base_audit_event.rb +43 -0
- data/lib/e11y/events/base_payment_event.rb +33 -0
- data/lib/e11y/events/rails/cache/delete.rb +21 -0
- data/lib/e11y/events/rails/cache/read.rb +23 -0
- data/lib/e11y/events/rails/cache/write.rb +22 -0
- data/lib/e11y/events/rails/database/query.rb +45 -0
- data/lib/e11y/events/rails/http/redirect.rb +21 -0
- data/lib/e11y/events/rails/http/request.rb +26 -0
- data/lib/e11y/events/rails/http/send_file.rb +21 -0
- data/lib/e11y/events/rails/http/start_processing.rb +26 -0
- data/lib/e11y/events/rails/job/completed.rb +22 -0
- data/lib/e11y/events/rails/job/enqueued.rb +22 -0
- data/lib/e11y/events/rails/job/failed.rb +22 -0
- data/lib/e11y/events/rails/job/scheduled.rb +23 -0
- data/lib/e11y/events/rails/job/started.rb +22 -0
- data/lib/e11y/events/rails/log.rb +56 -0
- data/lib/e11y/events/rails/view/render.rb +23 -0
- data/lib/e11y/events.rb +18 -0
- data/lib/e11y/instruments/active_job.rb +201 -0
- data/lib/e11y/instruments/rails_instrumentation.rb +141 -0
- data/lib/e11y/instruments/sidekiq.rb +175 -0
- data/lib/e11y/logger/bridge.rb +205 -0
- data/lib/e11y/metrics/cardinality_protection.rb +172 -0
- data/lib/e11y/metrics/cardinality_tracker.rb +134 -0
- data/lib/e11y/metrics/registry.rb +234 -0
- data/lib/e11y/metrics/relabeling.rb +226 -0
- data/lib/e11y/metrics.rb +102 -0
- data/lib/e11y/middleware/audit_signing.rb +174 -0
- data/lib/e11y/middleware/base.rb +140 -0
- data/lib/e11y/middleware/event_slo.rb +167 -0
- data/lib/e11y/middleware/pii_filter.rb +266 -0
- data/lib/e11y/middleware/pii_filtering.rb +280 -0
- data/lib/e11y/middleware/rate_limiting.rb +214 -0
- data/lib/e11y/middleware/request.rb +163 -0
- data/lib/e11y/middleware/routing.rb +157 -0
- data/lib/e11y/middleware/sampling.rb +254 -0
- data/lib/e11y/middleware/slo.rb +168 -0
- data/lib/e11y/middleware/trace_context.rb +131 -0
- data/lib/e11y/middleware/validation.rb +118 -0
- data/lib/e11y/middleware/versioning.rb +132 -0
- data/lib/e11y/middleware.rb +12 -0
- data/lib/e11y/pii/patterns.rb +90 -0
- data/lib/e11y/pii.rb +13 -0
- data/lib/e11y/pipeline/builder.rb +155 -0
- data/lib/e11y/pipeline/zone_validator.rb +110 -0
- data/lib/e11y/pipeline.rb +12 -0
- data/lib/e11y/presets/audit_event.rb +65 -0
- data/lib/e11y/presets/debug_event.rb +34 -0
- data/lib/e11y/presets/high_value_event.rb +51 -0
- data/lib/e11y/presets.rb +19 -0
- data/lib/e11y/railtie.rb +138 -0
- data/lib/e11y/reliability/circuit_breaker.rb +216 -0
- data/lib/e11y/reliability/dlq/file_storage.rb +277 -0
- data/lib/e11y/reliability/dlq/filter.rb +117 -0
- data/lib/e11y/reliability/retry_handler.rb +207 -0
- data/lib/e11y/reliability/retry_rate_limiter.rb +117 -0
- data/lib/e11y/sampling/error_spike_detector.rb +225 -0
- data/lib/e11y/sampling/load_monitor.rb +161 -0
- data/lib/e11y/sampling/stratified_tracker.rb +92 -0
- data/lib/e11y/sampling/value_extractor.rb +82 -0
- data/lib/e11y/self_monitoring/buffer_monitor.rb +79 -0
- data/lib/e11y/self_monitoring/performance_monitor.rb +97 -0
- data/lib/e11y/self_monitoring/reliability_monitor.rb +146 -0
- data/lib/e11y/slo/event_driven.rb +150 -0
- data/lib/e11y/slo/tracker.rb +119 -0
- data/lib/e11y/version.rb +9 -0
- data/lib/e11y.rb +283 -0
- metadata +452 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
# Implementation Plan: Critical Architecture Questions & Improvements
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-17
|
|
4
|
+
**Status:** 🚨 REQUIRES DECISION
|
|
5
|
+
**Priority:** CRITICAL (must be resolved BEFORE Phase 1)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🔴 CRITICAL QUESTIONS FROM CODE REVIEW
|
|
10
|
+
|
|
11
|
+
### Q1: ActiveSupport::Notifications - Bidirectional vs Unidirectional?
|
|
12
|
+
|
|
13
|
+
**Current Plan (ADR-008 §4.1):** Bidirectional bridge
|
|
14
|
+
- E11y → ActiveSupport::Notifications
|
|
15
|
+
- ActiveSupport::Notifications → E11y
|
|
16
|
+
|
|
17
|
+
**Your Question:** "Не лучше ли однонаправленный поток данных?"
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
#### 🤔 ANALYSIS:
|
|
22
|
+
|
|
23
|
+
**Unidirectional Design:**
|
|
24
|
+
```ruby
|
|
25
|
+
# ТОЛЬКО ASN → E11y (подписка на Rails события)
|
|
26
|
+
ActiveSupport::Notifications.subscribe('sql.active_record') do |...|
|
|
27
|
+
Events::Rails::Database::Query.track(...)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# E11y события идут ТОЛЬКО в adapters, не в ASN
|
|
31
|
+
Events::OrderCreated.track(...)
|
|
32
|
+
# → Middleware Pipeline → Adapters (Loki, Sentry)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
#### ✅ DESIGN: **UNIDIRECTIONAL FLOW (ASN → E11y)**
|
|
38
|
+
|
|
39
|
+
**Причины:**
|
|
40
|
+
|
|
41
|
+
1. **Избежание циклов:**
|
|
42
|
+
- ASN → E11y (ТОЛЬКО захват Rails internal events)
|
|
43
|
+
- E11y → Adapters (ТОЛЬКО отправка в бэкенды)
|
|
44
|
+
- Нет обратного пути (no cycles)
|
|
45
|
+
|
|
46
|
+
2. **Простота рассуждений (Single Direction):**
|
|
47
|
+
- Нет двунаправленной синхронизации
|
|
48
|
+
- Clear data flow
|
|
49
|
+
|
|
50
|
+
3. **Separation of Concerns:**
|
|
51
|
+
- ASN = Rails instrumentation (database, views, controllers)
|
|
52
|
+
- E11y = Business events + adapters
|
|
53
|
+
- Нет пересечения (clear boundary)
|
|
54
|
+
|
|
55
|
+
4. **Performance:**
|
|
56
|
+
- Unidirectional = 1x overhead (only subscribe from ASN)
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
#### 📋 IMPLEMENTATION:
|
|
61
|
+
|
|
62
|
+
**Unidirectional:**
|
|
63
|
+
```ruby
|
|
64
|
+
# lib/e11y/instruments/rails_instrumentation.rb
|
|
65
|
+
class RailsInstrumentation
|
|
66
|
+
# ActiveSupport::Notifications → E11y ✅
|
|
67
|
+
def self.subscribe_from_asn
|
|
68
|
+
...
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Implementation:**
|
|
74
|
+
```ruby
|
|
75
|
+
# lib/e11y/instruments/rails_instrumentation.rb
|
|
76
|
+
class RailsInstrumentation
|
|
77
|
+
# ONLY ActiveSupport::Notifications → E11y
|
|
78
|
+
def self.setup!
|
|
79
|
+
RAILS_EVENT_MAPPING.each do |asn_pattern, e11y_event_class|
|
|
80
|
+
ActiveSupport::Notifications.subscribe(asn_pattern) do |...|
|
|
81
|
+
e11y_event_class.track(...)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Q2: Built-In Event Classes - Можно ли переопределять?
|
|
91
|
+
|
|
92
|
+
**Current Plan:**
|
|
93
|
+
```ruby
|
|
94
|
+
# Built-in classes (hard-coded in gem)
|
|
95
|
+
Events::Rails::Database::Query
|
|
96
|
+
Events::Rails::Http::Request
|
|
97
|
+
Events::Rails::Job::Enqueued
|
|
98
|
+
Events::Rails::Job::Started
|
|
99
|
+
Events::Rails::Job::Completed
|
|
100
|
+
Events::Rails::Job::Failed
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Your Question:** "Вот эти классы событий можно будет переопределять в конфиге? По аналогии с devise controllers?"
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
#### ✅ RECOMMENDATION: **YES, OVERRIDABLE (Devise-style)**
|
|
108
|
+
|
|
109
|
+
**Design:**
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
# config/initializers/e11y.rb
|
|
113
|
+
E11y.configure do |config|
|
|
114
|
+
config.rails_instrumentation do
|
|
115
|
+
# Override default event classes (Devise-style)
|
|
116
|
+
event_class_for 'sql.active_record', MyApp::Events::CustomDatabaseQuery
|
|
117
|
+
event_class_for 'process_action.action_controller', MyApp::Events::CustomHttpRequest
|
|
118
|
+
|
|
119
|
+
# Or disable specific events
|
|
120
|
+
ignore_event 'cache_read.active_support' # Don't track cache reads
|
|
121
|
+
|
|
122
|
+
# Or use custom mapping
|
|
123
|
+
custom_mapping do
|
|
124
|
+
'my_custom_event' => MyApp::Events::CustomEvent
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Implementation:**
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
# lib/e11y/configuration/rails_instrumentation.rb
|
|
134
|
+
module E11y
|
|
135
|
+
module Configuration
|
|
136
|
+
class RailsInstrumentation
|
|
137
|
+
# Default mapping (can be overridden)
|
|
138
|
+
DEFAULT_EVENT_MAPPING = {
|
|
139
|
+
'sql.active_record' => Events::Rails::Database::Query,
|
|
140
|
+
'process_action.action_controller' => Events::Rails::Http::Request,
|
|
141
|
+
# ...
|
|
142
|
+
}.freeze
|
|
143
|
+
|
|
144
|
+
def initialize
|
|
145
|
+
@event_mapping = DEFAULT_EVENT_MAPPING.dup
|
|
146
|
+
@ignored_events = []
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Override event class (Devise-style)
|
|
150
|
+
def event_class_for(asn_pattern, custom_event_class)
|
|
151
|
+
@event_mapping[asn_pattern] = custom_event_class
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Disable event
|
|
155
|
+
def ignore_event(asn_pattern)
|
|
156
|
+
@ignored_events << asn_pattern
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Get final mapping (after overrides)
|
|
160
|
+
def event_mapping
|
|
161
|
+
@event_mapping.except(*@ignored_events)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Usage Example:**
|
|
169
|
+
|
|
170
|
+
```ruby
|
|
171
|
+
# Custom event class (override default)
|
|
172
|
+
module MyApp
|
|
173
|
+
module Events
|
|
174
|
+
class CustomDatabaseQuery < E11y::Event::Base
|
|
175
|
+
schema do
|
|
176
|
+
required(:query).filled(:string)
|
|
177
|
+
required(:duration).filled(:float)
|
|
178
|
+
required(:connection_name).filled(:string)
|
|
179
|
+
|
|
180
|
+
# Custom field (not in default Event::Rails::Database::Query)
|
|
181
|
+
optional(:database_shard).filled(:string)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Custom adapter routing
|
|
185
|
+
adapters [:loki, :elasticsearch] # Override: also send to ES
|
|
186
|
+
|
|
187
|
+
# Custom PII filtering
|
|
188
|
+
pii_filtering do
|
|
189
|
+
masks :query # Mask SQL queries (more aggressive than default)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# config/initializers/e11y.rb
|
|
196
|
+
E11y.configure do |config|
|
|
197
|
+
config.rails_instrumentation do
|
|
198
|
+
event_class_for 'sql.active_record', MyApp::Events::CustomDatabaseQuery
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Benefits:**
|
|
204
|
+
- ✅ Flexibility (custom schema, PII rules, adapters)
|
|
205
|
+
- ✅ Familiar pattern (Devise-style)
|
|
206
|
+
- ✅ Opt-in (defaults work for 90% cases)
|
|
207
|
+
- ✅ No monkey-patching (clean override)
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Q3: Gem Best Practices - Отсутствует в плане!
|
|
212
|
+
|
|
213
|
+
**Your Question:** "Не увидел в начале плана задачи про инициализацию гема и поиск лучших практик написания и оформления гемов (прежде всего популярных и успешных)"
|
|
214
|
+
|
|
215
|
+
**Current Plan:** Week -1 "Setup project skeleton" (но нет детализации!)
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
#### ✅ RECOMMENDATION: **ADD NEW TASK TO PHASE 0 (Week -1)**
|
|
220
|
+
|
|
221
|
+
**NEW PHASE 0: GEM INITIALIZATION & BEST PRACTICES (Week -1)**
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
#### 📋 PROPOSED NEW SECTION FOR PLAN:
|
|
226
|
+
|
|
227
|
+
```markdown
|
|
228
|
+
## PHASE 0: GEM INITIALIZATION & BEST PRACTICES (Week -1)
|
|
229
|
+
|
|
230
|
+
### L2.0: Gem Structure & Best Practices Research 🔴
|
|
231
|
+
|
|
232
|
+
**Purpose:** Research and setup professional gem structure BEFORE coding
|
|
233
|
+
**Depends On:** None (foundation)
|
|
234
|
+
**Parallelizable:** ⚙️ 1-2 devs
|
|
235
|
+
|
|
236
|
+
#### L3.0.1: Best Practices Research
|
|
237
|
+
|
|
238
|
+
**Tasks:**
|
|
239
|
+
|
|
240
|
+
1. **Study Successful Rails Gems**
|
|
241
|
+
- **Devise** (authentication) - controller overrides, modular design
|
|
242
|
+
- **Sidekiq** (background jobs) - middleware pattern, configuration DSL
|
|
243
|
+
- **Puma** (web server) - configuration DSL, plugin system
|
|
244
|
+
- **Dry-rb gems** (dry-schema, dry-validation) - functional design, composition
|
|
245
|
+
- **Yabeda** (metrics) - DSL design, extensibility
|
|
246
|
+
- **Sentry-ruby** (error tracking) - Rails integration, configuration
|
|
247
|
+
- ✅ DoD: Document 10+ patterns from each gem
|
|
248
|
+
|
|
249
|
+
2. **Gem Structure Analysis**
|
|
250
|
+
- Directory structure (lib/, spec/, bin/, docs/)
|
|
251
|
+
- File naming conventions
|
|
252
|
+
- Module organization (E11y::, E11y::Instruments::, etc.)
|
|
253
|
+
- Autoloading strategy (Zeitwerk vs manual requires)
|
|
254
|
+
- ✅ DoD: Documented gem structure template
|
|
255
|
+
|
|
256
|
+
3. **Configuration DSL Patterns**
|
|
257
|
+
- Study: Devise, Sidekiq, Sentry configuration patterns
|
|
258
|
+
- Block-based DSL (E11y.configure { |config| ... })
|
|
259
|
+
- Nested configuration (config.adapters do ... end)
|
|
260
|
+
- Type validation (dry-types?)
|
|
261
|
+
- Environment-specific config
|
|
262
|
+
- ✅ DoD: Configuration DSL design document
|
|
263
|
+
|
|
264
|
+
4. **Testing Strategies**
|
|
265
|
+
- RSpec setup (spec_helper, rails_helper)
|
|
266
|
+
- Test factories (FactoryBot? Plain Ruby?)
|
|
267
|
+
- Contract tests for public APIs
|
|
268
|
+
- Integration tests with Rails
|
|
269
|
+
- Load testing setup
|
|
270
|
+
- ✅ DoD: Testing strategy document
|
|
271
|
+
|
|
272
|
+
5. **Documentation Standards**
|
|
273
|
+
- YARD documentation (inline docs)
|
|
274
|
+
- README structure
|
|
275
|
+
- Guides vs API reference
|
|
276
|
+
- Code examples
|
|
277
|
+
- Changelog format (Keep a Changelog)
|
|
278
|
+
- ✅ DoD: Documentation template
|
|
279
|
+
|
|
280
|
+
6. **CI/CD Best Practices**
|
|
281
|
+
- GitHub Actions setup
|
|
282
|
+
- Matrix testing (Ruby 3.2, 3.3, Rails 8.0+)
|
|
283
|
+
- Code coverage (SimpleCov)
|
|
284
|
+
- Linting (Rubocop, StandardRB?)
|
|
285
|
+
- Security scanning (Brakeman, Bundler Audit)
|
|
286
|
+
- ✅ DoD: CI/CD pipeline configured
|
|
287
|
+
|
|
288
|
+
7. **Gem Release Process**
|
|
289
|
+
- Semantic versioning strategy
|
|
290
|
+
- Changelog generation
|
|
291
|
+
- RubyGems release checklist
|
|
292
|
+
- GitHub releases with notes
|
|
293
|
+
- Deprecation warnings strategy
|
|
294
|
+
- ✅ DoD: Release process documented
|
|
295
|
+
|
|
296
|
+
**Verification (L6):**
|
|
297
|
+
- Research notes: `docs/research/gem_best_practices.md`
|
|
298
|
+
- Gem structure template: `docs/research/gem_structure_template.md`
|
|
299
|
+
- Configuration DSL design: `docs/research/configuration_dsl_design.md`
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
#### L3.0.2: Project Skeleton Setup
|
|
304
|
+
|
|
305
|
+
**Tasks:**
|
|
306
|
+
|
|
307
|
+
1. **Initialize Gem**
|
|
308
|
+
```bash
|
|
309
|
+
bundle gem e11y --mit --test=rspec --ci=github --linter=rubocop
|
|
310
|
+
```
|
|
311
|
+
- ✅ DoD: Gem skeleton created
|
|
312
|
+
|
|
313
|
+
2. **Setup Directory Structure**
|
|
314
|
+
```
|
|
315
|
+
e11y/
|
|
316
|
+
├── lib/
|
|
317
|
+
│ ├── e11y.rb (main entry point)
|
|
318
|
+
│ ├── e11y/
|
|
319
|
+
│ │ ├── version.rb
|
|
320
|
+
│ │ ├── configuration.rb
|
|
321
|
+
│ │ ├── event/
|
|
322
|
+
│ │ │ └── base.rb
|
|
323
|
+
│ │ ├── middleware/
|
|
324
|
+
│ │ │ └── base.rb
|
|
325
|
+
│ │ ├── adapters/
|
|
326
|
+
│ │ │ └── base.rb
|
|
327
|
+
│ │ ├── buffers/
|
|
328
|
+
│ │ │ └── base_buffer.rb
|
|
329
|
+
│ │ ├── instruments/
|
|
330
|
+
│ │ │ └── rails_instrumentation.rb
|
|
331
|
+
│ │ └── railtie.rb (if Rails)
|
|
332
|
+
│ └── e11y/
|
|
333
|
+
├── spec/
|
|
334
|
+
│ ├── spec_helper.rb
|
|
335
|
+
│ ├── rails_helper.rb (for Rails integration tests)
|
|
336
|
+
│ ├── support/
|
|
337
|
+
│ └── e11y/
|
|
338
|
+
├── benchmarks/
|
|
339
|
+
│ ├── e11y_benchmarks.rb
|
|
340
|
+
│ └── load_tests.rb
|
|
341
|
+
├── docs/
|
|
342
|
+
│ ├── README.md
|
|
343
|
+
│ ├── ADR-*.md
|
|
344
|
+
│ ├── use_cases/
|
|
345
|
+
│ └── guides/
|
|
346
|
+
├── bin/
|
|
347
|
+
│ └── console (IRB with E11y loaded)
|
|
348
|
+
├── .github/
|
|
349
|
+
│ └── workflows/
|
|
350
|
+
│ ├── ci.yml
|
|
351
|
+
│ └── release.yml
|
|
352
|
+
├── docker-compose.yml (Loki, Prometheus, Elasticsearch)
|
|
353
|
+
├── Gemfile
|
|
354
|
+
├── e11y.gemspec
|
|
355
|
+
├── Rakefile
|
|
356
|
+
├── .rubocop.yml
|
|
357
|
+
└── README.md
|
|
358
|
+
```
|
|
359
|
+
- ✅ DoD: Professional gem structure
|
|
360
|
+
|
|
361
|
+
3. **Setup Zeitwerk Autoloading**
|
|
362
|
+
```ruby
|
|
363
|
+
# lib/e11y.rb
|
|
364
|
+
require 'zeitwerk'
|
|
365
|
+
|
|
366
|
+
loader = Zeitwerk::Loader.for_gem
|
|
367
|
+
loader.setup
|
|
368
|
+
```
|
|
369
|
+
- ✅ DoD: Autoloading works correctly
|
|
370
|
+
|
|
371
|
+
4. **Setup CI/CD (GitHub Actions)**
|
|
372
|
+
```yaml
|
|
373
|
+
# .github/workflows/ci.yml
|
|
374
|
+
name: CI
|
|
375
|
+
on: [push, pull_request]
|
|
376
|
+
jobs:
|
|
377
|
+
test:
|
|
378
|
+
runs-on: ubuntu-latest
|
|
379
|
+
strategy:
|
|
380
|
+
matrix:
|
|
381
|
+
ruby: ['3.2', '3.3']
|
|
382
|
+
rails: ['8.0']
|
|
383
|
+
steps:
|
|
384
|
+
- uses: actions/checkout@v3
|
|
385
|
+
- uses: ruby/setup-ruby@v1
|
|
386
|
+
with:
|
|
387
|
+
ruby-version: ${{ matrix.ruby }}
|
|
388
|
+
bundler-cache: true
|
|
389
|
+
- run: bundle exec rspec
|
|
390
|
+
- run: bundle exec rubocop
|
|
391
|
+
```
|
|
392
|
+
- ✅ DoD: CI runs on every commit
|
|
393
|
+
|
|
394
|
+
5. **Setup Docker Compose (Test Backends)**
|
|
395
|
+
```yaml
|
|
396
|
+
# docker-compose.yml
|
|
397
|
+
version: '3.8'
|
|
398
|
+
services:
|
|
399
|
+
loki:
|
|
400
|
+
image: grafana/loki:2.9.0
|
|
401
|
+
ports:
|
|
402
|
+
- "3100:3100"
|
|
403
|
+
|
|
404
|
+
prometheus:
|
|
405
|
+
image: prom/prometheus:v2.45.0
|
|
406
|
+
ports:
|
|
407
|
+
- "9090:9090"
|
|
408
|
+
|
|
409
|
+
elasticsearch:
|
|
410
|
+
image: elasticsearch:8.9.0
|
|
411
|
+
ports:
|
|
412
|
+
- "9200:9200"
|
|
413
|
+
environment:
|
|
414
|
+
- discovery.type=single-node
|
|
415
|
+
```
|
|
416
|
+
- ✅ DoD: Adapters can test against real backends
|
|
417
|
+
|
|
418
|
+
6. **Setup SimpleCov (Code Coverage)**
|
|
419
|
+
```ruby
|
|
420
|
+
# spec/spec_helper.rb
|
|
421
|
+
require 'simplecov'
|
|
422
|
+
SimpleCov.start do
|
|
423
|
+
add_filter '/spec/'
|
|
424
|
+
minimum_coverage 100 # Enforce 100% coverage!
|
|
425
|
+
end
|
|
426
|
+
```
|
|
427
|
+
- ✅ DoD: Coverage enforced
|
|
428
|
+
|
|
429
|
+
7. **Setup Rubocop (Linting)**
|
|
430
|
+
```yaml
|
|
431
|
+
# .rubocop.yml
|
|
432
|
+
require:
|
|
433
|
+
- rubocop-performance
|
|
434
|
+
- rubocop-rspec
|
|
435
|
+
|
|
436
|
+
AllCops:
|
|
437
|
+
TargetRubyVersion: 3.2
|
|
438
|
+
NewCops: enable
|
|
439
|
+
|
|
440
|
+
Style/Documentation:
|
|
441
|
+
Enabled: true # Enforce YARD docs!
|
|
442
|
+
```
|
|
443
|
+
- ✅ DoD: Linting enforced
|
|
444
|
+
|
|
445
|
+
**Verification (L6):**
|
|
446
|
+
- Gem builds: `gem build e11y.gemspec`
|
|
447
|
+
- Tests run: `bundle exec rspec`
|
|
448
|
+
- Linting passes: `bundle exec rubocop`
|
|
449
|
+
- Coverage 100%: `open coverage/index.html`
|
|
450
|
+
- CI green: GitHub Actions badge
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
#### L3.0.3: Research Documentation
|
|
455
|
+
|
|
456
|
+
**Deliverables:**
|
|
457
|
+
|
|
458
|
+
1. **`docs/research/gem_best_practices.md`**
|
|
459
|
+
- Patterns from Devise, Sidekiq, Puma, Dry-rb, Yabeda, Sentry
|
|
460
|
+
- Configuration DSL patterns
|
|
461
|
+
- Testing strategies
|
|
462
|
+
- Documentation standards
|
|
463
|
+
|
|
464
|
+
2. **`docs/research/gem_structure_template.md`**
|
|
465
|
+
- Directory structure
|
|
466
|
+
- File naming conventions
|
|
467
|
+
- Module organization
|
|
468
|
+
- Autoloading strategy
|
|
469
|
+
|
|
470
|
+
3. **`docs/research/configuration_dsl_design.md`**
|
|
471
|
+
- Block-based DSL design
|
|
472
|
+
- Nested configuration
|
|
473
|
+
- Type validation
|
|
474
|
+
- Environment-specific config
|
|
475
|
+
|
|
476
|
+
4. **`docs/research/gem_release_process.md`**
|
|
477
|
+
- Semantic versioning
|
|
478
|
+
- Changelog generation
|
|
479
|
+
- RubyGems release checklist
|
|
480
|
+
- Deprecation strategy
|
|
481
|
+
|
|
482
|
+
**Verification (L6):**
|
|
483
|
+
- Documents reviewed by team
|
|
484
|
+
- Patterns applied to Phase 1 tasks
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
### Q4: Rails.logger - Wrapper vs Replacement?
|
|
490
|
+
|
|
491
|
+
**Your Question:** "Может просто нужно сделать wrapper для rails логгера, а не переопределять?"
|
|
492
|
+
|
|
493
|
+
**Current ADR-008 §7:** Bridge pattern (wrapper + replacement)
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
#### ✅ CURRENT DESIGN IS CORRECT (Wrapper + Opt-In Replacement)
|
|
498
|
+
|
|
499
|
+
**ADR-008 already uses wrapper pattern!**
|
|
500
|
+
|
|
501
|
+
```ruby
|
|
502
|
+
# lib/e11y/logger/bridge.rb
|
|
503
|
+
class Bridge
|
|
504
|
+
def initialize(original_logger = nil)
|
|
505
|
+
@original_logger = original_logger # ← Keep original!
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def info(message)
|
|
509
|
+
# 1. Send to E11y
|
|
510
|
+
Events::Rails::Log.track(message: message, severity: :info)
|
|
511
|
+
|
|
512
|
+
# 2. Mirror to original logger (optional)
|
|
513
|
+
@original_logger.info(message) if @original_logger && mirror_enabled?
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
# Opt-in replacement:
|
|
518
|
+
Rails.logger = E11y::Logger::Bridge.new(Rails.logger)
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Benefits of Current Design:**
|
|
522
|
+
- ✅ Wrapper pattern (delegates to original logger)
|
|
523
|
+
- ✅ Opt-in replacement (`Rails.logger = Bridge.new(...)`)
|
|
524
|
+
- ✅ Mirroring support (dual logging during migration)
|
|
525
|
+
- ✅ Gradual migration (3-phase strategy)
|
|
526
|
+
|
|
527
|
+
**No changes needed!** Current design is correct.
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## 📋 SUMMARY OF REQUIRED CHANGES TO PLAN
|
|
532
|
+
|
|
533
|
+
### ✅ APPROVED CHANGES:
|
|
534
|
+
|
|
535
|
+
1. **Q1: Unidirectional Flow (ASN → E11y)** ✅ COMPLETED
|
|
536
|
+
- Changed bidirectional bridge to unidirectional
|
|
537
|
+
- **Files updated:**
|
|
538
|
+
- `docs/ADR-008-rails-integration.md` §4
|
|
539
|
+
|
|
540
|
+
2. **Q2: Overridable Event Classes (Devise-style)**
|
|
541
|
+
- Add configuration DSL for event class overrides
|
|
542
|
+
- Add `ignore_event` for disabling specific events
|
|
543
|
+
- **Files to update:**
|
|
544
|
+
- `docs/IMPLEMENTATION_PLAN_6_LEVELS.md` §L3.8.2
|
|
545
|
+
- `docs/ADR-008-rails-integration.md` §4
|
|
546
|
+
|
|
547
|
+
3. **Q3: Add Phase 0 (Gem Best Practices Research)**
|
|
548
|
+
- New phase: Week -1 (BEFORE Phase 1)
|
|
549
|
+
- Research successful gems (Devise, Sidekiq, Puma, etc.)
|
|
550
|
+
- Setup professional gem structure
|
|
551
|
+
- **Files to update:**
|
|
552
|
+
- `docs/IMPLEMENTATION_PLAN_6_LEVELS.md` (insert Phase 0)
|
|
553
|
+
- `docs/IMPLEMENTATION_PLAN_EXECUTIVE_SUMMARY.md` (update timeline)
|
|
554
|
+
- `docs/IMPLEMENTATION_PLAN_DEPENDENCY_MAP.md` (add Phase 0)
|
|
555
|
+
|
|
556
|
+
### ❌ NO CHANGES NEEDED:
|
|
557
|
+
|
|
558
|
+
4. **Q4: Rails.logger Wrapper**
|
|
559
|
+
- Current design already uses wrapper pattern
|
|
560
|
+
- No changes required
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## 🚨 ACTION ITEMS (BEFORE PHASE 1 STARTS)
|
|
565
|
+
|
|
566
|
+
### Immediate (This Week):
|
|
567
|
+
|
|
568
|
+
- [ ] **Review this document** with team/user
|
|
569
|
+
- [ ] **Approve architectural decisions** (Q1, Q2, Q3)
|
|
570
|
+
- [ ] **Update implementation plan** with Phase 0
|
|
571
|
+
- [ ] **Update ADR-008** with unidirectional flow + overridable classes
|
|
572
|
+
- [ ] **Research gems** (Devise, Sidekiq, Puma, Dry-rb, Yabeda, Sentry)
|
|
573
|
+
- [ ] **Setup project skeleton** (gem structure, CI/CD)
|
|
574
|
+
|
|
575
|
+
### Next Week (Week 0):
|
|
576
|
+
|
|
577
|
+
- [ ] **Team kickoff** (review Phase 0 research)
|
|
578
|
+
- [ ] **Assign streams** (A/B/C/D)
|
|
579
|
+
- [ ] **Start Phase 1** (Foundation)
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
**Status:** 🚨 AWAITING APPROVAL
|
|
584
|
+
**Priority:** CRITICAL (blocks Phase 1 start)
|
|
585
|
+
**Created:** 2026-01-17
|
|
586
|
+
**Estimated Resolution Time:** 1-2 days
|