exis_ray 0.10.0 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78d2b6cbc5e3da104fee7f3d2f481311acd2da7971d80295edf0bbad6eaab178
4
- data.tar.gz: c54ebfc75e0c5abf640506b97b41b4b86bfe1f05a8d17a2d484941dae0fb21d4
3
+ metadata.gz: e474f1122d88cba11551996f1fe73b01da92f28dcea658e6eb473e51277e838e
4
+ data.tar.gz: 708af8ed6b2ece0cf5e78f74543135ceb4e83d8e2e51788e980847c7675d586e
5
5
  SHA512:
6
- metadata.gz: e6642e744b2b9fc0d798e419664d76ebe2a0beba38722b1db09ac501d408938695990d4d752a0b0bf9cad78aa1a62a3939113e1444a623df890cabb8a4f0ad31
7
- data.tar.gz: e96e7936add04a739ac1f325d1b768437c82381f5252420f2ab0eb72d6ad51e50bc272c7b136e4f1c0096d59f50b4b9fdc227ec05086e374e385ad543d5d47e8
6
+ metadata.gz: 2e314e520ab390a510953c78c8774c816e30a9fd814e9bbd36eb2e874e5ed81abbaeb91a7f0abea350c46f4783f8f93c176209a08a15a4691de2c13551534135
7
+ data.tar.gz: 478cfe36c1b7f5e60c37de8c6db1e86c239a13a2ec2c8a3bd6797b455cc27dd0ed7f3960c02e29049e0979c648a7ab7857982d84664ae43647dfb2af5cb99f16
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.11.0] - 2026-05-26
2
+
3
+ ### Nuevas funcionalidades
4
+ - **`config.emit_legacy_exception_keys`** (#15): nuevo flag de `Configuration` (default `true`) que controla la emisión de las keys legacy `error_class`/`error_message` junto a `exception.type`/`exception.message`. Bajado a `false`, `ExisRay::LogSubscriber` (logs HTTP) y `ExisRay::TaskMonitor` (logs de tasks) emiten solo las keys OTel v1.0 (`exception.*`), reduciendo bytes y ruido downstream cuando los consumers (dashboards, alertas, queries) ya migraron. Mantiene `true` como default durante la ventana de transición — se flipea a `false` en v0.12.0 y se remueve el flag en v1.0 cuando los legacy se eliminen definitivamente.
5
+ - **`url.path` (OTel v1.0) + `config.emit_legacy_path_key`** (#15): `ExisRay::LogSubscriber` empieza a emitir `url.path` (nombre canónico OTel) en todos los logs HTTP. El alias legacy `path` se sigue emitiendo durante la ventana de transición y queda gateado por `config.emit_legacy_path_key` (default `true`). Cuando los consumers (queries, dashboards, alertas) hayan migrado a `url.path`, bajar el flag a `false` para suprimir el alias. Se flipea a `false` en v0.12.0 y se remueve el flag en v1.0.
6
+ - **Doc: `url.path` vs `http_route` no se deduplican** (#15): el caso reportado de "valores idénticos en endpoints estáticos" no es un bug — `url.path` es la URL **concreta** (alta cardinalidad), `http_route` es el **template** (baja cardinalidad). Cumplen roles distintos en dashboards/queries downstream; siguen emitiéndose siempre los dos. Documentado en `README.md` y `skill/SKILL.md` (subsección "Migración OTel — `path` → `url.path`" + nota explicativa de la coexistencia semántica).
7
+
1
8
  ## [0.10.0] - 2026-05-25
2
9
 
3
10
  ### Documentación
data/CLAUDE.md CHANGED
@@ -178,6 +178,7 @@ ExisRay.configure do |config|
178
178
  config.propagation_trace_header = 'X-Amzn-Trace-Id'
179
179
  config.current_class = 'Current'
180
180
  config.reporter_class = 'Reporter'
181
+ config.emit_legacy_exception_keys = true # default true; pasar a false cuando consumers usen exception.*
181
182
  end
182
183
 
183
184
  # BugBunny publisher — debe agregarse manualmente al cliente
data/README.md CHANGED
@@ -370,8 +370,9 @@ config.logger.formatter = ExisRay::JsonFormatter
370
370
  | `component` | String | Siempre `"exis_ray"` |
371
371
  | `event` | String | Siempre `"http_request"` |
372
372
  | `method` | String | Verbo HTTP |
373
- | `path` | String | URL concreta del request |
374
- | `http_route` | String | Template (ej: `/users/:id`). Baja cardinalidad para dashboards |
373
+ | `url.path` | String | URL concreta del request (OTel v1.0). Siempre presente |
374
+ | `path` | String | Alias legacy de `url.path`. Solo si `config.emit_legacy_path_key` (default `true`, deprecado) |
375
+ | `http_route` | String | Template (ej: `/users/:id`). Baja cardinalidad para dashboards. En endpoints sin params coincide en valor con `url.path` — la dupe es semánticamente esperada (concrete vs template) |
375
376
  | `format` | Symbol/String | `html`, `json`, etc. |
376
377
  | `controller` | String | Class name del controller |
377
378
  | `action` | String | Nombre del action |
@@ -382,11 +383,37 @@ config.logger.formatter = ExisRay::JsonFormatter
382
383
  | `db_runtime_s` | Float\|nil | Solo si ActiveRecord lo reporta |
383
384
  | `user_agent_original` | String | Header `User-Agent` |
384
385
  | `server_address` | String | Hostname sin puerto del header `Host` |
385
- | `error_class`, `error_message` | String | Solo en fallo (legacy) |
386
+ | `error_class`, `error_message` | String | Solo en fallo y si `config.emit_legacy_exception_keys` (default `true`, deprecadas) |
386
387
  | `exception.type`, `exception.message`, `exception.stacktrace` | String | Solo en fallo (OTel; stack limitado a 20 líneas) |
387
388
 
388
389
  Severity del log: `ERROR` si `http_status >= 500`, sino `INFO`.
389
390
 
391
+ ### Migración OTel — `error_class`/`error_message` → `exception.*`
392
+
393
+ Durante la ventana de transición OTel v1.0, `LogSubscriber` y `TaskMonitor` emiten ambos sets de keys en cada log de error. Cuando todos los consumers (dashboards, queries, alertas) hayan migrado a `exception.type`/`exception.message`/`exception.stacktrace`, desactivar los legacy:
394
+
395
+ ```ruby
396
+ ExisRay.configure do |c|
397
+ c.emit_legacy_exception_keys = false # default: true
398
+ end
399
+ ```
400
+
401
+ Roadmap: default `false` en v0.12.0; flag y legacy keys removidos en v1.0.
402
+
403
+ ### Migración OTel — `path` → `url.path`
404
+
405
+ `LogSubscriber` emite `url.path` (nombre OTel v1.0) en todos los logs HTTP. Durante la ventana de transición emite también `path` (alias legacy Wispro). Cuando las queries/dashboards/alertas migren a `url.path`, desactivar el legacy:
406
+
407
+ ```ruby
408
+ ExisRay.configure do |c|
409
+ c.emit_legacy_path_key = false # default: true
410
+ end
411
+ ```
412
+
413
+ Roadmap: default `false` en v0.12.0; flag y key `path` removidos en v1.0.
414
+
415
+ > **Sobre `url.path` vs `http_route`:** son semánticamente distintos — `url.path` es la URL **concreta** (alta cardinalidad, ej. `/users/42`), `http_route` es el **template** matcheado (baja cardinalidad, ej. `/users/:id`). En endpoints sin params coinciden en valor (ej. `/up`), pero ambos se siguen emitiendo porque cumplen roles distintos en dashboards/queries downstream. La dupe en valor es esperada, no es un bug.
416
+
390
417
  ### Filtrado de claves sensibles
391
418
 
392
419
  Las claves que matcheen `/password|pass|passwd|secret|token|api_key|auth/i` se reemplazan automáticamente por `[FILTERED]`, tanto en strings KV como en Hashes (incluyendo anidados).
@@ -52,6 +52,25 @@ module ExisRay
52
52
  # @example 'production'
53
53
  attr_accessor :deployment_environment
54
54
 
55
+ # @!attribute [rw] emit_legacy_exception_keys
56
+ # @return [Boolean] Si true, emite `error_class`/`error_message` junto a `exception.type`/`exception.message`.
57
+ # Default `true` durante la ventana de transición OTel v1.0. Setear a `false` cuando todos los
58
+ # consumers (dashboards, alertas, queries) hayan migrado a `exception.*` para reducir bytes
59
+ # y ruido en logs.
60
+ # Aplica a `ExisRay::LogSubscriber` (logs HTTP) y `ExisRay::TaskMonitor` (logs de tasks).
61
+ # @example false
62
+ attr_accessor :emit_legacy_exception_keys
63
+
64
+ # @!attribute [rw] emit_legacy_path_key
65
+ # @return [Boolean] Si true, `ExisRay::LogSubscriber` emite `path` (nombre legacy Wispro)
66
+ # junto a `url.path` (OTel v1.0). Default `true` durante la ventana de transición.
67
+ # Setear a `false` cuando los consumers (queries, dashboards, alertas) hayan migrado a
68
+ # `url.path` para reducir bytes y ruido en logs.
69
+ # Nota: `url.path` y `http_route` son semánticamente distintos (URL concreta vs template);
70
+ # coinciden como string solo en endpoints sin params — la dupe es esperada y no se elimina.
71
+ # @example false
72
+ attr_accessor :emit_legacy_path_key
73
+
55
74
  # Inicializa la configuración con valores por defecto compatibles con AWS X-Ray.
56
75
  def initialize
57
76
  @trace_header = "HTTP_X_AMZN_TRACE_ID"
@@ -62,6 +81,8 @@ module ExisRay
62
81
  @log_subscriber_class = nil
63
82
  @service_version = default_service_version
64
83
  @deployment_environment = default_deployment_environment
84
+ @emit_legacy_exception_keys = true
85
+ @emit_legacy_path_key = true
65
86
  end
66
87
 
67
88
  # Lee la versión del servicio desde la configuración de Rails.
@@ -98,7 +98,7 @@ module ExisRay
98
98
  component: "exis_ray",
99
99
  event: "http_request",
100
100
  method: payload[:method],
101
- path: payload[:path],
101
+ "url.path": payload[:path],
102
102
  http_route: extract_http_route(payload),
103
103
  format: payload[:format],
104
104
  controller: payload[:controller],
@@ -112,6 +112,8 @@ module ExisRay
112
112
  server_address: extract_server_address(headers["HTTP_HOST"])
113
113
  }
114
114
 
115
+ data[:path] = payload[:path] if ExisRay.configuration.emit_legacy_path_key
116
+
115
117
  data.merge!(exception_data)
116
118
  data.merge!(self.class.extra_fields(event))
117
119
  data.compact
@@ -129,15 +131,16 @@ module ExisRay
129
131
  end
130
132
 
131
133
  # Extrae los datos de excepción para logs OTel.
132
- # Emite tanto los campos legacy (`error_class`/`error_message`) como los OTel
133
- # (`exception.type`/`exception.message`/`exception.stacktrace`) durante la ventana
134
- # de transición definida en el plan "Breaking changes OTel v1.0".
134
+ # Siempre emite `exception.type`/`exception.message`/`exception.stacktrace` (OTel v1.0).
135
+ # Emite además los campos legacy (`error_class`/`error_message`) cuando
136
+ # `ExisRay.configuration.emit_legacy_exception_keys` es `true` (default durante la
137
+ # ventana de transición). Setear a `false` cuando los consumers hayan migrado.
135
138
  #
136
139
  # El stacktrace se toma de `payload[:exception_object]` (expuesto por Rails), no
137
140
  # de `payload[:exception]` que es solo `[class_name, message]`.
138
141
  #
139
142
  # @param payload [Hash] Payload completo del notification de Rails.
140
- # @return [Hash] Campos exception.* y error_class/error_message con keys symbol.
143
+ # @return [Hash] Campos exception.* (y error_class/error_message si el flag está activo).
141
144
  def extract_exception_data(payload)
142
145
  exception_info = payload[:exception]
143
146
  return {} unless exception_info
@@ -146,12 +149,15 @@ module ExisRay
146
149
  exception_message = exception_info.last
147
150
 
148
151
  data = {
149
- error_class: exception_class,
150
- error_message: exception_message,
151
152
  "exception.type": exception_class,
152
153
  "exception.message": exception_message
153
154
  }
154
155
 
156
+ if ExisRay.configuration.emit_legacy_exception_keys
157
+ data[:error_class] = exception_class
158
+ data[:error_message] = exception_message
159
+ end
160
+
155
161
  exception_object = payload[:exception_object]
156
162
  if exception_object.respond_to?(:backtrace) && exception_object.backtrace
157
163
  data[:"exception.stacktrace"] = exception_object.backtrace.take(20).join("\n")
@@ -47,9 +47,7 @@ module ExisRay
47
47
  log_event(:error,
48
48
  "component=exis_ray event=task_finished " \
49
49
  "outcome=failed duration_s=#{duration_s} duration_human=\"#{human_time}\" " \
50
- "error_class=#{e.class} error_message=#{e.message.inspect} " \
51
- "exception.type=#{e.class} exception.message=#{e.message.inspect} " \
52
- "exception.stacktrace=#{format_stacktrace(e.backtrace)}")
50
+ "#{format_exception_fields(e)}")
53
51
  raise e
54
52
  ensure
55
53
  # Limpieza centralizada obligatoria para evitar filtraciones de memoria o contexto
@@ -124,7 +122,26 @@ module ExisRay
124
122
  '""'
125
123
  end
126
124
 
125
+ # Construye los campos KV de excepción para el log de `task_finished` failed.
126
+ # Siempre incluye `exception.type` / `exception.message` / `exception.stacktrace` (OTel v1.0).
127
+ # Incluye además `error_class` / `error_message` cuando
128
+ # `ExisRay.configuration.emit_legacy_exception_keys` es `true` (default durante la ventana
129
+ # de transición).
130
+ #
131
+ # @param error [Exception]
132
+ # @return [String]
133
+ def self.format_exception_fields(error)
134
+ message_quoted = error.message.inspect
135
+ stack = format_stacktrace(error.backtrace)
136
+
137
+ parts = []
138
+ parts << "error_class=#{error.class} error_message=#{message_quoted}" if ExisRay.configuration.emit_legacy_exception_keys
139
+ parts << "exception.type=#{error.class} exception.message=#{message_quoted} " \
140
+ "exception.stacktrace=#{stack}"
141
+ parts.join(" ")
142
+ end
143
+
127
144
  private_class_method :pod_identifier, :setup_tracer, :execute_with_optional_tags,
128
- :log_event, :format_stacktrace
145
+ :log_event, :format_stacktrace, :format_exception_fields
129
146
  end
130
147
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module ExisRay
4
4
  # Versión actual de la gema.
5
- VERSION = "0.10.0"
5
+ VERSION = "0.11.0"
6
6
  end
data/skill/SKILL.md CHANGED
@@ -80,7 +80,7 @@ ExisRay unifica trazabilidad distribuida, logging estructurado JSON, contexto de
80
80
  3. `ExisRay.sync_correlation_id` asigna `Tracer.correlation_id` a `Current.correlation_id`
81
81
  4. Controller ejecuta `before_action` para setear `Current.user_id`, `Current.isp_id`
82
82
  5. `JsonFormatter` intercepta cada `Rails.logger.*` e inyecta el contexto de ejecucion en cada linea. **No es incondicional:** cada campo tiene un guard especifico (ver tabla "Condiciones de emision" mas abajo). En particular `inject_tracer_context` corta el bloque `root_id`/`trace_id`/`source`/`task`/`sidekiq_job` con `return unless Tracer.root_id` — la invariante "todo entrypoint garantiza `root_id`" es lo que hace que `source` (mandatorio) nunca falte. `request_id` se emite **fuera** de ese guard (distinto ciclo de vida que `root_id`). El developer aporta `component` (modulo de negocio) y `event` (que paso); estos NO son auto-inyectados porque dependen del call site, no del contexto de ejecucion.
83
- 6. `LogSubscriber` emite un unico Hash al finalizar el request con campos default (`component`, `event`, `method`, `path`, `http_route`, `format`, `controller`, `action`, `http_status`, `duration_s`, `duration_human`, `view_runtime_s`, `db_runtime_s`, `user_agent_original`, `server_address`, y en error `error_class`/`error_message`/`exception.*`).
83
+ 6. `LogSubscriber` emite un unico Hash al finalizar el request con campos default (`component`, `event`, `method`, `url.path` siempre + `path` si `config.emit_legacy_path_key`, `http_route`, `format`, `controller`, `action`, `http_status`, `duration_s`, `duration_human`, `view_runtime_s`, `db_runtime_s`, `user_agent_original`, `server_address`, y en error `exception.type`/`exception.message`/`exception.stacktrace` siempre + `error_class`/`error_message` si `config.emit_legacy_exception_keys`).
84
84
  7. En llamadas salientes, `FaradayMiddleware`/`ActiveResourceInstrumentation` inyectan `propagation_trace_header` con `Tracer.generate_trace_header`
85
85
  8. Al finalizar, `ActiveSupport::CurrentAttributes` hace reset automatico
86
86
 
@@ -100,6 +100,8 @@ ExisRay.configure do |config|
100
100
  config.log_subscriber_class = "MyLogSubscriber" # String|nil, default nil
101
101
  config.service_version = "1.2.3" # String|nil, default: Rails config.version o config.x.version
102
102
  config.deployment_environment = "production" # String|nil, default: Rails.env
103
+ config.emit_legacy_exception_keys = true # Boolean, default true (ventana transicion OTel v1.0)
104
+ config.emit_legacy_path_key = true # Boolean, default true (ventana transicion `path` -> `url.path` OTel v1.0)
103
105
  end
104
106
 
105
107
  ExisRay.configuration.json_logs? # => true si log_format == :json
@@ -233,8 +235,9 @@ ExisRay::TaskMonitor.run("billing:generate_invoices") do
233
235
  InvoiceService.process_all
234
236
  end
235
237
  # Genera root_id propio, loguea task_started/task_finished con outcome y duration_s.
236
- # En caso de error emite: error_class, error_message (legacy) + exception.type,
237
- # exception.message, exception.stacktrace (OTel, limitado a 20 lineas).
238
+ # En caso de error emite: exception.type, exception.message, exception.stacktrace
239
+ # (OTel, limitado a 20 lineas) + error_class/error_message si
240
+ # config.emit_legacy_exception_keys es true (default durante ventana de transicion).
238
241
  # Re-lanza excepciones despues de loguearlas.
239
242
  # Hace reset de Tracer, Current y Reporter en ensure.
240
243
  ```
@@ -250,8 +253,9 @@ Reemplaza Lograge. Se suscribe a `process_action.action_controller` y emite un H
250
253
  | `component` | String | Siempre `"exis_ray"` |
251
254
  | `event` | String | Siempre `"http_request"` |
252
255
  | `method` | String | Verbo HTTP |
253
- | `path` | String | URL concreta del request |
254
- | `http_route` | String | Template (ej: `/users/:id`). Baja cardinalidad para dashboards |
256
+ | `url.path` | String | URL concreta del request (OTel v1.0). Siempre presente |
257
+ | `path` | String | Alias legacy de `url.path`. Solo si `config.emit_legacy_path_key` (default `true`, deprecado) |
258
+ | `http_route` | String | Template (ej: `/users/:id`). Baja cardinalidad para dashboards. En endpoints sin params coincide en valor con `url.path` — dupe semanticamente esperada (concrete vs template) |
255
259
  | `format` | Symbol/String | `html`, `json`, etc. |
256
260
  | `controller` | String | Class name del controller |
257
261
  | `action` | String | Nombre del action |
@@ -262,7 +266,7 @@ Reemplaza Lograge. Se suscribe a `process_action.action_controller` y emite un H
262
266
  | `db_runtime_s` | Float\|nil | Solo si ActiveRecord lo reporta |
263
267
  | `user_agent_original` | String | Header `User-Agent` |
264
268
  | `server_address` | String | Hostname sin puerto (de `Host` header) |
265
- | `error_class`, `error_message` | String | Solo en fallo (legacy) |
269
+ | `error_class`, `error_message` | String | Solo en fallo y si `config.emit_legacy_exception_keys` (default `true`, deprecadas) |
266
270
  | `exception.type`, `exception.message`, `exception.stacktrace` | String | Solo en fallo (OTel; stack limitado a 20 lineas) |
267
271
 
268
272
  Para inyectar campos extra, sobreescribir `extra_fields`:
@@ -37,6 +37,14 @@ RSpec.describe ExisRay::Configuration do
37
37
  it "deployment_environment por defecto es nil fuera de Rails" do
38
38
  expect(config.deployment_environment).to be_nil
39
39
  end
40
+
41
+ it "emit_legacy_exception_keys por defecto es true (ventana de transición OTel)" do
42
+ expect(config.emit_legacy_exception_keys).to be true
43
+ end
44
+
45
+ it "emit_legacy_path_key por defecto es true (ventana de transición OTel url.path)" do
46
+ expect(config.emit_legacy_path_key).to be true
47
+ end
40
48
  end
41
49
 
42
50
  describe "resource attributes OTel" do
@@ -158,5 +166,19 @@ RSpec.describe ExisRay::Configuration do
158
166
 
159
167
  expect(config.log_subscriber_class).to eq("MyLogSubscriber")
160
168
  end
169
+
170
+ it "permite cambiar emit_legacy_exception_keys" do
171
+ config = described_class.new
172
+ config.emit_legacy_exception_keys = false
173
+
174
+ expect(config.emit_legacy_exception_keys).to be false
175
+ end
176
+
177
+ it "permite cambiar emit_legacy_path_key" do
178
+ config = described_class.new
179
+ config.emit_legacy_path_key = false
180
+
181
+ expect(config.emit_legacy_path_key).to be false
182
+ end
161
183
  end
162
184
  end
@@ -151,6 +151,33 @@ RSpec.describe ExisRay::LogSubscriber do
151
151
  expect(data[:server_address]).to eq("api.example.com")
152
152
  end
153
153
 
154
+ it "emite url.path (OTel v1.0) siempre con la URL concreta" do
155
+ event = build_event(payload: base_payload)
156
+
157
+ data = subscriber.send(:build_payload, event)
158
+
159
+ expect(data[:"url.path"]).to eq("/users/42")
160
+ end
161
+
162
+ it "emite path (legacy Wispro) junto a url.path cuando emit_legacy_path_key=true (default)" do
163
+ event = build_event(payload: base_payload)
164
+
165
+ data = subscriber.send(:build_payload, event)
166
+
167
+ expect(data[:path]).to eq("/users/42")
168
+ expect(data[:"url.path"]).to eq("/users/42")
169
+ end
170
+
171
+ it "omite path cuando emit_legacy_path_key=false (solo url.path)" do
172
+ allow(ExisRay.configuration).to receive(:emit_legacy_path_key).and_return(false)
173
+ event = build_event(payload: base_payload)
174
+
175
+ data = subscriber.send(:build_payload, event)
176
+
177
+ expect(data).not_to have_key(:path)
178
+ expect(data[:"url.path"]).to eq("/users/42")
179
+ end
180
+
154
181
  # Helper: construye un mock de ActionDispatch::Journey::Route con la API REAL
155
182
  # que usa el código de producción (route.defaults, route.path.spec, route.verb).
156
183
  # Esto evita el anti-patrón anterior de stubear una API inventada.
@@ -268,6 +295,22 @@ RSpec.describe ExisRay::LogSubscriber do
268
295
  expect(data[:error_message]).to eq("something went wrong")
269
296
  end
270
297
 
298
+ it "omite error_class/error_message cuando emit_legacy_exception_keys=false" do
299
+ allow(ExisRay.configuration).to receive(:emit_legacy_exception_keys).and_return(false)
300
+
301
+ event = build_event(payload: base_payload.merge(
302
+ status: nil,
303
+ exception: ["RuntimeError", "something went wrong"]
304
+ ))
305
+
306
+ data = subscriber.send(:build_payload, event)
307
+
308
+ expect(data[:"exception.type"]).to eq("RuntimeError")
309
+ expect(data[:"exception.message"]).to eq("something went wrong")
310
+ expect(data).not_to have_key(:error_class)
311
+ expect(data).not_to have_key(:error_message)
312
+ end
313
+
271
314
  it "inyecta exception.stacktrace desde payload[:exception_object]" do
272
315
  exception_object = RuntimeError.new("boom")
273
316
  exception_object.set_backtrace(["a.rb:1", "b.rb:2", "c.rb:3"])
@@ -109,6 +109,21 @@ RSpec.describe ExisRay::TaskMonitor do
109
109
  expect(finish_log[1]).to include("exception.stacktrace=")
110
110
  end
111
111
 
112
+ it "omite error_class/error_message cuando emit_legacy_exception_keys=false" do
113
+ allow(ExisRay.configuration).to receive(:emit_legacy_exception_keys).and_return(false)
114
+
115
+ expect do
116
+ described_class.run("task:boom") { raise "kaboom" }
117
+ end.to raise_error(RuntimeError, "kaboom")
118
+
119
+ finish_log = captured_logs.find { |lvl, msg| lvl == :error && msg.include?("task_finished") }
120
+ expect(finish_log[1]).not_to include("error_class=")
121
+ expect(finish_log[1]).not_to include("error_message=")
122
+ expect(finish_log[1]).to include("exception.type=RuntimeError")
123
+ expect(finish_log[1]).to include("exception.message=")
124
+ expect(finish_log[1]).to include("exception.stacktrace=")
125
+ end
126
+
112
127
  it "resetea el Tracer incluso en caso de error" do
113
128
  begin
114
129
  described_class.run("task:boom") { raise "kaboom" }
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.10.0
4
+ version: 0.11.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-05-25 00:00:00.000000000 Z
11
+ date: 2026-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -90,8 +90,8 @@ licenses:
90
90
  metadata:
91
91
  homepage_uri: https://github.com/gedera/exis_ray
92
92
  source_code_uri: https://github.com/gedera/exis_ray
93
- changelog_uri: https://github.com/gedera/exis_ray/blob/v0.10.0/CHANGELOG.md
94
- documentation_uri: https://github.com/gedera/exis_ray/blob/v0.10.0/skill
93
+ changelog_uri: https://github.com/gedera/exis_ray/blob/v0.11.0/CHANGELOG.md
94
+ documentation_uri: https://github.com/gedera/exis_ray/blob/v0.11.0/skill
95
95
  post_install_message:
96
96
  rdoc_options: []
97
97
  require_paths: