exis_ray 0.3.4 → 0.4.1
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 +40 -0
- data/README.md +24 -11
- data/lib/exis_ray/configuration.rb +8 -0
- data/lib/exis_ray/log_subscriber.rb +186 -0
- data/lib/exis_ray/railtie.rb +17 -25
- data/lib/exis_ray/reporter.rb +1 -1
- data/lib/exis_ray/task_monitor.rb +5 -9
- data/lib/exis_ray/version.rb +1 -1
- metadata +2 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb94b36fd16b408d5359621e78a03c722c89dab7c087322b67c975db743ad24e
|
|
4
|
+
data.tar.gz: ef093be07091568e6bad52d26de306dd82f91fc8e8f554d4eb04a7ca8c3b1581
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ce25522741b66f66318fa6d5223c0db754f1fe8f7eb1067a867f219988a1bc4ae78ef55c61e0895d553df955f129165af211a52dd41c86d6e3f6fe7066f7d7b2
|
|
7
|
+
data.tar.gz: 7ab403c8790dae80419260834d18787faa060bb2528d10974a4ef255bd6a0ea79c9aa837040015360db531b6114c8d99b4412c592d6749a0cba298ce24d072bc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
## [0.4.1] - 2026-03-23
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
- **Data-Driven Internal Logging:** Refactored internal library logs (boot, instrumentation, task status) from plain text messages to structured Key-Value (KV) strings.
|
|
5
|
+
- This leverages the `JsonFormatter`'s KV parser to elevate fields like `component`, `event`, and `status` to the JSON root, eliminating the need for unstructured `message` fields in infrastructure logs.
|
|
6
|
+
- Simplified `TaskMonitor#log_event` and `Railtie.log_boot` to emit raw KV strings directly to the logger.
|
|
7
|
+
- **Improved local debugging:** The `Reporter` now uses `exception.full_message` in non-production environments to provide a more readable backtrace in the development console.
|
|
8
|
+
|
|
9
|
+
## [0.4.0] - 2026-03-23
|
|
10
|
+
|
|
11
|
+
### Breaking Changes
|
|
12
|
+
- **Lograge removido como dependencia.** ExisRay ya no depende de Lograge para el logging estructurado de requests HTTP. Si tu app usaba `config.lograge.custom_options`, migrá al nuevo mecanismo de subclase (ver más abajo).
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **`ExisRay::LogSubscriber`:** Nuevo subscriber propio que reemplaza Lograge. Se suscribe a `process_action.action_controller` y emite un Hash estructurado directamente al logger, compatible con Rails 6, 7 y 8.
|
|
16
|
+
- Suprime `ActionController::LogSubscriber` y `ActionView::LogSubscriber` (Rails 3.0+, sin cambios en 6/7/8).
|
|
17
|
+
- Suprime `Rails::Rack::Logger` para eliminar las líneas "Started GET /..." (Rails 3.2+, firma `call_app(request, env)` desde Rails 5.0+).
|
|
18
|
+
- Usa `notifier.all_listeners_for` en Rails 7.1+ y `notifier.listeners_for` en Rails 6/7.0 para desuscribir los subscribers por defecto. Si `all_listeners_for` cambia en futuras versiones, revisar `ActiveSupport::Notifications::Fanout`.
|
|
19
|
+
- **`config.log_subscriber_class`:** Nueva opción de configuración para registrar una subclase de `ExisRay::LogSubscriber`. Permite inyectar campos extra en cada log de request HTTP sobreescribiendo `self.extra_fields(event)`. Si no se configura, se usa `ExisRay::LogSubscriber` directamente sin campos extra.
|
|
20
|
+
|
|
21
|
+
### Migration Guide
|
|
22
|
+
Si usabas `config.lograge.custom_options`, el equivalente es:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# Antes
|
|
26
|
+
config.lograge.custom_options = ->(event) { { user_id: Current.user_id } }
|
|
27
|
+
|
|
28
|
+
# Después — app/models/my_log_subscriber.rb
|
|
29
|
+
class MyLogSubscriber < ExisRay::LogSubscriber
|
|
30
|
+
def self.extra_fields(event)
|
|
31
|
+
{ user_id: Current.user_id }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# config/initializers/exis_ray.rb
|
|
36
|
+
ExisRay.configure do |config|
|
|
37
|
+
config.log_subscriber_class = "MyLogSubscriber"
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
|
|
1
41
|
## [0.3.4] - 2026-03-23
|
|
2
42
|
|
|
3
43
|
### Fixed
|
data/README.md
CHANGED
|
@@ -31,7 +31,7 @@ And then execute:
|
|
|
31
31
|
$ bundle install
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
*(Note: ExisRay
|
|
34
|
+
*(Note: ExisRay handles HTTP log condensation internally via `ExisRay::LogSubscriber`, compatible with Rails 6, 7 and 8. Lograge is no longer required).*
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
@@ -242,26 +242,38 @@ config.log_tags = [
|
|
|
242
242
|
{"time":"2026-03-12T14:30:00Z","service":"App-HTTP","tags":["abcd-1234-uuid","CustomValue"],"method":"GET","status":200}
|
|
243
243
|
```
|
|
244
244
|
|
|
245
|
-
### 3. Extending JSON with Custom
|
|
245
|
+
### 3. Extending JSON with Custom HTTP Fields
|
|
246
246
|
|
|
247
|
-
|
|
247
|
+
To inject extra fields into each HTTP request log, create a subclass of `ExisRay::LogSubscriber` and override `self.extra_fields`:
|
|
248
248
|
|
|
249
|
-
|
|
249
|
+
**File:** `app/models/my_log_subscriber.rb`
|
|
250
|
+
```ruby
|
|
251
|
+
class MyLogSubscriber < ExisRay::LogSubscriber
|
|
252
|
+
def self.extra_fields(event)
|
|
253
|
+
{
|
|
254
|
+
ip_address: event.payload[:ip],
|
|
255
|
+
user_agent: event.payload[:headers]["HTTP_USER_AGENT"]
|
|
256
|
+
}
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
```
|
|
250
260
|
|
|
251
|
-
|
|
261
|
+
Then register it in your initializer:
|
|
262
|
+
|
|
263
|
+
**File:** `config/initializers/exis_ray.rb`
|
|
252
264
|
```ruby
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
ip_address: event.payload[:ip],
|
|
256
|
-
browser: event.payload[:user_agent]
|
|
257
|
-
}
|
|
265
|
+
ExisRay.configure do |config|
|
|
266
|
+
config.log_subscriber_class = "MyLogSubscriber"
|
|
258
267
|
end
|
|
259
268
|
```
|
|
269
|
+
|
|
260
270
|
**Output:**
|
|
261
271
|
```json
|
|
262
|
-
{"time":"2026-03-12T14:30:00Z","service":"App-HTTP","root_id":"Root=1-65a...","method":"GET","ip_address":"192.168.1.1","
|
|
272
|
+
{"time":"2026-03-12T14:30:00Z","service":"App-HTTP","root_id":"Root=1-65a...","method":"GET","ip_address":"192.168.1.1","user_agent":"Chrome","status":200}
|
|
263
273
|
```
|
|
264
274
|
|
|
275
|
+
If you don't need extra fields, skip this step — `ExisRay::LogSubscriber` is used by default with no additional fields.
|
|
276
|
+
|
|
265
277
|
---
|
|
266
278
|
|
|
267
279
|
## 🏗 Architecture
|
|
@@ -271,6 +283,7 @@ end
|
|
|
271
283
|
* **`ExisRay::Reporter`**: The observability layer. Bridges the gap between your app and Sentry.
|
|
272
284
|
* **`ExisRay::JsonFormatter`**: The central logging engine. Intercepts HTTP, Sidekiq, and Tasks to output clean JSON.
|
|
273
285
|
* **KV String Parser:** It automatically detects if a log message (String) uses `key=value` format. If so, it parses the pairs and elevates them to the root of the JSON. For example, `Rails.logger.info "event=boot status=ok"` becomes `{"event":"boot","status":"ok",...}`. It supports quoted values with spaces: `message="something went wrong"`.
|
|
286
|
+
* **`ExisRay::LogSubscriber`**: Replaces Lograge for HTTP request logging. Subscribes to `process_action.action_controller` and suppresses Rails' default multi-line log subscribers. Compatible with Rails 6, 7, and 8. Subclass it and override `self.extra_fields(event)` to inject custom fields.
|
|
274
287
|
* **`ExisRay::TaskMonitor`**: The entry point for non-HTTP processes.
|
|
275
288
|
|
|
276
289
|
## License
|
|
@@ -31,6 +31,13 @@ module ExisRay
|
|
|
31
31
|
# @example :json
|
|
32
32
|
attr_accessor :log_format
|
|
33
33
|
|
|
34
|
+
# @!attribute [rw] log_subscriber_class
|
|
35
|
+
# @return [String, nil] Nombre de la subclase de ExisRay::LogSubscriber de la app host.
|
|
36
|
+
# Usada para inyectar campos extra en cada log de request HTTP via `extra_fields`.
|
|
37
|
+
# Si es nil, se usa ExisRay::LogSubscriber directamente (sin campos extra).
|
|
38
|
+
# @example 'MyLogSubscriber'
|
|
39
|
+
attr_accessor :log_subscriber_class
|
|
40
|
+
|
|
34
41
|
# Inicializa la configuración con valores por defecto compatibles con AWS X-Ray.
|
|
35
42
|
def initialize
|
|
36
43
|
@trace_header = 'HTTP_X_AMZN_TRACE_ID'
|
|
@@ -38,6 +45,7 @@ module ExisRay
|
|
|
38
45
|
@reporter_class = 'Reporter'
|
|
39
46
|
@current_class = 'Current'
|
|
40
47
|
@log_format = :text
|
|
48
|
+
@log_subscriber_class = nil
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
# Indica si la aplicación está configurada para emitir logs en formato estructurado (JSON).
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/log_subscriber"
|
|
4
|
+
|
|
5
|
+
module ExisRay
|
|
6
|
+
# Reemplaza Lograge para el logging estructurado de requests HTTP en Rails 6, 7 y 8.
|
|
7
|
+
#
|
|
8
|
+
# Se suscribe a `process_action.action_controller` y emite un Hash al logger,
|
|
9
|
+
# que JsonFormatter convierte a JSON. Suprime los log subscribers por defecto
|
|
10
|
+
# de Rails (ActionController, ActionView, Rails::Rack::Logger) para evitar
|
|
11
|
+
# líneas de log duplicadas o en formato texto.
|
|
12
|
+
#
|
|
13
|
+
# Para inyectar campos extra en cada log de request, heredá esta clase y
|
|
14
|
+
# sobreescribí `extra_fields`:
|
|
15
|
+
#
|
|
16
|
+
# class MyLogSubscriber < ExisRay::LogSubscriber
|
|
17
|
+
# def self.extra_fields(event)
|
|
18
|
+
# { user_agent: event.payload[:headers]["HTTP_USER_AGENT"] }
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# Luego configurá la subclase:
|
|
23
|
+
#
|
|
24
|
+
# ExisRay.configure do |config|
|
|
25
|
+
# config.log_subscriber_class = "MyLogSubscriber"
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
|
29
|
+
# Procesa el evento de finalización de un request HTTP y lo emite como Hash estructurado.
|
|
30
|
+
#
|
|
31
|
+
# @param event [ActiveSupport::Notifications::Event]
|
|
32
|
+
# @return [void]
|
|
33
|
+
def process_action(event)
|
|
34
|
+
payload = build_payload(event)
|
|
35
|
+
logger.info(payload)
|
|
36
|
+
rescue StandardError
|
|
37
|
+
# El logger nunca debe interrumpir el flujo del request.
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Hook para que las subclases inyecten campos extra en cada log de request.
|
|
41
|
+
# Por defecto retorna un Hash vacío.
|
|
42
|
+
#
|
|
43
|
+
# @param event [ActiveSupport::Notifications::Event]
|
|
44
|
+
# @return [Hash]
|
|
45
|
+
def self.extra_fields(_event)
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# --- Instalación y supresión de subscribers ---
|
|
50
|
+
|
|
51
|
+
# Activa el subscriber correcto (subclase configurada o ExisRay::LogSubscriber por defecto)
|
|
52
|
+
# y suprime los log subscribers por defecto de Rails.
|
|
53
|
+
#
|
|
54
|
+
# @return [void]
|
|
55
|
+
def self.install!
|
|
56
|
+
suppress_default_log_subscribers!
|
|
57
|
+
suppress_rack_logger!
|
|
58
|
+
subscriber_class.attach_to(:action_controller)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def build_payload(event)
|
|
64
|
+
payload = event.payload
|
|
65
|
+
status = payload[:status] || exception_status(payload[:exception])
|
|
66
|
+
|
|
67
|
+
data = {
|
|
68
|
+
method: payload[:method],
|
|
69
|
+
path: payload[:path],
|
|
70
|
+
format: payload[:format],
|
|
71
|
+
controller: payload[:controller],
|
|
72
|
+
action: payload[:action],
|
|
73
|
+
status: status,
|
|
74
|
+
duration: event.duration.round(2),
|
|
75
|
+
view: payload[:view_runtime]&.round(2),
|
|
76
|
+
db: payload[:db_runtime]&.round(2)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
data.merge!(self.class.extra_fields(event))
|
|
80
|
+
data.compact
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Infiere el status HTTP desde el nombre de la excepción cuando el request
|
|
84
|
+
# terminó con una excepción no rescatada (payload[:status] es nil).
|
|
85
|
+
#
|
|
86
|
+
# @param exception_info [Array(String, String), nil] [nombre_clase, mensaje]
|
|
87
|
+
# @return [Integer]
|
|
88
|
+
def exception_status(exception_info)
|
|
89
|
+
return 500 unless exception_info
|
|
90
|
+
|
|
91
|
+
exception_class_name = exception_info.first
|
|
92
|
+
# ActionDispatch::ExceptionWrapper disponible desde Rails 3.2+
|
|
93
|
+
ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
|
|
94
|
+
rescue StandardError
|
|
95
|
+
500
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Resuelve la clase a attachar: subclase configurada o ExisRay::LogSubscriber.
|
|
99
|
+
#
|
|
100
|
+
# @return [Class]
|
|
101
|
+
def self.subscriber_class
|
|
102
|
+
klass_name = ExisRay.configuration.log_subscriber_class
|
|
103
|
+
return self unless klass_name.present?
|
|
104
|
+
|
|
105
|
+
klass_name.safe_constantize || self
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Suprime ActionController::LogSubscriber y ActionView::LogSubscriber
|
|
109
|
+
# para evitar los logs multi-línea por defecto de Rails.
|
|
110
|
+
#
|
|
111
|
+
# Introducido en Rails 3.0. Presente sin cambios en Rails 6, 7 y 8.
|
|
112
|
+
#
|
|
113
|
+
# @return [void]
|
|
114
|
+
def self.suppress_default_log_subscribers!
|
|
115
|
+
require "action_controller/log_subscriber"
|
|
116
|
+
require "action_view/log_subscriber"
|
|
117
|
+
|
|
118
|
+
ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
|
|
119
|
+
case subscriber
|
|
120
|
+
when ActionController::LogSubscriber
|
|
121
|
+
unsubscribe_subscriber(:action_controller, subscriber)
|
|
122
|
+
when ActionView::LogSubscriber
|
|
123
|
+
unsubscribe_subscriber(:action_view, subscriber)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Suprime las líneas "Started GET /..." emitidas por Rails::Rack::Logger.
|
|
129
|
+
#
|
|
130
|
+
# Rails::Rack::Logger introducido en Rails 3.2. La firma de `call_app` recibe
|
|
131
|
+
# (request, env) desde Rails 5.0+. Compatible con Rails 6, 7 y 8.
|
|
132
|
+
#
|
|
133
|
+
# @return [void]
|
|
134
|
+
def self.suppress_rack_logger!
|
|
135
|
+
require "rails/rack/logger"
|
|
136
|
+
|
|
137
|
+
::Rails::Rack::Logger.class_eval do
|
|
138
|
+
def call_app(request, env) # rubocop:disable Lint/UnusedMethodArgument
|
|
139
|
+
status, headers, body = @app.call(env)
|
|
140
|
+
[status, headers, ::Rack::BodyProxy.new(body) {}]
|
|
141
|
+
ensure
|
|
142
|
+
ActiveSupport::LogSubscriber.flush_all!
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Desuscribe un subscriber de todas las notificaciones de un namespace.
|
|
148
|
+
#
|
|
149
|
+
# API de notificaciones:
|
|
150
|
+
# - Rails 6 / 7.0: `notifier.listeners_for(event_name)`
|
|
151
|
+
# - Rails 7.1+: `notifier.all_listeners_for(event_name)` (listeners_for fue deprecado)
|
|
152
|
+
# - Rails 8: solo `all_listeners_for`
|
|
153
|
+
#
|
|
154
|
+
# Si `all_listeners_for` desaparece en futuras versiones, revisar
|
|
155
|
+
# ActiveSupport::Notifications::Fanout para el API vigente.
|
|
156
|
+
#
|
|
157
|
+
# @param namespace [Symbol]
|
|
158
|
+
# @param subscriber [ActiveSupport::LogSubscriber]
|
|
159
|
+
# @return [void]
|
|
160
|
+
def self.unsubscribe_subscriber(namespace, subscriber)
|
|
161
|
+
events = subscriber.public_methods(false).reject { |m| m.to_s == "call" }
|
|
162
|
+
notifier = ActiveSupport::Notifications.notifier
|
|
163
|
+
|
|
164
|
+
events.each do |event|
|
|
165
|
+
event_name = "#{event}.#{namespace}"
|
|
166
|
+
listeners = if notifier.respond_to?(:all_listeners_for)
|
|
167
|
+
# Rails 7.1+ (introducido en 7.1.0)
|
|
168
|
+
notifier.all_listeners_for(event_name)
|
|
169
|
+
else
|
|
170
|
+
# Rails 6 / 7.0
|
|
171
|
+
notifier.listeners_for(event_name)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
listeners.each do |listener|
|
|
175
|
+
delegate = listener.instance_variable_get(:@delegate)
|
|
176
|
+
ActiveSupport::Notifications.unsubscribe(listener) if delegate == subscriber
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
private_class_method :suppress_default_log_subscribers!,
|
|
182
|
+
:suppress_rack_logger!,
|
|
183
|
+
:unsubscribe_subscriber,
|
|
184
|
+
:subscriber_class
|
|
185
|
+
end
|
|
186
|
+
end
|
data/lib/exis_ray/railtie.rb
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "rails/railtie"
|
|
4
|
-
require "lograge" # Requerido globalmente para que su propio Railtie se registre en el boot
|
|
5
4
|
|
|
6
5
|
module ExisRay
|
|
7
6
|
# Integración automática de la gema con el ecosistema de Ruby on Rails.
|
|
@@ -17,14 +16,11 @@ module ExisRay
|
|
|
17
16
|
app.middleware.insert_after ActionDispatch::RequestId, ExisRay::HttpMiddleware
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
# 2. Configuración de Estrategia de Logging
|
|
19
|
+
# 2. Configuración de Estrategia de Logging
|
|
21
20
|
# CLAVE: Usamos `after: :load_config_initializers` para garantizar que la app
|
|
22
21
|
# ya haya leído `config/initializers/exis_ray.rb` antes de tomar esta decisión.
|
|
23
22
|
initializer "exis_ray.configure_logging", after: :load_config_initializers do |app|
|
|
24
|
-
|
|
25
|
-
app.config.lograge.enabled = true
|
|
26
|
-
app.config.lograge.formatter = Lograge::Formatters::Raw.new
|
|
27
|
-
else
|
|
23
|
+
unless ExisRay.configuration.json_logs?
|
|
28
24
|
# Comportamiento legacy: Text Plain Tags
|
|
29
25
|
app.config.log_tags ||= []
|
|
30
26
|
app.config.log_tags << proc do
|
|
@@ -39,18 +35,20 @@ module ExisRay
|
|
|
39
35
|
# Aplicamos el formateador JSON globalmente al logger ya instanciado de Rails
|
|
40
36
|
if ExisRay.configuration.json_logs? && Rails.logger
|
|
41
37
|
Rails.logger.formatter = ExisRay::JsonFormatter.new
|
|
42
|
-
|
|
38
|
+
|
|
39
|
+
# Activamos nuestro LogSubscriber HTTP y suprimimos los de Rails por defecto.
|
|
40
|
+
# Reemplaza Lograge, compatible con Rails 6, 7 y 8.
|
|
41
|
+
require "exis_ray/log_subscriber"
|
|
42
|
+
ExisRay::LogSubscriber.install!
|
|
43
|
+
|
|
44
|
+
log_boot("component=exis_ray event=json_logging_enabled")
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
# --- Instrumentación de ActiveResource ---
|
|
46
48
|
if defined?(ActiveResource::Base)
|
|
47
49
|
require "exis_ray/active_resource_instrumentation"
|
|
48
50
|
ActiveResource::Base.send(:prepend, ExisRay::ActiveResourceInstrumentation)
|
|
49
|
-
|
|
50
|
-
log_message(
|
|
51
|
-
text: "[ExisRay] ActiveResource instrumentado.",
|
|
52
|
-
json: { message: "[ExisRay] ActiveResource instrumentado." }
|
|
53
|
-
)
|
|
51
|
+
log_boot("component=exis_ray event=active_resource_instrumented")
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
# --- Instrumentación de Sidekiq ---
|
|
@@ -73,27 +71,21 @@ module ExisRay
|
|
|
73
71
|
end
|
|
74
72
|
end
|
|
75
73
|
|
|
76
|
-
# Sidekiq maneja su propio logger. Lo forzamos a usar nuestra estructura JSON.
|
|
77
74
|
if ExisRay.configuration.json_logs? && ::Sidekiq.logger
|
|
78
75
|
::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
76
|
end
|
|
77
|
+
log_boot("component=exis_ray event=sidekiq_instrumented")
|
|
83
78
|
end
|
|
84
79
|
end
|
|
85
80
|
|
|
86
|
-
#
|
|
81
|
+
# Emite un log de boot en DEBUG con formato key=value.
|
|
82
|
+
# En modo texto es legible directamente. En modo JSON el JsonFormatter
|
|
83
|
+
# lo parsea y eleva cada campo al nivel raíz del JSON automáticamente.
|
|
87
84
|
#
|
|
88
|
-
# @param
|
|
89
|
-
# @param json [Hash] El payload para el formato JSON.
|
|
85
|
+
# @param message [String] String en formato key=value.
|
|
90
86
|
# @return [void]
|
|
91
|
-
def self.
|
|
92
|
-
|
|
93
|
-
Rails.logger.info(json)
|
|
94
|
-
else
|
|
95
|
-
Rails.logger.info(text)
|
|
96
|
-
end
|
|
87
|
+
def self.log_boot(message)
|
|
88
|
+
Rails.logger.debug(message)
|
|
97
89
|
end
|
|
98
90
|
end
|
|
99
91
|
end
|
data/lib/exis_ray/reporter.rb
CHANGED
|
@@ -32,7 +32,7 @@ module ExisRay
|
|
|
32
32
|
prepare_scope(context, tags, fingerprint, transaction_name)
|
|
33
33
|
add_tags(exception: excep.class.to_s)
|
|
34
34
|
|
|
35
|
-
Rails.logger.error(excep) unless Rails.env.production?
|
|
35
|
+
Rails.logger.error(excep.full_message) unless Rails.env.production?
|
|
36
36
|
|
|
37
37
|
if report_to_new_sentry?
|
|
38
38
|
exception_to_new_sentry(excep)
|
|
@@ -29,14 +29,14 @@ module ExisRay
|
|
|
29
29
|
curr.correlation_id = ExisRay::Tracer.correlation_id
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
log_event(:info, "
|
|
32
|
+
log_event(:info, "component=exis_ray event=task_started task=#{task_name} status=started")
|
|
33
33
|
|
|
34
34
|
# Bloque de ejecución con o sin tags dependiendo de la configuración
|
|
35
35
|
execute_with_optional_tags { yield }
|
|
36
36
|
|
|
37
|
-
log_event(:info, "
|
|
37
|
+
log_event(:info, "component=exis_ray event=task_finished task=#{task_name} status=success")
|
|
38
38
|
rescue StandardError => e
|
|
39
|
-
log_event(:error, "
|
|
39
|
+
log_event(:error, "component=exis_ray event=task_failed task=#{task_name} status=failed error=#{e.message.inspect}")
|
|
40
40
|
raise e
|
|
41
41
|
ensure
|
|
42
42
|
# Limpieza centralizada obligatoria para evitar filtraciones de memoria o contexto
|
|
@@ -89,12 +89,8 @@ module ExisRay
|
|
|
89
89
|
# @param message [String] Mensaje en texto plano para el modo clásico.
|
|
90
90
|
# @param payload [Hash] Datos estructurados para el modo JSON.
|
|
91
91
|
# @return [void]
|
|
92
|
-
def self.log_event(level, message
|
|
93
|
-
|
|
94
|
-
Rails.logger.send(level, payload.merge(message: "[ExisRay] #{message}"))
|
|
95
|
-
else
|
|
96
|
-
Rails.logger.send(level, "[ExisRay] #{message}")
|
|
97
|
-
end
|
|
92
|
+
def self.log_event(level, message)
|
|
93
|
+
Rails.logger.send(level, message)
|
|
98
94
|
rescue StandardError
|
|
99
95
|
# El logger nunca debe interrumpir el flujo principal de la tarea.
|
|
100
96
|
end
|
data/lib/exis_ray/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: exis_ray
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gabriel Edera
|
|
@@ -38,20 +38,6 @@ 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'
|
|
55
41
|
description: Gema que gestiona el contexto de request, logs y propagación de headers.
|
|
56
42
|
email:
|
|
57
43
|
- gab.edera@gmail.com
|
|
@@ -70,6 +56,7 @@ files:
|
|
|
70
56
|
- lib/exis_ray/faraday_middleware.rb
|
|
71
57
|
- lib/exis_ray/http_middleware.rb
|
|
72
58
|
- lib/exis_ray/json_formatter.rb
|
|
59
|
+
- lib/exis_ray/log_subscriber.rb
|
|
73
60
|
- lib/exis_ray/railtie.rb
|
|
74
61
|
- lib/exis_ray/reporter.rb
|
|
75
62
|
- lib/exis_ray/sidekiq/client_middleware.rb
|