Class: Stackdriver::Core::TraceContext

Inherits:
Object
  • Object
show all
Defined in:
lib/stackdriver/core/trace_context.rb

Overview

A Stackdriver trace context links the current request into a performance trace, and communicates tracing options between related requests. This functionality is used by the Stackdriver diagnostics libraries (including google-cloud-trace, google-cloud-logging, and other rubygems) that integrate with the tracing service.

Most applications will not need to use the TraceContext class directly. The Stackdriver libraries use it internally to store and propagate context information.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(trace_id: nil, is_new: nil, span_id: nil, sampled: nil, capture_stack: false) ⇒ TraceContext

Create a new TraceContext instance.

Examples:

require "stackdriver/core"

trace_id = "0123456789abcdef0123456789abcdef"
ctx = Stackdriver::Core::TraceContext.new trace_id: trace_id,
                                          sampled: true

Parameters:

  • trace_id (String) (defaults to: nil)

    The trace ID as a hex string. If nil or omitted, a new random Trace ID will be generated, and this TraceContext will be marked as new.

  • is_new (Boolean) (defaults to: nil)

    Whether this trace context should be flagged as newly created. Optional: if unset, will reflect whether a new trace_id was generated when this object was created.

  • span_id (Integer) (defaults to: nil)

    The context parent span ID as a 64-bit int. If nil or omitted, the context will specify no parent span.

  • sampled (Boolean) (defaults to: nil)

    Whether the context has decided to sample this trace or not, or nil if the context does not specify a sampling decision.

  • capture_stack (Boolean) (defaults to: false)

    Whether the the context has decided to capture stack traces. Ignored if sampled is not true.



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/stackdriver/core/trace_context.rb', line 70

def initialize trace_id: nil, is_new: nil, span_id: nil, sampled: nil,
               capture_stack: false
  @trace_id = trace_id || new_random_trace_id
  @is_new = is_new.nil? ? !trace_id : !!is_new
  @span_id = span_id&.to_i
  @sampled = sampled
  if @sampled.nil?
    @capture_stack = nil
  else
    @sampled = !!@sampled
    @capture_stack = capture_stack && @sampled
  end
end

Instance Attribute Details

#span_idInteger? (readonly)

The span ID, as a 64-bit integer, or nil if no span ID is present in the context.

Returns:

  • (Integer, nil)


97
98
99
# File 'lib/stackdriver/core/trace_context.rb', line 97

def span_id
  @span_id
end

#trace_idString (readonly)

The trace ID, as a hex string.

Returns:

  • (String)


89
90
91
# File 'lib/stackdriver/core/trace_context.rb', line 89

def trace_id
  @trace_id
end

Class Method Details

.getTraceContext?

Returns the current thread's trace context, or nil if no trace context has been set.

Examples:

require "stackdriver/core"

ctx = Stackdriver::Core::TraceContext.new
Stackdriver::Core::TraceContext.set ctx
same_ctx = Stackdriver::Core::TraceContext.get

Returns:



317
318
319
# File 'lib/stackdriver/core/trace_context.rb', line 317

def self.get
  Thread.current[THREAD_KEY]
end

.parse_rack_env(env) ⇒ TraceContext

Obtains a TraceContext from the given Rack environment. This should be used by any service that wants to obtain the TraceContext for a Rack request. If a new trace context is generated in the process, it is memoized into the Rack environment so subsequent services will get the same context.

Specifically, the following steps are attempted in order:

  1. Attempts to use any memoized context previously obtained.
  2. Attempts to parse the trace context header.
  3. Creates a new trace context with a random trace ID.

Furthermore, if a block is given, it is provided with an opportunity to modify the trace context. The current trace context and the Rack environment is passed to the block, and its result is used as the final trace context. The final context is memoized back into the Rack environment.

Examples:

require "stackdriver/core"

class MyMiddleware
  def initialize app
    @app = app
  end

  def call env
    ctx = Stackdriver::Core::TraceContext.parse_rack_env env
    do_something_with ctx
    @app.call env
  end
end

Parameters:

  • env (Hash)

    The Rack environment hash

Returns:



276
277
278
279
280
281
282
# File 'lib/stackdriver/core/trace_context.rb', line 276

def self.parse_rack_env env
  trace_context = env[MEMO_RACK_KEY] ||
                  parse_string(env[HEADER_RACK_KEY].to_s) ||
                  new
  trace_context = yield trace_context, env if block_given?
  env[MEMO_RACK_KEY] = trace_context
end

.parse_string(str) ⇒ TraceContext?

Attempts to parse the given string as a trace context representation. Expects the form <traceid>[/<spanid>][;o=<options>], which is the form used in the trace context header. Returns either the parsed trace context, or nil if the string was malformed.

Examples:

require "stackdriver/core"

str = "0123456789abcdef0123456789abcdef/12345;o=1"
ctx = Stackdriver::Core::TraceContext.parse_string str

Parameters:

  • str (String)

    The string to parse.

Returns:



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/stackdriver/core/trace_context.rb', line 222

