Class: BrainzLab::Pulse::Tracer

Inherits:
Object
  • Object
show all
Defined in:
lib/brainzlab/pulse/tracer.rb

Instance Method Summary collapse

Constructor Details

#initialize(config, client) ⇒ Tracer

Returns a new instance of Tracer.



6
7
8
9
# File 'lib/brainzlab/pulse/tracer.rb', line 6

def initialize(config, client)
  @config = config
  @client = client
end

Instance Method Details

#current_spansObject



15
16
17
# File 'lib/brainzlab/pulse/tracer.rb', line 15

def current_spans
  Thread.current[:brainzlab_pulse_spans] ||= []
end

#current_traceObject



11
12
13
# File 'lib/brainzlab/pulse/tracer.rb', line 11

def current_trace
  Thread.current[:brainzlab_pulse_trace]
end

#finish_trace(error: false, error_class: nil, error_message: nil) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/brainzlab/pulse/tracer.rb', line 37

def finish_trace(error: false, error_class: nil, error_message: nil)
  trace = current_trace
  return unless trace

  ended_at = Time.now.utc
  duration_ms = ((ended_at - trace[:started_at]) * 1000).round(2)

  payload = trace.merge(
    ended_at: ended_at.iso8601(3),
    started_at: trace[:started_at].utc.iso8601(3),
    duration_ms: duration_ms,
    error: error,
    error_class: error_class,
    error_message: error_message,
    spans: current_spans.map { |s| format_span(s, trace[:started_at]) }
  ).compact

  # Add request context if available
  ctx = BrainzLab::Context.current
  payload[:request_id] ||= ctx.request_id
  payload[:user_id] ||= ctx.user&.dig(:id)&.to_s

  @client.send_trace(payload)

  Thread.current[:brainzlab_pulse_trace] = nil
  Thread.current[:brainzlab_pulse_spans] = nil

  payload
end

#span(name, kind: 'custom', **data) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/brainzlab/pulse/tracer.rb', line 67

def span(name, kind: 'custom', **data)
  span_data = {
    span_id: SecureRandom.uuid,
    name: name,
    kind: kind,
    started_at: Time.now.utc,
    data: data
  }

  begin
    result = yield
    span_data[:error] = false
    result
  rescue StandardError => e
    span_data[:error] = true
    span_data[:error_class] = e.class.name
    span_data[:error_message] = e.message
    raise
  ensure
    span_data[:ended_at] = Time.now.utc
    span_data[:duration_ms] = ((span_data[:ended_at] - span_data[:started_at]) * 1000).round(2)
    current_spans << span_data
  end
end

#start_trace(name, kind: 'custom', **attributes) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/brainzlab/pulse/tracer.rb', line 19

def start_trace(name, kind: 'custom', **attributes)
  trace = {
    trace_id: SecureRandom.uuid,
    name: name,
    kind: kind,
    started_at: Time.now.utc,
    environment: @config.environment,
    commit: @config.commit,
    host: @config.host,
    **attributes
  }

  Thread.current[:brainzlab_pulse_trace] = trace
  Thread.current[:brainzlab_pulse_spans] = []

  trace
end