rapitapir 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.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +57 -0
  4. data/CHANGELOG.md +94 -0
  5. data/CLEANUP_SUMMARY.md +155 -0
  6. data/CONTRIBUTING.md +280 -0
  7. data/LICENSE +21 -0
  8. data/README.md +485 -0
  9. data/debug_hash.rb +20 -0
  10. data/docs/EXTENSION_COMPARISON.md +388 -0
  11. data/docs/SINATRA_EXTENSION.md +467 -0
  12. data/docs/archive/PHASE_1_2_COMPLETE.md +77 -0
  13. data/docs/archive/PHASE_1_3_COMPLETE.md +152 -0
  14. data/docs/archive/PHASE_2_1_OBSERVABILITY_COMPLETED.md +203 -0
  15. data/docs/archive/PHASE_2_SUMMARY.md +209 -0
  16. data/docs/archive/REFACTORING_SUMMARY.md +184 -0
  17. data/docs/archive/phase_1_3_plan.md +136 -0
  18. data/docs/archive/sinatra_extension_summary.md +188 -0
  19. data/docs/archive/sinatra_working_solution.md +113 -0
  20. data/docs/archive/typescript-client-generator-summary.md +259 -0
  21. data/docs/auto-derivation.md +146 -0
  22. data/docs/blueprint.md +1091 -0
  23. data/docs/endpoint-definition.md +211 -0
  24. data/docs/github_pages_fix.md +52 -0
  25. data/docs/github_pages_setup.md +49 -0
  26. data/docs/implementation-status.md +357 -0
  27. data/docs/observability.md +647 -0
  28. data/docs/phase3-plan.md +108 -0
  29. data/docs/sinatra_rapitapir.md +87 -0
  30. data/docs/type_shortcuts.md +146 -0
  31. data/examples/README_ENTERPRISE.md +202 -0
  32. data/examples/authentication_example.rb +192 -0
  33. data/examples/auto_derivation_ruby_friendly.rb +163 -0
  34. data/examples/cli/user_api_endpoints.rb +56 -0
  35. data/examples/client/typescript_client_example.rb +102 -0
  36. data/examples/client/user-api-client.ts +193 -0
  37. data/examples/demo_api.rb +41 -0
  38. data/examples/docs/documentation_example.rb +112 -0
  39. data/examples/docs/user-api-docs.html +789 -0
  40. data/examples/docs/user-api-docs.md +403 -0
  41. data/examples/enhanced_auto_derivation_test.rb +83 -0
  42. data/examples/enterprise_extension_demo.rb +417 -0
  43. data/examples/enterprise_rapitapir_api.rb +662 -0
  44. data/examples/getting_started_extension.rb +218 -0
  45. data/examples/hello_world.rb +74 -0
  46. data/examples/oauth2/.env.example +19 -0
  47. data/examples/oauth2/README.md +205 -0
  48. data/examples/oauth2/generic_oauth2_api.rb +226 -0
  49. data/examples/oauth2/get_token.rb +72 -0
  50. data/examples/oauth2/songs_api_with_auth0.rb +320 -0
  51. data/examples/oauth2/test_api.sh +16 -0
  52. data/examples/oauth2/test_songs_api.sh +110 -0
  53. data/examples/observability/.env.example +35 -0
  54. data/examples/observability/README.md +230 -0
  55. data/examples/observability/README_HONEYCOMB.md +332 -0
  56. data/examples/observability/advanced_setup.rb +384 -0
  57. data/examples/observability/basic_setup.rb +192 -0
  58. data/examples/observability/complete_test.rb +121 -0
  59. data/examples/observability/honeycomb_example.rb +523 -0
  60. data/examples/observability/honeycomb_rapitapir_clean.rb +488 -0
  61. data/examples/observability/honeycomb_rapitapir_example.rb +523 -0
  62. data/examples/observability/honeycomb_working_example.rb +489 -0
  63. data/examples/observability/quick_test.rb +78 -0
  64. data/examples/observability/simple_test.rb +14 -0
  65. data/examples/observability/test_honeycomb_demo.rb +354 -0
  66. data/examples/observability/test_live_honeycomb.rb +111 -0
  67. data/examples/observability/test_validation.rb +78 -0
  68. data/examples/observability/test_working_validation.rb +66 -0
  69. data/examples/openapi/user_api_schema.rb +132 -0
  70. data/examples/production_ready_example.rb +105 -0
  71. data/examples/rails/users_controller.rb +146 -0
  72. data/examples/readme/basic_sinatra_example.rb +128 -0
  73. data/examples/server/user_api.rb +179 -0
  74. data/examples/simple_auto_derivation_demo.rb +44 -0
  75. data/examples/simple_demo_api.rb +18 -0
  76. data/examples/sinatra/user_app.rb +127 -0
  77. data/examples/t_shortcut_demo.rb +59 -0
  78. data/examples/user_api.rb +190 -0
  79. data/examples/working_getting_started.rb +184 -0
  80. data/examples/working_simple_example.rb +195 -0
  81. data/lib/rapitapir/auth/configuration.rb +129 -0
  82. data/lib/rapitapir/auth/context.rb +122 -0
  83. data/lib/rapitapir/auth/errors.rb +104 -0
  84. data/lib/rapitapir/auth/middleware.rb +324 -0
  85. data/lib/rapitapir/auth/oauth2.rb +350 -0
  86. data/lib/rapitapir/auth/schemes.rb +420 -0
  87. data/lib/rapitapir/auth.rb +113 -0
  88. data/lib/rapitapir/cli/command.rb +535 -0
  89. data/lib/rapitapir/cli/server.rb +243 -0
  90. data/lib/rapitapir/cli/validator.rb +373 -0
  91. data/lib/rapitapir/client/generator_base.rb +272 -0
  92. data/lib/rapitapir/client/typescript_generator.rb +350 -0
  93. data/lib/rapitapir/core/endpoint.rb +158 -0
  94. data/lib/rapitapir/core/enhanced_endpoint.rb +235 -0
  95. data/lib/rapitapir/core/input.rb +182 -0
  96. data/lib/rapitapir/core/output.rb +164 -0
  97. data/lib/rapitapir/core/request.rb +19 -0
  98. data/lib/rapitapir/core/response.rb +17 -0
  99. data/lib/rapitapir/docs/html_generator.rb +780 -0
  100. data/lib/rapitapir/docs/markdown_generator.rb +464 -0
  101. data/lib/rapitapir/dsl/endpoint_dsl.rb +116 -0
  102. data/lib/rapitapir/dsl/enhanced_endpoint_dsl.rb +62 -0
  103. data/lib/rapitapir/dsl/enhanced_input.rb +73 -0
  104. data/lib/rapitapir/dsl/enhanced_output.rb +63 -0
  105. data/lib/rapitapir/dsl/enhanced_structures.rb +393 -0
  106. data/lib/rapitapir/dsl/fluent_dsl.rb +72 -0
  107. data/lib/rapitapir/dsl/fluent_endpoint_builder.rb +316 -0
  108. data/lib/rapitapir/dsl/http_verbs.rb +77 -0
  109. data/lib/rapitapir/dsl/input_methods.rb +47 -0
  110. data/lib/rapitapir/dsl/observability_methods.rb +81 -0
  111. data/lib/rapitapir/dsl/output_methods.rb +43 -0
  112. data/lib/rapitapir/dsl/type_resolution.rb +43 -0
  113. data/lib/rapitapir/observability/configuration.rb +108 -0
  114. data/lib/rapitapir/observability/health_check.rb +236 -0
  115. data/lib/rapitapir/observability/logging.rb +270 -0
  116. data/lib/rapitapir/observability/metrics.rb +203 -0
  117. data/lib/rapitapir/observability/middleware.rb +243 -0
  118. data/lib/rapitapir/observability/tracing.rb +143 -0
  119. data/lib/rapitapir/observability.rb +28 -0
  120. data/lib/rapitapir/openapi/schema_generator.rb +403 -0
  121. data/lib/rapitapir/schema.rb +136 -0
  122. data/lib/rapitapir/server/enhanced_rack_adapter.rb +379 -0
  123. data/lib/rapitapir/server/middleware.rb +120 -0
  124. data/lib/rapitapir/server/path_matcher.rb +45 -0
  125. data/lib/rapitapir/server/rack_adapter.rb +215 -0
  126. data/lib/rapitapir/server/rails_adapter.rb +17 -0
  127. data/lib/rapitapir/server/rails_adapter_class.rb +53 -0
  128. data/lib/rapitapir/server/rails_controller.rb +72 -0
  129. data/lib/rapitapir/server/rails_input_processor.rb +73 -0
  130. data/lib/rapitapir/server/rails_response_handler.rb +29 -0
  131. data/lib/rapitapir/server/sinatra_adapter.rb +200 -0
  132. data/lib/rapitapir/server/sinatra_integration.rb +93 -0
  133. data/lib/rapitapir/sinatra/configuration.rb +91 -0
  134. data/lib/rapitapir/sinatra/extension.rb +214 -0
  135. data/lib/rapitapir/sinatra/oauth2_helpers.rb +236 -0
  136. data/lib/rapitapir/sinatra/resource_builder.rb +152 -0
  137. data/lib/rapitapir/sinatra/swagger_ui_generator.rb +166 -0
  138. data/lib/rapitapir/sinatra_rapitapir.rb +40 -0
  139. data/lib/rapitapir/types/array.rb +163 -0
  140. data/lib/rapitapir/types/auto_derivation.rb +265 -0
  141. data/lib/rapitapir/types/base.rb +146 -0
  142. data/lib/rapitapir/types/boolean.rb +46 -0
  143. data/lib/rapitapir/types/date.rb +92 -0
  144. data/lib/rapitapir/types/datetime.rb +98 -0
  145. data/lib/rapitapir/types/email.rb +32 -0
  146. data/lib/rapitapir/types/float.rb +134 -0
  147. data/lib/rapitapir/types/hash.rb +161 -0
  148. data/lib/rapitapir/types/integer.rb +143 -0
  149. data/lib/rapitapir/types/object.rb +156 -0
  150. data/lib/rapitapir/types/optional.rb +65 -0
  151. data/lib/rapitapir/types/string.rb +185 -0
  152. data/lib/rapitapir/types/uuid.rb +32 -0
  153. data/lib/rapitapir/types.rb +155 -0
  154. data/lib/rapitapir/version.rb +5 -0
  155. data/lib/rapitapir.rb +173 -0
  156. data/rapitapir.gemspec +66 -0
  157. metadata +387 -0