def self.parse_string str
  match = %r|^(\w{32})(/(\d+))?(;o=(\d+))?|.match str
  return unless match

  trace_id = match[1]
  span_id = match[3]&.to_i
  options = match[5]&.to_i
  if options.nil?
    sampled = capture_stack = nil
  else
    sampled = options & 1 != 0
    capture_stack = options & 2 != 0
  end
  new trace_id: trace_id, span_id: span_id, sampled: sampled,
      capture_stack: capture_stack
end

.set(trace_context) ⇒ TraceContext?

Set the current thread's trace context, and returns the context.

Examples:

require "stackdriver/core"

ctx = Stackdriver::Core::TraceContext.new
Stackdriver::Core::TraceContext.set ctx
same_ctx = Stackdriver::Core::TraceContext.get

Parameters:

  • trace_context (TraceContext, nil)

    The trace context to set for the current thread. May be nil.

Returns:



299
300
301
302
# File 'lib/stackdriver/core/trace_context.rb', line 299

def self.set trace_context
  Thread.current[THREAD_KEY] = trace_context
  trace_context
end

Instance Method Details

#capture_stack?Boolean?

Returns true if the context wants to capture stack traces, false if the context does not, or nil if the context does not specify a sampling decision.

Returns:

  • (Boolean, nil)


117
118
119
# File 'lib/stackdriver/core/trace_context.rb', line 117

def capture_stack?
  @capture_stack
end

#eql?(other) ⇒ Boolean Also known as: ==

Standard value equality check for this object.

Parameters:

  • other (Object)

    An object to compare with.

Returns:

  • (Boolean)


136
137
138
139
140
141
142
143
# File 'lib/stackdriver/core/trace_context.rb', line 136

def eql? other
  other.is_a?(TraceContext) &&
    trace_id == other.trace_id &&
    new? == other.new? &&
    span_id == other.span_id &&
    sampled? == other.sampled? &&
    capture_stack? == other.capture_stack?
end

#hashInteger

Generate standard hash code for this object.

Returns:

  • (Integer)


151
152
153
# File 'lib/stackdriver/core/trace_context.rb', line 151

def hash
  @hash ||= [@trace_id, @is_new, @span_id, @sampled, @capture_stack].hash
end

#new?Boolean

Returns true if this trace includes a newly generated trace_id.

Returns:

  • (Boolean)


126
127
128
# File 'lib/stackdriver/core/trace_context.rb', line 126

def new?
  @is_new
end

#sampled?Boolean?

Returns true if the context wants to sample, false if the context wants explicitly to disable sampling, or nil if the context does not specify.

Returns:

  • (Boolean, nil)


106
107
108
# File 'lib/stackdriver/core/trace_context.rb', line 106

def sampled?
  @sampled
end

#to_stringString Also known as: to_s

Returns a string representation of this trace context, in the form <traceid>[/<spanid>][;o=<options>]. This form is suitable for setting the trace context header.

Returns:

  • (String)


193
194
195
196
197
198
199
200
201
202
203
# File 'lib/stackdriver/core/trace_context.rb', line 193

def to_string
  str = trace_id
  str += "/#{span_id}" if span_id
  unless sampled?.nil?
    options = 0
    options |= 1 if sampled?
    options |= 2 if capture_stack?
    str += ";o=#{options}"
  end
  str
end

#with(trace_id: UNCHANGED, is_new: UNCHANGED, span_id: UNCHANGED, sampled: UNCHANGED, capture_stack: UNCHANGED) ⇒ TraceContext

Returns a new TraceContext instance that is identical to this instance except for the given changes. All parameters are optional. See #initialize for more details on each parameter.

Examples:

require "stackdriver/core"

trace_id = "0123456789abcdef0123456789abcdef"
orig_ctx = Stackdriver::Core::TraceContext.new trace_id: trace_id,

sampled_ctx = orig_ctx.with sampled: true

Parameters:

  • trace_id (String) (defaults to: UNCHANGED)

    New trace ID.

  • is_new (Boolean) (defaults to: UNCHANGED)

    New setting for newness indicator.

  • span_id (Integer) (defaults to: UNCHANGED)

    New parent span ID.

  • sampled (Boolean) (defaults to: UNCHANGED)

    New sampling decision.

  • capture_stack (Boolean) (defaults to: UNCHANGED)

    New stack capture decision.

Returns:



175
176
177
178
179
180
181
182
183
184
# File 'lib/stackdriver/core/trace_context.rb', line 175

def with trace_id: UNCHANGED, is_new: UNCHANGED, span_id: UNCHANGED,
         sampled: UNCHANGED, capture_stack: UNCHANGED
  trace_id = @trace_id if trace_id == UNCHANGED
  is_new = @is_new if is_new == UNCHANGED
  span_id = @span_id if span_id == UNCHANGED
  sampled = @sampled if sampled == UNCHANGED
  capture_stack = @capture_stack if capture_stack == UNCHANGED
  TraceContext.new trace_id: trace_id, is_new: is_new, span_id: span_id,
                   sampled: sampled, capture_stack: capture_stack
end