Class: Instana::Trace

Inherits:
Object
  • Object
show all
Defined in:
lib/instana/tracing/trace.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, kvs = nil, incoming_context = {}, start_time = ::Instana::Util.now_in_ms) ⇒ Trace

Initializes a new instance of Trace

Parameters:

  • name (String)

    the name of the span to start

  • kvs (Hash) (defaults to: nil)

    list of key values to be reported in the span

  • incoming_context (Hash) (defaults to: {})

    specifies the incoming context. At a minimum, it should specify :trace_id and :span_id from the following:

    :trace_id the trace ID (must be an unsigned hex-string)
    :span_id the ID of the parent span (must be an unsigned hex-string)
    :level specifies data collection level (optional)
    


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/instana/tracing/trace.rb', line 20

def initialize(name, kvs = nil, incoming_context = {}, start_time = ::Instana::Util.now_in_ms)
  # The collection of spans that make
  # up this trace.
  @spans = Set.new

  # Generate a random 64bit ID for this trace
  @id = ::Instana::Util.generate_id

  # Indicates the time when this trace was started.  Used to timeout
  # traces that have asynchronous spans that never close out.
  @started_at = Time.now

  # Indicates if this trace has any asynchronous spans within it
  @has_async = false

  # This is a new trace so open the first span with the proper
  # root span IDs.
  @current_span = Span.new(name, @id, start_time: start_time)
  @current_span.set_tags(kvs) if kvs

  # Handle potential incoming context
  if !incoming_context || incoming_context.empty?
    # No incoming context. Set trace ID the same
    # as this first span.
    @current_span[:s] = @id
  else
    @id = incoming_context[:trace_id]
    @current_span[:t] = incoming_context[:trace_id]
    @current_span[:p] = incoming_context[:span_id]
  end

  @spans.add(@current_span)
end

Instance Attribute Details

#idInteger (readonly)

Returns the ID for this trace.

Returns:

  • (Integer)

    the ID for this trace



4
5
6
# File 'lib/instana/tracing/trace.rb', line 4

def id
  @id
end

#spansSet (readonly)

The collection of ‘Span` for this trace

Returns:

  • (Set)

    the collection of spans for this trace



8
9
10
# File 'lib/instana/tracing/trace.rb', line 8

def spans
  @spans
end

Instance Method Details

#add_async_error(e, span) ⇒ Object

Log an error into an asynchronous span

Parameters:

  • e (Exception)

    Add exception to the current span

  • span (Span)

    the span of this Async op (previously returned from ‘log_async_entry`)



157
158
159
# File 'lib/instana/tracing/trace.rb', line 157

def add_async_error(e, span)
  span.add_error(e)
end

#add_async_info(kvs, span) ⇒ Object

Log info into an asynchronous span

Parameters:

  • kvs (Hash)

    list of key values to be reported in the span

  • span (Span)

    the span of this Async op (previously returned from ‘log_async_entry`)



147
148
149
# File 'lib/instana/tracing/trace.rb', line 147

def add_async_info(kvs, span)
  span.set_tags(kvs)
end

#add_error(e, span = nil) ⇒ Object

Log an error into the current span

Parameters:

  • e (Exception)

    Add exception to the current span



95
96
97
98
99
100
101
# File 'lib/instana/tracing/trace.rb', line 95

def add_error(e, span = nil)
  # Return if we've already logged this exception and it
  # is just propogating up the spans.
  return if e && e.instance_variable_get(:@instana_logged) || @current_span.nil?
  span ||= @current_span
  span.add_error(e)
end

#add_info(kvs, span = nil) ⇒ Object

Add KVs to the current span

Parameters:

  • span (Span) (defaults to: nil)

    the span to add kvs to or otherwise the current span

  • kvs (Hash)

    list of key values to be reported in the span



82
83
84
85
86
87
88
89
# File 'lib/instana/tracing/trace.rb', line 82

def add_info(kvs, span = nil)
  return unless @current_span
  span ||= @current_span

  # Pass on to the OT span interface which will properly
  # apply KVs based on span type
  span.set_tags(kvs)
end

#complete?Boolean

Indicates if every span of this trace has completed. Useful when asynchronous spans potentially could run longer than the parent trace.

Returns:

  • (Boolean)


194
195
196
197
198
199
200
201
# File 'lib/instana/tracing/trace.rb', line 194

def complete?
  @spans.each do |span|
    if !span.duration
      return false
    end
  end
  true
end

#current_spanSpan

Get the current span.

Returns:



230
231
232
# File 'lib/instana/tracing/trace.rb', line 230

def current_span
  @current_span
end

#current_span_idInteger

Get the ID of the current span for this trace. Used often to place in HTTP response headers.

Returns:

  • (Integer)

    a random 64bit integer



239
240
241
# File 'lib/instana/tracing/trace.rb', line 239

def current_span_id
  @current_span.id
end

#current_span_nameObject

Get the name of the current span. Supports both registered spans and custom sdk spans.



246
247
248
# File 'lib/instana/tracing/trace.rb', line 246

def current_span_name
  @current_span.name
end

#current_span_name?(name) ⇒ Boolean

Check if the current span has the name value of <name>

Parameters:

  • name (Symbol)

    The name to be checked against.

Returns:

  • (Boolean)


256
257
258
# File 'lib/instana/tracing/trace.rb', line 256

def current_span_name?(name)
  @current_span.name == name
end

#discard?Boolean

For traces that have asynchronous spans, this method indicates whether we have hit the timeout on waiting for those async spans to close out.

Returns:

  • (Boolean)


266
267
268
269
270
271
272
273
# File 'lib/instana/tracing/trace.rb', line 266

def discard?
  # If this trace has async spans that have not closed
  # out in 5 minutes, then it's discarded.
  if has_async? && (Time.now.to_i - @started_at.to_i) > 601
    return true
  end
  false
end

#end_async_span(kvs = {}, span) ⇒ Object

End an asynchronous span

Parameters:

  • name (Symbol)

    the name of the span

  • kvs (Hash) (defaults to: {})

    list of key values to be reported in the span

  • span (Span)

    the span of this Async op (previously returned from ‘log_async_entry`)



