Class: ExisRay::Tracer
- Inherits:
-
ActiveSupport::CurrentAttributes
- Object
- ActiveSupport::CurrentAttributes
- ExisRay::Tracer
- Defined in:
- lib/exis_ray/tracer.rb
Overview
Gestiona el contexto de trazabilidad distribuida (Distributed Tracing). Utiliza ‘ActiveSupport::CurrentAttributes` para mantener el estado de la petición actual de forma segura entre hilos (thread-safe).
Esta clase parsea headers de AWS X-Ray y genera nuevos headers para la propagación.
Class Method Summary collapse
-
.correlation_id ⇒ String
Genera un ID de correlación compuesto, útil para logs y auditoría.
-
.current_duration_ms ⇒ Integer
Calcula el tiempo transcurrido en milisegundos desde el inicio de la request.
-
.current_duration_s ⇒ Float
Calcula el tiempo transcurrido en segundos desde el inicio de la request.
-
.format_duration(seconds) ⇒ String
Formatea una duración en segundos a un string legible por humanos.
-
.generate_trace_header ⇒ String
Construye el header de trazabilidad para enviar al siguiente servicio.
-
.hydrate(trace_id:, source:) ⇒ void
Hidrata el Tracer con un trace header entrante y registra el inicio del contexto.
-
.parse_trace_id ⇒ void
Parsea el string de trazabilidad recibido y popula los atributos individuales.
-
.service_name ⇒ String
Devuelve el nombre de la aplicación en snake_case (ej: “cold_storage_service”).
Class Method Details
.correlation_id ⇒ String
Genera un ID de correlación compuesto, útil para logs y auditoría.
32 33 34 |
# File 'lib/exis_ray/tracer.rb', line 32 def self.correlation_id "#{service_name};#{root_id}" end |
.current_duration_ms ⇒ Integer
Calcula el tiempo transcurrido en milisegundos desde el inicio de la request.
67 68 69 |
# File 'lib/exis_ray/tracer.rb', line 67 def self.current_duration_ms (current_duration_s * 1000).round end |
.current_duration_s ⇒ Float
Calcula el tiempo transcurrido en segundos desde el inicio de la request. Cumple con el estándar Wispro-Observability-Spec (v1).
89 90 91 92 93 |
# File 'lib/exis_ray/tracer.rb', line 89 def self.current_duration_s return 0.0 unless created_at (Process.clock_gettime(Process::CLOCK_MONOTONIC) - created_at).round(4) end |
.format_duration(seconds) ⇒ String
Formatea una duración en segundos a un string legible por humanos.
-
Menos de 1s → “7.2ms”
-
Entre 1-60s → “1.25s”
-
60s o más → “2 minutes 5 seconds” (via ActiveSupport::Duration)
102 103 104 105 106 107 108 109 110 |
# File 'lib/exis_ray/tracer.rb', line 102 def self.format_duration(seconds) if seconds < 1.0 "#{(seconds * 1000).round(1)}ms" elsif seconds < 60.0 "#{seconds.round(3)}s" else ActiveSupport::Duration.build(seconds.round).inspect end end |
.generate_trace_header ⇒ String
Construye el header de trazabilidad para enviar al siguiente servicio.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/exis_ray/tracer.rb', line 115 def self.generate_trace_header safe_root = if root_id.present? root_id.start_with?("Root=") ? root_id : "Root=#{root_id}" else generate_new_root end total_acc_time = (total_time_so_far || 0) + current_duration_ms # Nuevo ID para el span actual my_new_id = "1-#{Time.now.to_i.to_s(16)}-#{clean_request_id}" "#{safe_root};Self=#{my_new_id};CalledFrom=#{service_name};TotalTimeSoFar=#{total_acc_time}ms" end |
.hydrate(trace_id:, source:) ⇒ void
This method returns an undefined value.
Hidrata el Tracer con un trace header entrante y registra el inicio del contexto. Centraliza la inicialización de contexto de trazabilidad para todos los entrypoints (HTTP, Sidekiq, BugBunny, etc.), eliminando duplicación entre middlewares.
78 79 80 81 82 83 |
# File 'lib/exis_ray/tracer.rb', line 78 def self.hydrate(trace_id:, source:) self.created_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) self.source = source self.trace_id = trace_id parse_trace_id end |
.parse_trace_id ⇒ void
This method returns an undefined value.
Parsea el string de trazabilidad recibido y popula los atributos individuales. Maneja el formato estándar de AWS: “Root=…;Self=…;CalledFrom=…;TotalTimeSoFar=…”
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/exis_ray/tracer.rb', line 40 def self.parse_trace_id return unless trace_id.present? self.trace_id = generate_new_root(trace_id) if trace_id.exclude?("Root") data = {} trace_id.split(";").each do |part| key_value = part.split("=", 2) next unless key_value.size == 2 data[key_value[0]] = key_value[1] end self.root_id = data["Root"] self.self_id = data["Self"] self.called_from = data["CalledFrom"] self.total_time_so_far = if data["TotalTimeSoFar"] data["TotalTimeSoFar"].gsub(/ms$/i, "").to_i else 0 end end |
.service_name ⇒ String
Devuelve el nombre de la aplicación en snake_case (ej: “cold_storage_service”). Se utiliza como identificador global del servicio en logs y trazabilidad.
22 23 24 |
# File 'lib/exis_ray/tracer.rb', line 22 def self.service_name @service_name ||= (defined?(Rails) ? Rails.application.class.module_parent_name.underscore : "app") end |