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)

    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)

    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)

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

  • sampled (Boolean)

    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)

    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
83
84
85
86
# 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
  if is_new.nil?
    @is_new = !trace_id
  else
    @is_new = is_new ? true : false
  end
  @span_id = span_id ? span_id.to_i : nil
  @sampled = sampled
  if @sampled.nil?
    @capture_stack = nil
  else
    @sampled = @sampled ? true : false
    @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)


101
102
103
# File 'lib/stackdriver/core/trace_context.rb', line 101

def span_id
  @span_id
end

#trace_idString (readonly)

The trace ID, as a hex string.

Returns:

  • (String)


93
94
95
# File 'lib/stackdriver/core/trace_context.rb', line 93

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:



324
325
326
# File 'lib/stackdriver/core/trace_context.rb', line 324

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:



283
284
285
286
287
288
289
# File 'lib/stackdriver/core/trace_context.rb', line 283

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:



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/stackdriver/core/trace_context.rb', line 227

def self.parse_string str
  match = %r|^(\w{32})(/(\d+))?(;o=(\d+))?|.match str
  if match
    trace_id = match[1]
    span_id = match[3] ? match[3].to_i : nil
    options = match[5] ? match[5].to_i : nil
    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
  else
    nil
  end
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:



306
307
308
309
# File 'lib/stackdriver/core/trace_context.rb', line 306

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)


121
122
123
# File 'lib/stackdriver/core/trace_context.rb', line 121

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)


140
141
142
143
144
145
146
147
# File 'lib/stackdriver/core/trace_context.rb', line 140

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)


155
156
157
158
# File 'lib/stackdriver/core/trace_context.rb', line 155

def hash
  @hash ||= @trace_id.hash ^ @is_new.hash ^ @span_id.hash ^
            @sampled.hash ^ @capture_stack.hash
end

#new?Boolean

Returns true if this trace includes a newly generated trace_id.

Returns:

  • (Boolean)


130
131
132
# File 'lib/stackdriver/core/trace_context.rb', line 130

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)


110
111
112
# File 'lib/stackdriver/core/trace_context.rb', line 110

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)


198
199
200
201
202
203
204
205
206
207
208
# File 'lib/stackdriver/core/trace_context.rb', line 198

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)

    New trace ID.

  • is_new (Boolean)

    New setting for newness indicator.

  • span_id (Integer)

    New parent span ID.

  • sampled (Boolean)

    New sampling decision.

  • capture_stack (Boolean)

    New stack capture decision.

Returns:



180
181
182
183
184
185
186
187
188
189
# File 'lib/stackdriver/core/trace_context.rb', line 180

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