exis_ray 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +104 -39
- data/lib/exis_ray/configuration.rb +14 -0
- data/lib/exis_ray/json_formatter.rb +100 -0
- data/lib/exis_ray/railtie.rb +63 -24
- data/lib/exis_ray/sidekiq/server_middleware.rb +47 -51
- data/lib/exis_ray/task_monitor.rb +62 -18
- data/lib/exis_ray/version.rb +1 -1
- data/lib/exis_ray.rb +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 72c313e5194f8252623ac026d98ab510c8ad50c7f4b7c7d8f362005c14d6d3e5
|
|
4
|
+
data.tar.gz: 51b8c985ab03bff4389784477e9c5eb5f27e81138766e50356414b2e88121b68
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5bd0a72ee15676c2074306af62a71098230b30831f49d9b678bb02dd853528a687db9e2d354d0fa34f3bcf758e0bf63fbd5512a949963e256528817749163fda
|
|
7
|
+
data.tar.gz: 485e39a4b8bf41a01a099d5a75c472f77683ac4a98bb1dcfa109e9abd16be0532930f78bebfee0a94beeb2a725cbae0a3696eabafaa070b0aae2a4cd24b13937
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2026-03-12
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Structured JSON Logging:** Introduced a centralized `ExisRay::JsonFormatter` that intercepts all application logs (HTTP, Sidekiq, and Rake tasks) and formats them into context-rich, single-line JSON objects.
|
|
7
|
+
- Added `lograge` as a core dependency to condense standard Rails multi-line HTTP logs into single events.
|
|
8
|
+
- Introduced the `config.log_format` configuration option (accepts `:text` or `:json`).
|
|
9
|
+
- Added native support for `ActiveSupport::TaggedLogging`. Standard Rails tags (`config.log_tags`) are now automatically intercepted and injected as a `"tags"` array within the JSON payload.
|
|
10
|
+
- Added support for merging Lograge's `custom_options` directly into the JSON root.
|
|
11
|
+
- Expanded `README.md` with an "Advanced Logging Guide", detailing environment-specific setup and customization strategies.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Refactored `Sidekiq::ServerMiddleware` and `TaskMonitor` to intelligently adapt their logging behavior based on the active `log_format`, preventing redundant tagging in JSON mode.
|
|
15
|
+
- Shifted the `Railtie` logging configuration to execute `after: :load_config_initializers`. This guarantees the host application's initializers are fully loaded before ExisRay determines the log format.
|
|
16
|
+
- Enforced strict RuboCop compliance (`Style/StringLiterals` -> double quotes) across all internal classes, methods, and documentation examples.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Fixed `NoMethodError: undefined method 'current_tags'` by ensuring `JsonFormatter` correctly includes the `ActiveSupport::TaggedLogging::Formatter` interface.
|
|
20
|
+
- Resolved a race condition during Rails boot where `lograge` failed to initialize if the gem configuration was set via an initializer.
|
|
21
|
+
|
|
3
22
|
## [0.1.0] - 2025-12-23
|
|
4
23
|
|
|
5
24
|
- Initial release
|
data/README.md
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# ExisRay
|
|
2
2
|
|
|
3
|
-
**ExisRay** is a robust observability framework designed for Ruby on Rails microservices. It unifies **Distributed Tracing** (AWS X-Ray compatible), **Business Context Propagation**,
|
|
3
|
+
**ExisRay** is a robust observability framework designed for Ruby on Rails microservices. It unifies **Distributed Tracing** (AWS X-Ray compatible), **Business Context Propagation**, **Error Reporting**, and **Structured JSON Logging** into a single, cohesive gem.
|
|
4
4
|
|
|
5
5
|
It acts as the backbone of your architecture, ensuring that every request, background task (Sidekiq/Cron), log line, and external API call carries the necessary context to debug issues across a distributed system.
|
|
6
6
|
|
|
7
7
|
## 🚀 Features
|
|
8
8
|
|
|
9
9
|
* **Distributed Tracing:** Automatically parses, generates, and propagates Trace headers (compatible with AWS ALB `X-Amzn-Trace-Id`).
|
|
10
|
-
* **
|
|
10
|
+
* **Structured JSON Logging:** Optionally unifies all your application logs (HTTP requests, Sidekiq jobs, and Rake tasks) into a clean, single-line JSON format, perfect for Datadog, ELK, or CloudWatch.
|
|
11
|
+
* **Unified Tagging:** If JSON logging is disabled, it automatically injects the global `Root ID` into every Rails log line.
|
|
11
12
|
* **Context Management:** Thread-safe storage for business identity (`User`, `ISP`, `CorrelationId`) with automatic cleanup.
|
|
12
13
|
* **Error Reporting:** A wrapper for Sentry (Legacy & Modern SDKs) that enriches errors with the full trace and business context.
|
|
13
|
-
* **Sidekiq Integration:** Automatic context propagation (User/ISP/Trace) between the Enqueuer and the Worker.
|
|
14
|
-
* **Task Monitor:** A specialized monitor for Rake/Cron tasks to initialize traces where no HTTP request exists.
|
|
14
|
+
* **Sidekiq Integration:** Automatic context propagation (User/ISP/Trace) and log formatting between the Enqueuer and the Worker.
|
|
15
|
+
* **Task Monitor:** A specialized monitor for Rake/Cron tasks to initialize traces and format logs where no HTTP request exists.
|
|
15
16
|
* **HTTP Clients:** Automatically patches `ActiveResource` and provides middleware for `Faraday`.
|
|
16
17
|
|
|
17
18
|
---
|
|
@@ -21,7 +22,7 @@ It acts as the backbone of your architecture, ensuring that every request, backg
|
|
|
21
22
|
Add this line to your application's Gemfile:
|
|
22
23
|
|
|
23
24
|
```ruby
|
|
24
|
-
gem
|
|
25
|
+
gem "exis_ray"
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
And then execute:
|
|
@@ -30,6 +31,8 @@ And then execute:
|
|
|
30
31
|
$ bundle install
|
|
31
32
|
```
|
|
32
33
|
|
|
34
|
+
*(Note: ExisRay automatically installs and configures `lograge` as a dependency to handle HTTP log condensation).*
|
|
35
|
+
|
|
33
36
|
---
|
|
34
37
|
|
|
35
38
|
## ⚙️ Configuration
|
|
@@ -42,18 +45,24 @@ Create an initializer to configure the behavior. This is crucial to link ExisRay
|
|
|
42
45
|
ExisRay.configure do |config|
|
|
43
46
|
# 1. Trace Header (Incoming)
|
|
44
47
|
# The HTTP header used to read the Trace ID from the Load Balancer (Rack format).
|
|
45
|
-
# Default:
|
|
46
|
-
config.trace_header =
|
|
48
|
+
# Default: "HTTP_X_AMZN_TRACE_ID" (AWS Standard).
|
|
49
|
+
config.trace_header = "HTTP_X_WP_TRACE_ID"
|
|
47
50
|
|
|
48
51
|
# 2. Propagation Header (Outgoing)
|
|
49
52
|
# The header sent to downstream services via ActiveResource/Faraday.
|
|
50
|
-
config.propagation_trace_header =
|
|
53
|
+
config.propagation_trace_header = "X-Wp-Trace-Id"
|
|
51
54
|
|
|
52
55
|
# 3. Dynamic Classes (Required)
|
|
53
56
|
# Link your app's specific classes to the gem.
|
|
54
57
|
# We use Strings to avoid "uninitialized constant" errors during boot.
|
|
55
|
-
config.current_class =
|
|
56
|
-
config.reporter_class =
|
|
58
|
+
config.current_class = "Current" # Your Context Model
|
|
59
|
+
config.reporter_class = "Choto" # Your Sentry Wrapper
|
|
60
|
+
|
|
61
|
+
# 4. Log Format (New!)
|
|
62
|
+
# Choose the output format for your application logs.
|
|
63
|
+
# Options: :text (default Rails behavior) or :json (Structured logging).
|
|
64
|
+
# Pro-tip: Make it dynamic based on the environment!
|
|
65
|
+
config.log_format = Rails.env.production? ? :json : :text
|
|
57
66
|
end
|
|
58
67
|
```
|
|
59
68
|
|
|
@@ -71,7 +80,7 @@ Inherit from `ExisRay::Current` to manage your global state. This class handles
|
|
|
71
80
|
class Current < ExisRay::Current
|
|
72
81
|
# Add app-specific attributes here
|
|
73
82
|
attribute :billing_cycle, :permissions
|
|
74
|
-
|
|
83
|
+
|
|
75
84
|
# ExisRay provides: user_id, isp_id, correlation_id
|
|
76
85
|
end
|
|
77
86
|
```
|
|
@@ -107,10 +116,7 @@ def set_exis_ray_context
|
|
|
107
116
|
Current.user = current_user if current_user
|
|
108
117
|
|
|
109
118
|
# 2. ISP Context (e.g., from Headers)
|
|
110
|
-
Current.isp_id = request.headers[
|
|
111
|
-
|
|
112
|
-
# Note: Setting these automatically prepares headers for ActiveResource
|
|
113
|
-
# and tags for Sentry.
|
|
119
|
+
Current.isp_id = request.headers["X-Isp-Id"]
|
|
114
120
|
end
|
|
115
121
|
```
|
|
116
122
|
|
|
@@ -118,33 +124,30 @@ end
|
|
|
118
124
|
|
|
119
125
|
## 🛠 Usage Scenarios
|
|
120
126
|
|
|
121
|
-
### A.
|
|
127
|
+
### A. Structured JSON Logging
|
|
128
|
+
|
|
129
|
+
When `config.log_format = :json` is enabled, ExisRay transforms all your application outputs into single-line, context-rich JSON objects.
|
|
130
|
+
|
|
131
|
+
**HTTP Requests (via Lograge):**
|
|
132
|
+
```json
|
|
133
|
+
{"time":"2026-03-12T14:30:00Z","level":"INFO","service":"App-HTTP","root_id":"Root=1-65a...bc","trace_id":"Root=1-65a...bc;Self=...","request_id":"9876-abcd-...","user_id":42,"isp_id":10,"method":"GET","path":"/api/v1/users","format":"html","controller":"UsersController","action":"index","status":200,"duration":45.2,"view":20.1,"db":15.0}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Sidekiq Jobs & Rake Tasks:**
|
|
137
|
+
```json
|
|
138
|
+
{"time":"2026-03-12T14:31:00Z","level":"INFO","service":"Sidekiq-HardWorker","root_id":"Root=1-65a...bc","user_id":42,"message":"[ExisRay] Processing payment..."}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### B. Automatic Sidekiq Integration
|
|
122
142
|
|
|
123
143
|
If `Sidekiq` is present, ExisRay automatically configures Client and Server middlewares. **No code changes are required in your workers.**
|
|
124
144
|
|
|
125
145
|
**How it works:**
|
|
126
146
|
1. **Enqueue:** When you call `Worker.perform_async`, the current `Trace ID` and `Current` attributes are injected into the job payload.
|
|
127
147
|
2. **Process:** When the worker executes, `Current` is hydrated with the original data.
|
|
128
|
-
3. **Logs:** Sidekiq logs will
|
|
148
|
+
3. **Logs:** Sidekiq logs will automatically include the propagated `Root ID` and Business Context (either as text tags or structured JSON).
|
|
129
149
|
|
|
130
|
-
|
|
131
|
-
# Controller
|
|
132
|
-
def create
|
|
133
|
-
# Trace ID: A, User: 42
|
|
134
|
-
HardWorker.perform_async(100)
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
# Worker
|
|
138
|
-
class HardWorker
|
|
139
|
-
include Sidekiq::Worker
|
|
140
|
-
def perform(amount)
|
|
141
|
-
puts Current.user_id # => 42 (Restored!)
|
|
142
|
-
Rails.logger.info "Processing" # => [Root=A] Processing...
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### B. Background Tasks (Cron/Rake)
|
|
150
|
+
### C. Background Tasks (Cron/Rake)
|
|
148
151
|
|
|
149
152
|
For Rake tasks or Cron jobs (where no HTTP request exists), use `ExisRay::TaskMonitor`. It generates a fresh `Root ID`.
|
|
150
153
|
|
|
@@ -152,14 +155,13 @@ For Rake tasks or Cron jobs (where no HTTP request exists), use `ExisRay::TaskMo
|
|
|
152
155
|
|
|
153
156
|
```ruby
|
|
154
157
|
task generate_invoices: :environment do
|
|
155
|
-
ExisRay::TaskMonitor.run(
|
|
156
|
-
# Logs are tagged: [Root=1-65a...bc] [ExisRay] Starting task...
|
|
158
|
+
ExisRay::TaskMonitor.run("billing:generate_invoices") do
|
|
157
159
|
InvoiceService.process_all
|
|
158
160
|
end
|
|
159
161
|
end
|
|
160
162
|
```
|
|
161
163
|
|
|
162
|
-
###
|
|
164
|
+
### D. HTTP Clients
|
|
163
165
|
|
|
164
166
|
ExisRay ensures traceability across microservices.
|
|
165
167
|
|
|
@@ -172,7 +174,7 @@ If `ActiveResource` is detected, ExisRay automatically patches it. All outgoing
|
|
|
172
174
|
For Faraday, you must explicitly add the middleware:
|
|
173
175
|
|
|
174
176
|
```ruby
|
|
175
|
-
conn = Faraday.new(url:
|
|
177
|
+
conn = Faraday.new(url: "[https://api.internal](https://api.internal)") do |f|
|
|
176
178
|
f.use ExisRay::FaradayMiddleware
|
|
177
179
|
f.adapter Faraday.default_adapter
|
|
178
180
|
end
|
|
@@ -180,11 +182,74 @@ end
|
|
|
180
182
|
|
|
181
183
|
---
|
|
182
184
|
|
|
185
|
+
## 📋 Advanced Logging Guide
|
|
186
|
+
|
|
187
|
+
ExisRay's `JsonFormatter` is designed to be highly extensible. Here is how you can get the most out of your observability stack.
|
|
188
|
+
|
|
189
|
+
### 1. Environment Best Practices
|
|
190
|
+
|
|
191
|
+
For the best developer experience, we recommend using standard text logs in development and structured JSON logs in production.
|
|
192
|
+
|
|
193
|
+
**File:** `config/environments/production.rb`
|
|
194
|
+
```ruby
|
|
195
|
+
Rails.application.configure do
|
|
196
|
+
# Force Rails to log to STDOUT so Docker/Swarm can collect the JSON output
|
|
197
|
+
if ENV["RAILS_LOG_TO_STDOUT"].present?
|
|
198
|
+
logger = ActiveSupport::Logger.new(STDOUT)
|
|
199
|
+
logger.formatter = config.log_formatter
|
|
200
|
+
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Set an appropriate log level to avoid disk/network saturation
|
|
204
|
+
config.log_level = :info
|
|
205
|
+
end
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 2. Extending JSON with Rails Tags (`config.log_tags`)
|
|
209
|
+
|
|
210
|
+
If you are using native Rails tags, ExisRay will automatically capture them and group them into a `"tags"` array within your JSON log. This prevents the JSON structure from breaking.
|
|
211
|
+
|
|
212
|
+
**File:** `config/environments/production.rb`
|
|
213
|
+
```ruby
|
|
214
|
+
# Add custom tags to your HTTP requests
|
|
215
|
+
config.log_tags = [
|
|
216
|
+
:uuid,
|
|
217
|
+
->(request) { request.headers["X-Custom-Header"] }
|
|
218
|
+
]
|
|
219
|
+
```
|
|
220
|
+
**Output:**
|
|
221
|
+
```json
|
|
222
|
+
{"time":"2026-03-12T14:30:00Z","service":"App-HTTP","tags":["abcd-1234-uuid","CustomValue"],"method":"GET","status":200}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 3. Extending JSON with Custom Properties (Lograge)
|
|
226
|
+
|
|
227
|
+
If you prefer to inject key-value pairs directly into the root of the JSON (which is highly recommended for querying in Datadog, Kibana, etc.), you can leverage Lograge's `custom_options` in your host application.
|
|
228
|
+
|
|
229
|
+
ExisRay will flawlessly merge these attributes with the core Trace ID and Business Context.
|
|
230
|
+
|
|
231
|
+
**File:** `config/environments/production.rb`
|
|
232
|
+
```ruby
|
|
233
|
+
config.lograge.custom_options = lambda do |event|
|
|
234
|
+
{
|
|
235
|
+
ip_address: event.payload[:ip],
|
|
236
|
+
browser: event.payload[:user_agent]
|
|
237
|
+
}
|
|
238
|
+
end
|
|
239
|
+
```
|
|
240
|
+
**Output:**
|
|
241
|
+
```json
|
|
242
|
+
{"time":"2026-03-12T14:30:00Z","service":"App-HTTP","root_id":"Root=1-65a...","method":"GET","ip_address":"192.168.1.1","browser":"Chrome","status":200}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
183
247
|
## 🏗 Architecture
|
|
184
248
|
|
|
185
249
|
* **`ExisRay::Tracer`**: The infrastructure layer. Handles AWS X-Ray format parsing and ID generation.
|
|
186
250
|
* **`ExisRay::Current`**: The business layer. Manages domain identity (`User`, `ISP`).
|
|
187
251
|
* **`ExisRay::Reporter`**: The observability layer. Bridges the gap between your app and Sentry.
|
|
252
|
+
* **`ExisRay::JsonFormatter`**: The central logging engine. Intercepts HTTP, Sidekiq, and Tasks to output clean JSON.
|
|
188
253
|
* **`ExisRay::TaskMonitor`**: The entry point for non-HTTP processes.
|
|
189
254
|
|
|
190
255
|
## License
|
|
@@ -25,12 +25,26 @@ module ExisRay
|
|
|
25
25
|
# @example 'Current'
|
|
26
26
|
attr_accessor :current_class
|
|
27
27
|
|
|
28
|
+
# @!attribute [rw] log_format
|
|
29
|
+
# @return [Symbol] El formato en el que se emitirán los logs de la aplicación.
|
|
30
|
+
# Puede ser `:text` (comportamiento por defecto de Rails) o `:json` (formato estructurado).
|
|
31
|
+
# @example :json
|
|
32
|
+
attr_accessor :log_format
|
|
33
|
+
|
|
28
34
|
# Inicializa la configuración con valores por defecto compatibles con AWS X-Ray.
|
|
29
35
|
def initialize
|
|
30
36
|
@trace_header = 'HTTP_X_AMZN_TRACE_ID'
|
|
31
37
|
@propagation_trace_header = 'X-Amzn-Trace-Id'
|
|
32
38
|
@reporter_class = 'Reporter'
|
|
33
39
|
@current_class = 'Current'
|
|
40
|
+
@log_format = :text
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Indica si la aplicación está configurada para emitir logs en formato estructurado (JSON).
|
|
44
|
+
#
|
|
45
|
+
# @return [Boolean] `true` si `log_format` es `:json`, `false` en caso contrario.
|
|
46
|
+
def json_logs?
|
|
47
|
+
@log_format == :json
|
|
34
48
|
end
|
|
35
49
|
end
|
|
36
50
|
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "logger"
|
|
4
|
+
require "json"
|
|
5
|
+
require "active_support/tagged_logging"
|
|
6
|
+
|
|
7
|
+
module ExisRay
|
|
8
|
+
# Formateador global que intercepta todos los logs de la aplicación y los emite en formato JSON.
|
|
9
|
+
#
|
|
10
|
+
# Esta clase hereda de `Logger::Formatter` y tiene la responsabilidad unificada
|
|
11
|
+
# de estandarizar la salida para peticiones HTTP (procesadas previamente vía Lograge),
|
|
12
|
+
# trabajos en segundo plano (Sidekiq), tareas programadas (Rake/Cron) y cualquier
|
|
13
|
+
# mensaje arbitrario enviado explícitamente a `Rails.logger`.
|
|
14
|
+
#
|
|
15
|
+
# Automáticamente inyecta el contexto de trazabilidad ({ExisRay::Tracer})
|
|
16
|
+
# y el contexto de negocio ({ExisRay::Current}) en cada línea de log.
|
|
17
|
+
class JsonFormatter < ::Logger::Formatter
|
|
18
|
+
# Solución al NoMethodError: Garantiza que el formateador sea compatible
|
|
19
|
+
# con el wrapper de ActiveSupport::TaggedLogging de Rails.
|
|
20
|
+
include ActiveSupport::TaggedLogging::Formatter if defined?(ActiveSupport::TaggedLogging::Formatter)
|
|
21
|
+
|
|
22
|
+
# Procesa un mensaje de log y lo formatea como una cadena estructurada en JSON.
|
|
23
|
+
#
|
|
24
|
+
# @param severity [String] El nivel de severidad del log (ej. "INFO", "ERROR", "DEBUG").
|
|
25
|
+
# @param timestamp [Time] La marca de tiempo en la que se generó el log.
|
|
26
|
+
# @param _progname [String, nil] El nombre del programa o aplicación (ignorado aquí).
|
|
27
|
+
# @param msg [String, Hash, Object] El mensaje a registrar. Puede ser un Hash (inyectado por Lograge) o un String.
|
|
28
|
+
# @return [String] Una cadena en formato JSON terminada con un salto de línea (\n).
|
|
29
|
+
def call(severity, timestamp, _progname, msg)
|
|
30
|
+
payload = {
|
|
31
|
+
time: timestamp.utc.iso8601,
|
|
32
|
+
level: severity,
|
|
33
|
+
service: ExisRay::Tracer.service_name
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
inject_tracer_context(payload)
|
|
37
|
+
inject_business_context(payload)
|
|
38
|
+
inject_current_tags(payload)
|
|
39
|
+
process_message(payload, msg)
|
|
40
|
+
|
|
41
|
+
# Compactamos para eliminar claves con valores nulos (nil) y generamos el JSON
|
|
42
|
+
"#{payload.compact.to_json}\n"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Inyecta los identificadores de trazabilidad distribuida en el payload.
|
|
48
|
+
#
|
|
49
|
+
# @param payload [Hash] El diccionario del log donde se insertarán los datos.
|
|
50
|
+
# @return [void]
|
|
51
|
+
def inject_tracer_context(payload)
|
|
52
|
+
return unless ExisRay::Tracer.root_id
|
|
53
|
+
|
|
54
|
+
payload[:root_id] = ExisRay::Tracer.root_id
|
|
55
|
+
payload[:trace_id] = ExisRay::Tracer.trace_id if ExisRay::Tracer.trace_id
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Inyecta el contexto de negocio (ID de usuario, ISP, ID de correlación) en el payload.
|
|
59
|
+
#
|
|
60
|
+
# @param payload [Hash] El diccionario del log donde se insertarán los datos.
|
|
61
|
+
# @return [void]
|
|
62
|
+
def inject_business_context(payload)
|
|
63
|
+
curr = ExisRay.current_class
|
|
64
|
+
return unless curr
|
|
65
|
+
|
|
66
|
+
payload[:user_id] = curr.user_id if curr.respond_to?(:user_id) && curr.user_id
|
|
67
|
+
payload[:isp_id] = curr.isp_id if curr.respond_to?(:isp_id) && curr.isp_id
|
|
68
|
+
|
|
69
|
+
if curr.respond_to?(:correlation_id) && curr.correlation_id
|
|
70
|
+
payload[:correlation_id] = curr.correlation_id
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Inyecta cualquier etiqueta nativa (tags) de Rails que esté presente en el hilo actual.
|
|
75
|
+
#
|
|
76
|
+
# @param payload [Hash] El diccionario base del log.
|
|
77
|
+
# @return [void]
|
|
78
|
+
def inject_current_tags(payload)
|
|
79
|
+
if respond_to?(:current_tags) && current_tags.any?
|
|
80
|
+
payload[:tags] = current_tags
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Procesa el cuerpo del mensaje recibido y lo fusiona con el payload.
|
|
85
|
+
#
|
|
86
|
+
# Si el mensaje es un `Hash` (como el que nos pasará Lograge para peticiones HTTP),
|
|
87
|
+
# se hace un merge directo. Si es texto plano u otro objeto, se asigna a la clave `:message`.
|
|
88
|
+
#
|
|
89
|
+
# @param payload [Hash] El diccionario base del log.
|
|
90
|
+
# @param msg [String, Hash, Object] El mensaje original recibido por el logger.
|
|
91
|
+
# @return [void]
|
|
92
|
+
def process_message(payload, msg)
|
|
93
|
+
if msg.is_a?(Hash)
|
|
94
|
+
payload.merge!(msg)
|
|
95
|
+
else
|
|
96
|
+
payload[:message] = msg.to_s
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
data/lib/exis_ray/railtie.rb
CHANGED
|
@@ -1,43 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/railtie"
|
|
4
|
+
require "lograge" # Requerido globalmente para que su propio Railtie se registre en el boot
|
|
2
5
|
|
|
3
6
|
module ExisRay
|
|
4
|
-
# Integración automática con Rails.
|
|
5
|
-
#
|
|
7
|
+
# Integración automática de la gema con el ecosistema de Ruby on Rails.
|
|
8
|
+
#
|
|
9
|
+
# Se encarga de inyectar middlewares, configurar la estrategia de logging
|
|
10
|
+
# (texto plano o JSON estructurado) e instrumentar dependencias externas
|
|
11
|
+
# como Sidekiq y ActiveResource durante la fase de inicialización (`boot`) de la app.
|
|
6
12
|
class Railtie < ::Rails::Railtie
|
|
7
13
|
# 1. Middleware HTTP
|
|
14
|
+
# Intercepta las peticiones entrantes para hidratar el Tracer.
|
|
8
15
|
initializer "exis_ray.configure_middleware" do |app|
|
|
9
|
-
require
|
|
16
|
+
require "exis_ray/http_middleware"
|
|
10
17
|
app.middleware.insert_after ActionDispatch::RequestId, ExisRay::HttpMiddleware
|
|
11
18
|
end
|
|
12
19
|
|
|
13
|
-
# 2.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
# 2. Configuración de Estrategia de Logging (Lograge y Tags)
|
|
21
|
+
# CLAVE: Usamos `after: :load_config_initializers` para garantizar que la app
|
|
22
|
+
# ya haya leído `config/initializers/exis_ray.rb` antes de tomar esta decisión.
|
|
23
|
+
initializer "exis_ray.configure_logging", after: :load_config_initializers do |app|
|
|
24
|
+
if ExisRay.configuration.json_logs?
|
|
25
|
+
app.config.lograge.enabled = true
|
|
26
|
+
app.config.lograge.formatter = Lograge::Formatters::Raw.new
|
|
27
|
+
else
|
|
28
|
+
# Comportamiento legacy: Text Plain Tags
|
|
29
|
+
app.config.log_tags ||= []
|
|
30
|
+
app.config.log_tags << proc do
|
|
31
|
+
ExisRay::Tracer.trace_id.presence || ExisRay::Tracer.root_id.presence
|
|
23
32
|
end
|
|
24
|
-
|
|
33
|
+
end
|
|
25
34
|
end
|
|
26
35
|
|
|
27
|
-
# 3. Integraciones Post-Boot
|
|
36
|
+
# 3. Integraciones Post-Boot y Forzado de Formateadores
|
|
37
|
+
# Se ejecuta una vez que las gemas y el entorno de Rails están completamente cargados.
|
|
28
38
|
config.after_initialize do
|
|
29
|
-
#
|
|
39
|
+
# Aplicamos el formateador JSON globalmente al logger ya instanciado de Rails
|
|
40
|
+
if ExisRay.configuration.json_logs? && Rails.logger
|
|
41
|
+
Rails.logger.formatter = ExisRay::JsonFormatter.new
|
|
42
|
+
Rails.logger.info({ message: "[ExisRay] JSON Logging unificado activado." })
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# --- Instrumentación de ActiveResource ---
|
|
30
46
|
if defined?(ActiveResource::Base)
|
|
31
|
-
require
|
|
47
|
+
require "exis_ray/active_resource_instrumentation"
|
|
32
48
|
ActiveResource::Base.send(:prepend, ExisRay::ActiveResourceInstrumentation)
|
|
33
|
-
|
|
49
|
+
|
|
50
|
+
log_message(
|
|
51
|
+
text: "[ExisRay] ActiveResource instrumentado.",
|
|
52
|
+
json: { message: "[ExisRay] ActiveResource instrumentado." }
|
|
53
|
+
)
|
|
34
54
|
end
|
|
35
55
|
|
|
36
|
-
# Sidekiq
|
|
37
|
-
# Usamos ::Sidekiq para referirnos a la Gema Global y no al módulo local ExisRay::Sidekiq
|
|
56
|
+
# --- Instrumentación de Sidekiq ---
|
|
38
57
|
if defined?(::Sidekiq)
|
|
39
|
-
require
|
|
40
|
-
require
|
|
58
|
+
require "exis_ray/sidekiq/client_middleware"
|
|
59
|
+
require "exis_ray/sidekiq/server_middleware"
|
|
41
60
|
|
|
42
61
|
::Sidekiq.configure_client do |config|
|
|
43
62
|
config.client_middleware do |chain|
|
|
@@ -53,7 +72,27 @@ module ExisRay
|
|
|
53
72
|
chain.prepend ExisRay::Sidekiq::ServerMiddleware
|
|
54
73
|
end
|
|
55
74
|
end
|
|
56
|
-
|
|
75
|
+
|
|
76
|
+
# Sidekiq maneja su propio logger. Lo forzamos a usar nuestra estructura JSON.
|
|
77
|
+
if ExisRay.configuration.json_logs? && ::Sidekiq.logger
|
|
78
|
+
::Sidekiq.logger.formatter = ExisRay::JsonFormatter.new
|
|
79
|
+
Rails.logger.info({ message: "[ExisRay] Sidekiq Middleware y JsonFormatter integrados." })
|
|
80
|
+
else
|
|
81
|
+
Rails.logger.info "[ExisRay] Sidekiq Middleware integrado."
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Helper interno para imprimir logs de inicialización respetando el formato elegido.
|
|
87
|
+
#
|
|
88
|
+
# @param text [String] El mensaje para el formato texto.
|
|
89
|
+
# @param json [Hash] El payload para el formato JSON.
|
|
90
|
+
# @return [void]
|
|
91
|
+
def self.log_message(text:, json:)
|
|
92
|
+
if ExisRay.configuration.json_logs?
|
|
93
|
+
Rails.logger.info(json)
|
|
94
|
+
else
|
|
95
|
+
Rails.logger.info(text)
|
|
57
96
|
end
|
|
58
97
|
end
|
|
59
98
|
end
|
|
@@ -1,102 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ExisRay
|
|
2
4
|
module Sidekiq
|
|
3
5
|
# Middleware de Servidor para Sidekiq.
|
|
4
|
-
# Se ejecuta alrededor de cada trabajo (job) procesado por un Worker.
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# Se ejecuta envolviendo cada trabajo (job) procesado por un Worker.
|
|
8
|
+
#
|
|
9
|
+
# Responsabilidades:
|
|
10
|
+
# 1. Recuperar el Trace ID y contexto de negocio (User, ISP) inyectados por el cliente.
|
|
11
|
+
# 2. Hidratar el entorno local (Tracer, Current, Reporter).
|
|
12
|
+
# 3. Limpiar absolutamente todo al finalizar para no contaminar el Thread Pool de Sidekiq.
|
|
10
13
|
class ServerMiddleware
|
|
11
|
-
# Intercepta la ejecución del job.
|
|
14
|
+
# Intercepta la ejecución del job en el servidor Sidekiq.
|
|
12
15
|
#
|
|
13
16
|
# @param worker [Object] La instancia del worker que procesará el job.
|
|
14
|
-
# @param job [Hash] El payload del trabajo (contiene argumentos y metadatos).
|
|
15
|
-
# @param
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
# @param job [Hash] El payload del trabajo (contiene argumentos y metadatos inyectados).
|
|
18
|
+
# @param _queue [String] El nombre de la cola (ignorado).
|
|
19
|
+
# @yield Ejecuta el bloque que procesa el job real.
|
|
20
|
+
# @return [void]
|
|
21
|
+
def call(worker, job, _queue)
|
|
18
22
|
hydrate_tracer(worker, job)
|
|
19
|
-
|
|
20
|
-
# 2. Hidratación de Negocio (Current Class configurada)
|
|
21
23
|
hydrate_current(job)
|
|
22
|
-
|
|
23
|
-
# 3. Configuración de Reporte (Sentry/Reporter Class configurada)
|
|
24
24
|
setup_reporter(worker)
|
|
25
25
|
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if Rails.logger.respond_to?(:tagged)
|
|
31
|
-
Rails.logger.tagged(*tags) { yield }
|
|
26
|
+
# Ejecución adaptativa de logs
|
|
27
|
+
if !ExisRay.configuration.json_logs? && Rails.logger.respond_to?(:tagged)
|
|
28
|
+
Rails.logger.tagged(ExisRay::Tracer.root_id) { yield }
|
|
32
29
|
else
|
|
33
30
|
yield
|
|
34
31
|
end
|
|
35
|
-
|
|
36
32
|
ensure
|
|
37
|
-
#
|
|
38
|
-
# Sidekiq reutiliza threads. Si no limpiamos, el contexto de un job
|
|
39
|
-
# (ej: usuario actual) podría filtrarse al siguiente job.
|
|
33
|
+
# Limpieza vital en Sidekiq para evitar fugas de contexto entre jobs en el mismo hilo.
|
|
40
34
|
ExisRay::Tracer.reset
|
|
41
|
-
|
|
42
|
-
# Limpieza usando los helpers centralizados (sin hardcodear Current)
|
|
43
35
|
ExisRay.current_class&.reset if ExisRay.current_class.respond_to?(:reset)
|
|
44
36
|
ExisRay.reporter_class&.reset if ExisRay.reporter_class.respond_to?(:reset)
|
|
45
37
|
end
|
|
46
38
|
|
|
47
39
|
private
|
|
48
40
|
|
|
49
|
-
# Configura el Tracer con el ID recibido o genera uno nuevo.
|
|
41
|
+
# Configura el Tracer con el ID recibido en el payload o genera uno nuevo si no existe.
|
|
42
|
+
#
|
|
43
|
+
# @param worker [Object] Instancia del worker.
|
|
44
|
+
# @param job [Hash] Payload de Sidekiq.
|
|
45
|
+
# @return [void]
|
|
50
46
|
def hydrate_tracer(worker, job)
|
|
51
47
|
ExisRay::Tracer.created_at = Time.now.utc.to_f
|
|
52
48
|
ExisRay::Tracer.service_name = "Sidekiq-#{worker.class.name}"
|
|
53
49
|
|
|
54
|
-
if job[
|
|
55
|
-
# Continuidad: Usamos la traza
|
|
56
|
-
ExisRay::Tracer.trace_id = job[
|
|
50
|
+
if job["exis_ray_trace"]
|
|
51
|
+
# Continuidad: Usamos la traza propagada desde el cliente (Web/Cron)
|
|
52
|
+
ExisRay::Tracer.trace_id = job["exis_ray_trace"]
|
|
57
53
|
ExisRay::Tracer.parse_trace_id
|
|
58
54
|
else
|
|
59
|
-
# Origen: El job nació aquí
|
|
55
|
+
# Origen: El job nació directamente aquí sin contexto previo
|
|
60
56
|
ExisRay::Tracer.root_id = ExisRay::Tracer.send(:generate_new_root)
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
|
|
64
|
-
# Hidrata la clase Current configurada con los datos del payload.
|
|
60
|
+
# Hidrata la clase Current configurada con los datos de negocio del payload.
|
|
61
|
+
#
|
|
62
|
+
# @param job [Hash] Payload de Sidekiq.
|
|
63
|
+
# @return [void]
|
|
65
64
|
def hydrate_current(job)
|
|
66
|
-
# Obtenemos la clase dinámica (ej: Current)
|
|
67
65
|
klass = ExisRay.current_class
|
|
66
|
+
return unless klass && job["exis_ray_context"]
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
return unless klass && job['exis_ray_context']
|
|
71
|
-
|
|
72
|
-
ctx = job['exis_ray_context']
|
|
68
|
+
ctx = job["exis_ray_context"]
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
klass.
|
|
76
|
-
klass.isp_id = ctx['isp_id'] if ctx['isp_id'] && klass.respond_to?(:isp_id=)
|
|
70
|
+
klass.user_id = ctx["user_id"] if ctx["user_id"] && klass.respond_to?(:user_id=)
|
|
71
|
+
klass.isp_id = ctx["isp_id"] if ctx["isp_id"] && klass.respond_to?(:isp_id=)
|
|
77
72
|
|
|
78
|
-
if ctx[
|
|
79
|
-
klass.correlation_id = ctx[
|
|
73
|
+
if ctx["correlation_id"] && klass.respond_to?(:correlation_id=)
|
|
74
|
+
klass.correlation_id = ctx["correlation_id"]
|
|
80
75
|
end
|
|
81
76
|
end
|
|
82
77
|
|
|
83
|
-
# Configura
|
|
78
|
+
# Configura etiquetas y nombres de transacción en el Reporter (Sentry).
|
|
79
|
+
#
|
|
80
|
+
# @param worker [Object] Instancia del worker.
|
|
81
|
+
# @return [void]
|
|
84
82
|
def setup_reporter(worker)
|
|
85
83
|
klass = ExisRay.reporter_class
|
|
86
84
|
return unless klass
|
|
87
85
|
|
|
88
|
-
# Nombre de transacción para Sentry: "Sidekiq/HardWorker"
|
|
89
86
|
if klass.respond_to?(:transaction_name=)
|
|
90
87
|
klass.transaction_name = "Sidekiq/#{worker.class.name}"
|
|
91
88
|
end
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
end
|
|
90
|
+
return unless klass.respond_to?(:add_tags)
|
|
91
|
+
|
|
92
|
+
klass.add_tags(
|
|
93
|
+
sidekiq_queue: worker.class.get_sidekiq_options["queue"],
|
|
94
|
+
retry_count: worker.respond_to?(:retry_count) ? worker.retry_count : 0
|
|
95
|
+
)
|
|
100
96
|
end
|
|
101
97
|
end
|
|
102
98
|
end
|
|
@@ -1,44 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ExisRay
|
|
2
|
-
# Wrapper para monitorear tareas en segundo plano (Rake/Cron).
|
|
4
|
+
# Wrapper para monitorear tareas en segundo plano (Rake/Cron) o scripts aislados.
|
|
5
|
+
#
|
|
6
|
+
# Esta clase inicializa un contexto de trazabilidad simulado (ya que no hay
|
|
7
|
+
# una petición HTTP entrante) generando un nuevo `Root ID`. Luego, configura
|
|
8
|
+
# el reporte de errores y el contexto global antes de ejecutar el bloque provisto.
|
|
3
9
|
module TaskMonitor
|
|
4
|
-
# Ejecuta un bloque dentro de un contexto monitoreado.
|
|
5
|
-
#
|
|
10
|
+
# Ejecuta un bloque de código dentro de un contexto monitoreado por ExisRay.
|
|
11
|
+
#
|
|
12
|
+
# @param task_name [String, Symbol] Nombre identificador de la tarea (ej: "billing:generate").
|
|
13
|
+
# @yield El bloque de código que representa la lógica de la tarea.
|
|
14
|
+
# @raise [StandardError] Re-lanza cualquier excepción ocurrida tras registrarla.
|
|
15
|
+
# @return [void]
|
|
6
16
|
def self.run(task_name)
|
|
7
17
|
setup_tracer(task_name)
|
|
8
18
|
|
|
9
|
-
short_name = task_name.to_s.split(
|
|
19
|
+
short_name = task_name.to_s.split(":").last
|
|
10
20
|
|
|
11
|
-
# Configurar Reporter
|
|
21
|
+
# Configurar Reporter (Sentry u otro)
|
|
12
22
|
if (rep = ExisRay.reporter_class) && rep.respond_to?(:transaction_name=)
|
|
13
23
|
rep.transaction_name = short_name
|
|
14
24
|
rep.add_tags(service: :cron, task: short_name) if rep.respond_to?(:add_tags)
|
|
15
25
|
end
|
|
16
26
|
|
|
17
|
-
# Configurar Current
|
|
27
|
+
# Configurar Current Attributes
|
|
18
28
|
if (curr = ExisRay.current_class) && curr.respond_to?(:correlation_id=)
|
|
19
29
|
curr.correlation_id = ExisRay::Tracer.correlation_id
|
|
20
30
|
end
|
|
21
31
|
|
|
22
|
-
#
|
|
23
|
-
tags = [ExisRay::Tracer.root_id]
|
|
24
|
-
Rails.logger.tagged(*tags) do
|
|
25
|
-
Rails.logger.info "[ExisRay] Iniciando tarea: #{task_name}"
|
|
26
|
-
yield
|
|
27
|
-
Rails.logger.info "[ExisRay] Finalizada con éxito."
|
|
28
|
-
end
|
|
32
|
+
log_event(:info, "Iniciando tarea: #{task_name}", task: task_name, status: "started")
|
|
29
33
|
|
|
34
|
+
# Bloque de ejecución con o sin tags dependiendo de la configuración
|
|
35
|
+
execute_with_optional_tags { yield }
|
|
36
|
+
|
|
37
|
+
log_event(:info, "Finalizada con éxito.", task: task_name, status: "success")
|
|
30
38
|
rescue StandardError => e
|
|
31
|
-
|
|
39
|
+
log_event(:error, "Falló la tarea #{task_name}: #{e.message}", task: task_name, status: "failed", error: e.message)
|
|
32
40
|
raise e
|
|
33
41
|
ensure
|
|
34
|
-
# Limpieza centralizada
|
|
42
|
+
# Limpieza centralizada obligatoria para evitar filtraciones de memoria o contexto
|
|
35
43
|
ExisRay::Tracer.reset
|
|
36
44
|
ExisRay.current_class&.reset if ExisRay.current_class.respond_to?(:reset)
|
|
37
45
|
ExisRay.reporter_class&.reset if ExisRay.reporter_class.respond_to?(:reset)
|
|
38
46
|
end
|
|
39
47
|
|
|
48
|
+
# --- Métodos Privados ---
|
|
49
|
+
|
|
50
|
+
# Inicializa el Tracer con datos específicos de la tarea y el entorno.
|
|
51
|
+
#
|
|
52
|
+
# @param task_name [String, Symbol] El nombre de la tarea en ejecución.
|
|
53
|
+
# @return [void]
|
|
40
54
|
def self.setup_tracer(task_name)
|
|
41
|
-
ExisRay::Tracer.service_name = task_name.to_s.
|
|
55
|
+
ExisRay::Tracer.service_name = task_name.to_s.tr(":", "-").camelize
|
|
42
56
|
ExisRay::Tracer.request_id = SecureRandom.uuid
|
|
43
57
|
ExisRay::Tracer.created_at = Time.now.utc.to_f
|
|
44
58
|
|
|
@@ -46,10 +60,40 @@ module ExisRay
|
|
|
46
60
|
ExisRay::Tracer.root_id = ExisRay::Tracer.send(:generate_new_root, pod_id)
|
|
47
61
|
end
|
|
48
62
|
|
|
63
|
+
# Obtiene un identificador único del contenedor o máquina actual.
|
|
64
|
+
#
|
|
65
|
+
# @return [String] El sufijo del hostname o "local" por defecto.
|
|
49
66
|
def self.get_pod_identifier
|
|
50
|
-
(ENV[
|
|
67
|
+
(ENV["HOSTNAME"] || "local").split("-").last.to_s
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Ejecuta el bloque inyectando tags de Rails solo si estamos en modo texto.
|
|
71
|
+
# En modo JSON, JsonFormatter ya se encarga de inyectar el root_id.
|
|
72
|
+
#
|
|
73
|
+
# @yield El bloque de ejecución de la tarea.
|
|
74
|
+
# @return [void]
|
|
75
|
+
def self.execute_with_optional_tags
|
|
76
|
+
if !ExisRay.configuration.json_logs? && Rails.logger.respond_to?(:tagged)
|
|
77
|
+
Rails.logger.tagged(ExisRay::Tracer.root_id) { yield }
|
|
78
|
+
else
|
|
79
|
+
yield
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Envía un evento al logger de Rails adaptándose al formato configurado.
|
|
84
|
+
#
|
|
85
|
+
# @param level [Symbol] Nivel de severidad (:info, :error).
|
|
86
|
+
# @param message [String] Mensaje en texto plano para el modo clásico.
|
|
87
|
+
# @param payload [Hash] Datos estructurados para el modo JSON.
|
|
88
|
+
# @return [void]
|
|
89
|
+
def self.log_event(level, message, **payload)
|
|
90
|
+
if ExisRay.configuration.json_logs?
|
|
91
|
+
Rails.logger.send(level, payload.merge(message: "[ExisRay] #{message}"))
|
|
92
|
+
else
|
|
93
|
+
Rails.logger.send(level, "[ExisRay] #{message}")
|
|
94
|
+
end
|
|
51
95
|
end
|
|
52
96
|
|
|
53
|
-
private_class_method :get_pod_identifier, :setup_tracer
|
|
97
|
+
private_class_method :get_pod_identifier, :setup_tracer, :execute_with_optional_tags, :log_event
|
|
54
98
|
end
|
|
55
99
|
end
|
data/lib/exis_ray/version.rb
CHANGED
data/lib/exis_ray.rb
CHANGED
|
@@ -13,6 +13,7 @@ require "exis_ray/task_monitor"
|
|
|
13
13
|
require "exis_ray/http_middleware"
|
|
14
14
|
require "exis_ray/current"
|
|
15
15
|
require "exis_ray/reporter"
|
|
16
|
+
require "exis_ray/json_formatter"
|
|
16
17
|
|
|
17
18
|
# Integraciones Opcionales
|
|
18
19
|
# Solo cargamos el middleware de Faraday si la gema está presente en el sistema.
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: exis_ray
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gabriel Edera
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-03-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -38,6 +38,20 @@ dependencies:
|
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '6.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: lograge
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.11'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.11'
|
|
41
55
|
description: Gema que gestiona el contexto de request, logs y propagación de headers.
|
|
42
56
|
email:
|
|
43
57
|
- gab.edera@gmail.com
|
|
@@ -55,6 +69,7 @@ files:
|
|
|
55
69
|
- lib/exis_ray/current.rb
|
|
56
70
|
- lib/exis_ray/faraday_middleware.rb
|
|
57
71
|
- lib/exis_ray/http_middleware.rb
|
|
72
|
+
- lib/exis_ray/json_formatter.rb
|
|
58
73
|
- lib/exis_ray/railtie.rb
|
|
59
74
|
- lib/exis_ray/reporter.rb
|
|
60
75
|
- lib/exis_ray/sidekiq/client_middleware.rb
|