@@ -0,0 +1,647 @@
1
+ # RapiTapir Observability Guide
2
+
3
+ This guide covers the comprehensive observability features introduced in RapiTapir Phase 2.1, including metrics collection, distributed tracing, structured logging, and health checks.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Quick Start](#quick-start)
8
+ - [Configuration](#configuration)
9
+ - [Metrics](#metrics)
10
+ - [Distributed Tracing](#distributed-tracing)
11
+ - [Structured Logging](#structured-logging)
12
+ - [Health Checks](#health-checks)
13
+ - [Middleware Integration](#middleware-integration)
14
+ - [Examples](#examples)
15
+
16
+ ## Quick Start
17
+
18
+ ```ruby
19
+ require 'rapitapir'
20
+
21
+ # Configure observability
22
+ RapiTapir.configure do |config|
23
+ # Enable Prometheus metrics
24
+ config.metrics.enable_prometheus
25
+
26
+ # Enable OpenTelemetry tracing
27
+ config.tracing.enable_opentelemetry
28
+
29
+ # Enable structured logging
30
+ config.logging.enable_structured
31
+
32
+ # Enable health checks
33
+ config.health_check.enable
34
+ end
35
+
36
+ # Create an endpoint with observability
37
+ endpoint = RapiTapir.endpoint
38
+ .get
39
+ .in("/users")
40
+ .out_json({ users: [{ id: :uuid, name: :string }] })
41
+ .with_metrics("user_list")
42
+ .with_tracing
43
+ .with_logging(level: :info)
44
+ .handle do |request|
45
+ # Your endpoint logic here
46
+ { users: [] }
47
+ end
48
+ ```
49
+
50
+ ## Configuration
51
+
52
+ ### Metrics Configuration
53
+
54
+ ```ruby
55
+ RapiTapir.configure do |config|
56
+ config.metrics.enable_prometheus(
57
+ namespace: 'my_api', # Metrics namespace (default: 'rapitapir')
58
+ labels: { # Custom labels for all metrics
59
+ service: 'user_service',
60
+ version: '1.0.0',
61
+ environment: 'production'
62
+ }
63
+ )
64
+ end
65
+ ```
66
+
67
+ ### Tracing Configuration
68
+
69
+ ```ruby
70
+ RapiTapir.configure do |config|
71
+ config.tracing.enable_opentelemetry(
72
+ service_name: 'my-api-service', # Service name for tracing
73
+ service_version: '1.0.0' # Service version
74
+ )
75
+ end
76
+ ```
77
+
78
+ ### Logging Configuration
79
+
80
+ ```ruby
81
+ RapiTapir.configure do |config|
82
+ config.logging.enable_structured(
83
+ level: :info, # Log level (:debug, :info, :warn, :error, :fatal)
84
+ fields: [ # Fields to include in structured logs
85
+ :timestamp, :level, :message, :request_id,
86
+ :method, :path, :status, :duration,
87
+ :user_id, :tenant_id # Custom fields
88
+ ]
89
+ )
90
+ end
91
+ ```
92
+
93
+ ### Health Check Configuration
94
+
95
+ ```ruby
96
+ RapiTapir.configure do |config|
97
+ config.health_check.enable(endpoint: '/health')
98
+
99
+ # Add custom health checks
100
+ config.health_check.add_check(:database) do
101
+ # Database health check logic
102
+ { status: :healthy, message: 'Database connection OK' }
103
+ end
104
+
105
+ config.health_check.add_check(:redis) do
106
+ # Redis health check logic
107
+ { status: :healthy, message: 'Redis connection OK' }
108
+ end
109
+ end
110
+ ```
111
+
112
+ ## Metrics
113
+
114
+ RapiTapir automatically collects the following metrics:
115
+
116
+ ### Default HTTP Metrics
117
+
118
+ - `{namespace}_http_requests_total` - Total number of HTTP requests
119
+ - `{namespace}_http_request_duration_seconds` - HTTP request duration histogram
120
+ - `{namespace}_http_errors_total` - Total number of HTTP errors
121
+ - `{namespace}_http_active_requests` - Number of active HTTP requests
122
+
123
+ ### Custom Metrics
124
+
125
+ You can record custom metrics in your endpoint handlers:
126
+
127
+ ```ruby
128
+ endpoint = RapiTapir.endpoint
129
+ .post
130
+ .in("/orders")
131
+ .with_metrics("order_creation")
132
+ .handle do |request|
133
+ # Custom counter
134
+ RapiTapir::Observability::Metrics.registry
135
+ .counter(:custom_events_total, labels: [:event_type])
136
+ .increment(labels: { event_type: 'order_created' })
137
+
138
+ # Custom histogram
139
+ duration = measure_time do
140
+ # Some operation
141
+ end
142
+
143
+ RapiTapir::Observability::Metrics.registry
144
+ .histogram(:operation_duration_seconds, labels: [:operation])
145
+ .observe(duration, labels: { operation: 'order_processing' })
146
+
147
+ # Your logic here
148
+ end
149
+ ```
150
+
151
+ ### Accessing Metrics
152
+
153
+ Metrics are exposed at `/metrics` endpoint in Prometheus format:
154
+
155
+ ```bash
156
+ curl http://localhost:9292/metrics
157
+ ```
158
+
159
+ ## Distributed Tracing
160
+
161
+ RapiTapir integrates with OpenTelemetry for distributed tracing:
162
+
163
+ ### Automatic Tracing
164
+
165
+ Every HTTP request is automatically traced with:
166
+ - Span name: `HTTP {METHOD} {PATH}`
167
+ - HTTP method, URL, status code, duration
168
+ - Request and response size
169
+ - Error information if applicable
170
+
171
+ ### Custom Tracing
172
+
173
+ Add custom spans and attributes in your endpoints:
174
+
175
+ ```ruby
176
+ endpoint = RapiTapir.endpoint
177
+ .post
178
+ .in("/orders")
179
+ .with_tracing("POST /orders")
180
+ .handle do |request|
181
+ # Add custom attributes to current span
182
+ RapiTapir::Observability::Tracing.set_attribute('user.id', request.user_id)
183
+ RapiTapir::Observability::Tracing.set_attribute('order.total', request.body[:total])
184
+
185
+ # Create nested spans
186
+ RapiTapir::Observability::Tracing.start_span("validate_order") do |span|
187
+ span.set_attribute('validation.type', 'business_rules')
188
+ validate_order(request.body)
189
+ end
190
+
191
+ RapiTapir::Observability::Tracing.start_span("process_payment") do |span|
192
+ payment_result = process_payment(request.body[:payment])
193
+ span.set_attribute('payment.provider', payment_result[:provider])
194
+ span.set_attribute('payment.transaction_id', payment_result[:transaction_id])
195
+ end
196
+
197
+ # Add events to span
198
+ RapiTapir::Observability::Tracing.add_event(
199
+ 'order.created',
200
+ attributes: { 'order.id' => order_id }
201
+ )
202
+
203
+ # Record exceptions
204
+ begin
205
+ risky_operation()
206
+ rescue => e
207
+ RapiTapir::Observability::Tracing.record_exception(e)
208
+ raise
209
+ end
210
+
211
+ # Your logic here
212
+ end
213
+ ```
214
+
215
+ ## Structured Logging
216
+
217
+ RapiTapir provides comprehensive structured logging:
218
+
219
+ ### Automatic Request Logging
220
+
221
+ Every HTTP request is automatically logged with:
222
+ - Request method, path, status code
223
+ - Request duration
224
+ - Request ID for correlation
225
+ - User agent, IP address
226
+ - Custom fields you configure
227
+
228
+ ### Custom Logging
229
+
230
+ Add structured logging in your endpoints:
231
+
232
+ ```ruby
233
+ endpoint = RapiTapir.endpoint
234
+ .post
235
+ .in("/users")
236
+ .with_logging(level: :info, fields: [:user_id, :operation])
237
+ .handle do |request|
238
+ user_data = request.body
239
+
240
+ # Structured info logging
241
+ RapiTapir::Observability::Logging.info(
242
+ "Creating user",
243
+ user_email: user_data[:email],
244
+ user_age: user_data[:age],
245
+ operation: 'user_creation'
246
+ )
247
+
248
+ # Log with different levels
249
+ RapiTapir::Observability::Logging.debug(
250
+ "Validation passed",
251
+ validation_time_ms: 5.2
252
+ )
253
+
254
+ RapiTapir::Observability::Logging.warn(
255
+ "Slow database response",
256
+ db_response_time_ms: 1200
257
+ )
258
+
259
+ # Log errors with context
260
+ begin
261
+ create_user(user_data)
262
+ rescue => e
263
+ RapiTapir::Observability::Logging.log_error(
264
+ e,
265
+ user_email: user_data[:email],
266
+ operation: 'user_creation',
267
+ request_id: request.id
268
+ )
269
+ raise
270
+ end
271
+
272
+ # Your logic here
273
+ end
274
+ ```
275
+
276
+ ### Log Formats
277
+
278
+ Choose from multiple log formats:
279
+
280
+ ```ruby
281
+ # JSON format (default for structured logging)
282
+ {"timestamp":"2024-01-01T12:00:00Z","level":"INFO","message":"User created","user_id":"123"}
283
+
284
+ # Logfmt format
285
+ timestamp=2024-01-01T12:00:00Z level=INFO message="User created" user_id=123
286
+
287
+ # Text format
288
+ 2024-01-01 12:00:00 [INFO] User created user_id=123
289
+ ```
290
+
291
+ ## Health Checks
292
+
293
+ RapiTapir provides comprehensive health check functionality:
294
+
295
+ ### Default Health Checks
296
+
297
+ - `ruby_runtime` - Ruby runtime status
298
+ - `memory_usage` - Memory and GC statistics
299
+ - `thread_count` - Active thread count
300
+
301
+ ### Custom Health Checks
302
+
303
+ Add custom health checks for your dependencies:
304
+
305
+ ```ruby
306
+ RapiTapir.configure do |config|
307
+ config.health_check.enable
308
+
309
+ # Database health check
310
+ config.health_check.add_check(:database) do
311
+ begin
312
+ result = ActiveRecord::Base.connection.execute("SELECT 1")
313
+ { status: :healthy, message: "Database connection OK" }
314
+ rescue => e
315
+ { status: :unhealthy, message: "Database error: #{e.message}" }
316
+ end
317
+ end
318
+
319
+ # Redis health check with timeout
320
+ config.health_check.add_check(:redis) do
321
+ begin
322
+ Timeout.timeout(5) do
323
+ Redis.current.ping
324
+ { status: :healthy, message: "Redis connection OK" }
325
+ end
326
+ rescue Timeout::Error
327
+ { status: :unhealthy, message: "Redis timeout" }
328
+ rescue => e
329
+ { status: :unhealthy, message: "Redis error: #{e.message}" }
330
+ end
331
+ end
332
+
333
+ # External API health check
334
+ config.health_check.add_check(:payment_api) do
335
+ begin
336
+ response = HTTP.timeout(10).get("https://api.stripe.com/v1/charges")
337
+ if response.status.success?
338
+ { status: :healthy, message: "Payment API reachable" }
339
+ else
340
+ { status: :unhealthy, message: "Payment API returned #{response.status}" }
341
+ end
342
+ rescue => e
343
+ { status: :unhealthy, message: "Payment API unreachable: #{e.message}" }
344
+ end
345
+ end
346
+ end
347
+ ```
348
+
349
+ ### Health Check Endpoints
350
+
351
+ Health checks are available at multiple endpoints:
352
+
353
+ ```bash
354
+ # Overall health status
355
+ GET /health
356
+ {
357
+ "status": "healthy",
358
+ "timestamp": "2024-01-01T12:00:00Z",
359
+ "service": "rapitapir",
360
+ "version": "0.1.0",
361
+ "checks": [
362
+ {
363
+ "name": "database",
364
+ "status": "healthy",
365
+ "message": "Database connection OK",
366
+ "duration_ms": 2.5
367
+ }
368
+ ]
369
+ }
370
+
371
+ # Individual health check
372
+ GET /health/check?name=database
373
+ {
374
+ "name": "database",
375
+ "status": "healthy",
376
+ "message": "Database connection OK",
377
+ "duration_ms": 2.5
378
+ }
379
+
380
+ # List available checks
381
+ GET /health/checks
382
+ {
383
+ "available_checks": [
384
+ {"name": "ruby_runtime", "url": "/health/check?name=ruby_runtime"},
385
+ {"name": "database", "url": "/health/check?name=database"}
386
+ ],
387
+ "total": 2
388
+ }
389
+ ```
390
+
391
+ ## Middleware Integration
392
+
393
+ ### Rack Applications
394
+
395
+ Use the observability middleware with any Rack application:
396
+
397
+ ```ruby
398
+ require 'rack'
399
+ require 'rapitapir'
400
+
401
+ # Configure observability
402
+ RapiTapir.configure do |config|
403
+ config.metrics.enable_prometheus
404
+ config.tracing.enable_opentelemetry
405
+ config.logging.enable_structured
406
+ config.health_check.enable
407
+ end
408
+
409
+ # Build application with observability
410
+ app = Rack::Builder.new do
411
+ # Add observability middleware (includes metrics, tracing, logging)
412
+ use RapiTapir::Observability::RackMiddleware
413
+
414
+ # Your application
415
+ run MyApp.new
416
+ end
417
+
418
+ run app
419
+ ```
420
+
421
+ ### Sinatra Integration
422
+
423
+ ```ruby
424
+ require 'sinatra'
425
+ require 'rapitapir'
426
+
427
+ # Configure observability
428
+ RapiTapir.configure do |config|
429
+ config.metrics.enable_prometheus
430
+ config.tracing.enable_opentelemetry
431
+ config.logging.enable_structured
432
+ config.health_check.enable
433
+ end
434
+
435
+ class MyApp < Sinatra::Base
436
+ use RapiTapir::Observability::RackMiddleware
437
+
438
+ get '/users' do
439
+ # Your route logic
440
+ end
441
+ end
442
+ ```
443
+
444
+ ### Rails Integration
445
+
446
+ ```ruby
447
+ # config/application.rb
448
+ require 'rapitapir'
449
+
450
+ class Application < Rails::Application
451
+ # Configure observability
452
+ config.before_configuration do
453
+ RapiTapir.configure do |config|
454
+ config.metrics.enable_prometheus(
455
+ namespace: 'rails_app',
456
+ labels: { environment: Rails.env }
457
+ )
458
+ config.tracing.enable_opentelemetry(
459
+ service_name: 'my-rails-app',
460
+ service_version: MyApp::VERSION
461
+ )
462
+ config.logging.enable_structured(level: :info)
463
+ config.health_check.enable
464
+ end
465
+ end
466
+
467
+ # Add observability middleware
468
+ config.middleware.use RapiTapir::Observability::RackMiddleware
469
+ end
470
+ ```
471
+
472
+ ## Examples
473
+
474
+ ### Basic E-commerce API
475
+
476
+ ```ruby
477
+ require 'rapitapir'
478
+
479
+ # Configure observability
480
+ RapiTapir.configure do |config|
481
+ config.metrics.enable_prometheus(namespace: 'ecommerce')
482
+ config.tracing.enable_opentelemetry(service_name: 'ecommerce-api')
483
+ config.logging.enable_structured
484
+ config.health_check.enable
485
+ end
486
+
487
+ # Create order endpoint
488
+ create_order = RapiTapir.endpoint
489
+ .post
490
+ .in("/orders")
491
+ .json_body({
492
+ customer_id: :uuid,
493
+ items: [{ product_id: :uuid, quantity: :integer, price: :float }]
494
+ })
495
+ .out_json({ id: :uuid, status: :string, total: :float })
496
+ .with_metrics("order_creation")
497
+ .with_tracing
498
+ .with_logging(fields: [:customer_id, :order_total, :item_count])
499
+ .handle do |request|
500
+ order_data = request.body
501
+
502
+ # Add business context to tracing
503
+ RapiTapir::Observability::Tracing.set_attribute('customer.id', order_data[:customer_id])
504
+ RapiTapir::Observability::Tracing.set_attribute('order.item_count', order_data[:items].length)
505
+
506
+ total = order_data[:items].sum { |item| item[:quantity] * item[:price] }
507
+ RapiTapir::Observability::Tracing.set_attribute('order.total', total)
508
+
509
+ # Structured logging
510
+ RapiTapir::Observability::Logging.info(
511
+ "Processing order",
512
+ customer_id: order_data[:customer_id],
513
+ order_total: total,
514
+ item_count: order_data[:items].length
515
+ )
516
+
517
+ # Process order with nested tracing
518
+ order_id = RapiTapir::Observability::Tracing.start_span("create_order_record") do
519
+ SecureRandom.uuid
520
+ end
521
+
522
+ RapiTapir::Observability::Tracing.start_span("send_confirmation_email") do |span|
523
+ span.set_attribute('email.type', 'order_confirmation')
524
+ # Send confirmation email
525
+ end
526
+
527
+ {
528
+ id: order_id,
529
+ status: 'confirmed',
530
+ total: total
531
+ }
532
+ end
533
+ ```
534
+
535
+ ### Advanced Monitoring Setup
536
+
537
+ ```ruby
538
+ # Production observability configuration
539
+ RapiTapir.configure do |config|
540
+ # Comprehensive metrics
541
+ config.metrics.enable_prometheus(
542
+ namespace: 'production_api',
543
+ labels: {
544
+ service: ENV['SERVICE_NAME'],
545
+ version: ENV['APP_VERSION'],
546
+ environment: ENV['RAILS_ENV'],
547
+ datacenter: ENV['DATACENTER']
548
+ }
549
+ )
550
+
551
+ # Distributed tracing
552
+ config.tracing.enable_opentelemetry(
553
+ service_name: ENV['SERVICE_NAME'],
554
+ service_version: ENV['APP_VERSION']
555
+ )
556
+
557
+ # Structured logging for log aggregation
558
+ config.logging.enable_structured(
559
+ level: ENV.fetch('LOG_LEVEL', 'info').to_sym,
560
+ fields: [
561
+ :timestamp, :level, :message, :request_id, :trace_id,
562
+ :method, :path, :status, :duration,
563
+ :user_id, :tenant_id, :session_id,
564
+ :source_ip, :user_agent
565
+ ]
566
+ )
567
+
568
+ # Comprehensive health checks
569
+ config.health_check.enable(endpoint: '/health')
570
+
571
+ # Database health check
572
+ config.health_check.add_check(:database) do
573
+ ActiveRecord::Base.connection.execute("SELECT 1")
574
+ { status: :healthy, message: "Primary database OK" }
575
+ rescue => e
576
+ { status: :unhealthy, message: "Database error: #{e.message}" }
577
+ end
578
+
579
+ # Redis health check
580
+ config.health_check.add_check(:redis) do
581
+ Redis.current.ping
582
+ { status: :healthy, message: "Redis cache OK" }
583
+ rescue => e
584
+ { status: :unhealthy, message: "Redis error: #{e.message}" }
585
+ end
586
+
587
+ # Message queue health check
588
+ config.health_check.add_check(:message_queue) do
589
+ # Check Sidekiq or similar
590
+ if defined?(Sidekiq)
591
+ stats = Sidekiq::Stats.new
592
+ queue_size = stats.enqueued
593
+
594
+ if queue_size > 10000
595
+ { status: :warning, message: "High queue size: #{queue_size}" }
596
+ else
597
+ { status: :healthy, message: "Queue size: #{queue_size}" }
598
+ end
599
+ else
600
+ { status: :healthy, message: "No message queue configured" }
601
+ end
602
+ rescue => e
603
+ { status: :unhealthy, message: "Queue error: #{e.message}" }
604
+ end
605
+ end
606
+ ```
607
+
608
+ ## Best Practices
609
+
610
+ ### 1. Metric Naming
611
+
612
+ Use consistent metric naming:
613
+ - Use underscores for separating words
614
+ - Include units in metric names (e.g., `_seconds`, `_bytes`)
615
+ - Use clear, descriptive names
616
+
617
+ ### 2. Trace Context
618
+
619
+ Add meaningful attributes to traces:
620
+ - Business identifiers (user_id, order_id, etc.)
621
+ - Request context (tenant_id, api_version)
622
+ - Performance indicators (cache_hit, db_query_count)
623
+
624
+ ### 3. Structured Logging
625
+
626
+ Design your log structure:
627
+ - Use consistent field names across services
628
+ - Include correlation IDs for request tracing
629
+ - Log at appropriate levels (debug for development, info+ for production)
630
+
631
+ ### 4. Health Check Design
632
+
633
+ Create meaningful health checks:
634
+ - Test actual functionality, not just connectivity
635
+ - Include response time thresholds
636
+ - Use timeouts to prevent hanging checks
637
+ - Return actionable status messages
638
+
639
+ ### 5. Error Handling
640
+
641
+ Implement comprehensive error observability:
642
+ - Always record exceptions in traces
643
+ - Log errors with sufficient context
644
+ - Use error metrics to track error rates
645
+ - Include error classification (validation, system, external)
646
+
647
+ This observability implementation provides production-ready monitoring capabilities for RapiTapir applications, enabling comprehensive visibility into system performance, health, and behavior.