168
169
170
171
# File 'lib/instana/tracing/trace.rb', line 168

def end_async_span(kvs = {}, span)
  span.set_tags(kvs) unless kvs.empty?
  span.close
end

#end_span(kvs = {}, end_time = ::Instana::Util.now_in_ms) ⇒ Object Also known as: finish

Close out the current span and set the parent as the current span

Parameters:

  • kvs (Hash) (defaults to: {})

    list of key values to be reported in the span



108
109
110
111
112
113
114
# File 'lib/instana/tracing/trace.rb', line 108

def end_span(kvs = {}, end_time = ::Instana::Util.now_in_ms)
  return unless @current_span

  @current_span.close(end_time)
  add_info(kvs) if kvs && !kvs.empty?
  @current_span = @current_span.parent unless @current_span.is_root?
end

#has_async?Boolean

Indicates whether this trace has any asynchronous spans.

Returns:

  • (Boolean)


205
206
207
# File 'lib/instana/tracing/trace.rb', line 205

def has_async?
  @has_async
end

#has_error?Boolean

Searches the set of spans and indicates if there is an error logged in one of them.

Returns:

  • (Boolean)

    true or false indicating the presence of an error



215
216
217
218
219
220
221
222
223
224
# File 'lib/instana/tracing/trace.rb', line 215

def has_error?
  @spans.each do |s|
    if s.key?(:error)
      if s[:error] == true
        return true
      end
    end
  end
  false
end

#new_async_span(name, kvs = {}) ⇒ Object

Start a new asynchronous span

The major differentiator between this method and simple new_span is that this method doesn’t affect @current_trace and instead returns an ID pair that can be used later to close out the created async span.

Parameters:

  • name (String)

    the name of the span to start

  • kvs (Hash) (defaults to: {})

    list of key values to be reported in the span



130
131
132
133
134
135
136
137
138
139
# File 'lib/instana/tracing/trace.rb', line 130

def new_async_span(name, kvs = {})
  new_span = Span.new(name, @id, parent_id: @current_span.id)
  new_span.set_tags(kvs) unless kvs.empty?
  new_span.parent = @current_span
  new_span[:deferred] = @has_async = true

  # Add the new span to the span collection
  @spans.add(new_span)
  new_span
end

#new_span(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil) ⇒ Object

Start a new span as a child of @current_span

Parameters:

  • name (String)

    the name of the span to start

  • kvs (Hash) (defaults to: nil)

    list of key values to be reported in the span



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/instana/tracing/trace.rb', line 59

def new_span(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil)
  return unless @current_span

  if child_of && child_of.is_a?(::Instana::Span)
    new_span = Span.new(name, @id, parent_id: child_of.id, start_time: start_time)
    new_span.parent = child_of
    new_span.baggage = child_of.baggage.dup
  else
    new_span = Span.new(name, @id, parent_id: @current_span.id, start_time: start_time)
    new_span.parent = @current_span
    new_span.baggage = @current_span.baggage.dup
  end
  new_span.set_tags(kvs) if kvs

  @spans.add(new_span)
  @current_span = new_span
end

#valid?Boolean

Indicates whether all seems ok with this trace in it’s current state. Should be only called on finished traces.

Returns:

  • (Boolean)

    true or false on whether this trace is valid



182
183
184
185
186
187
188
189
# File 'lib/instana/tracing/trace.rb', line 182

def valid?
  @spans.each do |span|
    unless span.key?(:d)
      return false
    end
  end
  true
end