Class: Traces::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/traces/context.rb

Overview

A generic representation of the current tracing context.

Constant Summary collapse

SAMPLED =
0x01

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(trace_id, parent_id, flags, state = nil, baggage = nil, remote: false) ⇒ Context

Initialize the trace context.



64
65
66
67
68
69
70
71
# File 'lib/traces/context.rb', line 64

def initialize(trace_id, parent_id, flags, state = nil, baggage = nil, remote: false)
  @trace_id = trace_id
  @parent_id = parent_id
  @flags = flags
  @state = state
  @baggage = baggage
  @remote = remote
end

Instance Attribute Details

#baggageObject (readonly)

Provides additional application-specific trace identification information across different distributed tracing systems.



91
92
93
# File 'lib/traces/context.rb', line 91

def baggage
  @baggage
end

#flagsObject (readonly)

An 8-bit field that controls tracing flags such as sampling, trace level, etc. These flags are recommendations given by the caller rather than strict rules.



85
86
87
# File 'lib/traces/context.rb', line 85

def flags
  @flags
end

#parent_idObject (readonly)

The ID of this operation as known by the caller (in some tracing systems, this is known as the span-id, where a span is the execution of a client operation). It is represented as an 8-byte array, for example, 00f067aa0ba902b7. All bytes as zero (0000000000000000) is considered an invalid value.



82
83
84
# File 'lib/traces/context.rb', line 82

def parent_id
  @parent_id
end

#stateObject (readonly)

Provides additional vendor-specific trace identification information across different distributed tracing systems.



88
89
90
# File 'lib/traces/context.rb', line 88

def state
  @state
end

#trace_idObject (readonly)

The ID of the whole trace forest and is used to uniquely identify a distributed trace through a system. It is represented as a 16-byte array, for example, 4bf92f3577b34da6a3ce929d0e0e4736. All bytes as zero (00000000000000000000000000000000) is considered an invalid value.



79
80
81
# File 'lib/traces/context.rb', line 79

def trace_id
  @trace_id
end

Class Method Details

.extract(headers) ⇒ Object

Extract the trace context from the headers.

The ‘“traceparent”` header is a string representation of the trace context. If it is an Array, the first element is used, otherwise it is used as is. The `“tracestate”` header is a string representation of the trace state. If it is a String, it is split on commas before being processed. The `“baggage”` header is a string representation of the baggage. If it is a String, it is split on commas before being processed.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/traces/context.rb', line 153

def self.extract(headers)
  if traceparent = headers["traceparent"]
    if traceparent.is_a?(Array)
      traceparent = traceparent.first
    end
    
    if traceparent.empty?
      return nil
    end
    
    tracestate = headers["tracestate"]
    baggage = headers["baggage"]
    
    return self.parse(traceparent, tracestate, baggage, remote: true)
  end
end

.local(flags = 0, **options) ⇒ Object

Create a local trace context which is likely to be globally unique.



42
43
44
# File 'lib/traces/context.rb', line 42

def self.local(flags = 0, **options)
  self.new(SecureRandom.hex(16), SecureRandom.hex(8), flags, **options)
end

.nested(parent, flags = 0) ⇒ Object

Nest a local trace context in an optional parent context.



48
49
50
51
52
53
54
# File 'lib/traces/context.rb', line 48

def self.nested(parent, flags = 0)
  if parent
    parent.nested(flags)
  else
    self.local(flags)
  end
end

.parse(parent, state = nil, baggage = nil, **options) ⇒ Object

Parse a string representation of a distributed trace.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/traces/context.rb', line 14

def self.parse(parent, state = nil, baggage = nil, **options)
  version, trace_id, parent_id, flags = parent.split("-")
  
  if version == "00" && trace_id && parent_id && flags
    flags = Integer(flags, 16)
    
    if state.is_a?(String)
      state = state.split(",")
    end
    
    if state
      state = state.map{|item| item.split("=")}.to_h
    end
    
    if baggage.is_a?(String)
      baggage = baggage.split(",")
    end
    
    if baggage
      baggage = baggage.map{|item| item.split("=")}.to_h
    end
    
    self.new(trace_id, parent_id, flags, state, baggage, **options)
  end
end

Instance Method Details

#as_jsonObject

Convert the trace context to a JSON representation, including trace state.



109
110
111
112
113
114
115
116
117
118
# File 'lib/traces/context.rb', line 109

def as_json
  {
    trace_id: @trace_id,
    parent_id: @parent_id,
    flags: @flags,
    state: @state,
    baggage: @baggage,
    remote: @remote
  }
end

#inject(headers) ⇒ Object

Inject the trace context into the headers, including the ‘“traceparent”`, `“tracestate”`, and `“baggage”` headers.



130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/traces/context.rb', line 130

def inject(headers)
  headers["traceparent"] = self.to_s
  
  if @state and !@state.empty?
    headers["tracestate"] = self.state.map{|key, value| "#{key}=#{value}"}.join(",")
  end
  
  if @baggage and !@baggage.empty?
    headers["baggage"] = self.baggage.map{|key, value| "#{key}=#{value}"}.join(",")
  end
  
  return headers
end

#nested(flags = @flags) ⇒ Object

Create a new nested trace context in which spans can be recorded.



74
75
76
# File 'lib/traces/context.rb', line 74

def nested(flags = @flags)
  Context.new(@trace_id, SecureRandom.hex(8), flags, @state, @baggage, remote: @remote)
end

#remote?Boolean

Whether this context was created from a distributed trace header.

Returns:

  • (Boolean)


99
100
101
# File 'lib/traces/context.rb', line 99

def remote?
  @remote
end

#sampled?Boolean

Denotes that the caller may have recorded trace data. When unset, the caller did not record trace data out-of-band.

Returns:

  • (Boolean)


94
95
96
# File 'lib/traces/context.rb', line 94

def sampled?
  (@flags & SAMPLED) != 0
end

#to_jsonObject

Convert the trace context to a JSON string.



121
122
123
# File 'lib/traces/context.rb', line 121

def to_json(...)
  as_json.to_json(...)
end

#to_sObject

A string representation of the trace context (excluding trace state).



104
105
106
# File 'lib/traces/context.rb', line 104

def to_s
  "00-#{@trace_id}-#{@parent_id}-#{@flags.to_s(16)}"
end