This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Released under the MIT License.
|
||||
# Copyright, 2021-2023, by Samuel Williams.
|
||||
|
||||
require 'securerandom'
|
||||
|
||||
module Traces
|
||||
# A generic representation of the current tracing context.
|
||||
class Context
|
||||
# Parse a string representation of a distributed trace.
|
||||
# @parameter parent [String] The parent trace context.
|
||||
# @parameter state [Array(String)] Any attached trace state.
|
||||
def self.parse(parent, state = nil, **options)
|
||||
version, trace_id, parent_id, flags = parent.split('-')
|
||||
|
||||
if version == '00'
|
||||
flags = Integer(flags, 16)
|
||||
|
||||
if state.is_a?(String)
|
||||
state = state.split(',')
|
||||
end
|
||||
|
||||
if state
|
||||
state = state.map{|item| item.split('=')}.to_h
|
||||
end
|
||||
|
||||
self.new(trace_id, parent_id, flags, state, **options)
|
||||
end
|
||||
end
|
||||
|
||||
# Create a local trace context which is likley to be globally unique.
|
||||
# @parameter flags [Integer] Any trace context flags.
|
||||
def self.local(flags = 0, **options)
|
||||
self.new(SecureRandom.hex(16), SecureRandom.hex(8), flags, **options)
|
||||
end
|
||||
|
||||
# Nest a local trace context in an optional parent context.
|
||||
# @parameter parent [Context] An optional parent context.
|
||||
def self.nested(parent, flags = 0)
|
||||
if parent
|
||||
parent.nested(flags)
|
||||
else
|
||||
self.local(flags)
|
||||
end
|
||||
end
|
||||
|
||||
SAMPLED = 0x01
|
||||
|
||||
# Initialize the trace context.
|
||||
# @parameter trace_id [String] The ID of the whole trace forest.
|
||||
# @parameter parent_id [String] The ID of this operation as known by the caller (sometimes referred to as the span ID).
|
||||
# @parameter flags [Integer] An 8-bit field that controls tracing flags such as sampling, trace level, etc.
|
||||
# @parameter state [Hash] Additional vendor-specific trace identification information.
|
||||
# @parameter remote [Boolean] Whether this context was created from a distributed trace header.
|
||||
def initialize(trace_id, parent_id, flags, state = nil, remote: false)
|
||||
@trace_id = trace_id
|
||||
@parent_id = parent_id
|
||||
@flags = flags
|
||||
@state = state
|
||||
@remote = remote
|
||||
end
|
||||
|
||||
# Create a new nested trace context in which spans can be recorded.
|
||||
def nested(flags = @flags)
|
||||
Context.new(@trace_id, SecureRandom.hex(8), flags, @state, remote: @remote)
|
||||
end
|
||||
|
||||
# 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.
|
||||
attr :trace_id
|
||||
|
||||
# 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.
|
||||
attr :parent_id
|
||||
|
||||
# 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.
|
||||
attr :flags
|
||||
|
||||
# Provides additional vendor-specific trace identification information across different distributed tracing systems. Conveys information about the operation's position in multiple distributed tracing graphs.
|
||||
attr :state
|
||||
|
||||
# Denotes that the caller may have recorded trace data. When unset, the caller did not record trace data out-of-band.
|
||||
def sampled?
|
||||
(@flags & SAMPLED) != 0
|
||||
end
|
||||
|
||||
# Whether this context was created from a distributed trace header.
|
||||
def remote?
|
||||
@remote
|
||||
end
|
||||
|
||||
# A string representation of the trace context (excluding trace state).
|
||||
def to_s
|
||||
"00-#{@trace_id}-#{@parent_id}-#{@flags.to_s(16)}"
|
||||
end
|
||||
|
||||
# Convert the trace context to a JSON representation, including trace state.
|
||||
def as_json
|
||||
{
|
||||
trace_id: @trace_id,
|
||||
parent_id: @parent_id,
|
||||
flags: @flags,
|
||||
state: @state,
|
||||
remote: @remote
|
||||
}
|
||||
end
|
||||
|
||||
# Convert the trace context to a JSON string.
|
||||
def to_json(...)
|
||||
as_json.to_json(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user