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)
    


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
53
54
55
# File 'lib/instana/tracing/trace.rb', line 23

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

#current_spanObject (readonly)

The currently active span



11
12
13
# File 'lib/instana/tracing/trace.rb', line 11

def current_span
  @current_span
end

#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`)



160
161
162
# File 'lib/instana/tracing/trace.rb', line 160

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`)



150
151
152
# File 'lib/instana/tracing/trace.rb', line 150

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



98
99
100
101
102
103
104
# File 'lib/instana/tracing/trace.rb', line 98

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



85
86
87
88
89
90
91
92
# File 'lib/instana/tracing/trace.rb', line 85

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)


197
198
199
200
201
202
203
204
# File 'lib/instana/tracing/trace.rb', line 197

def complete?
  @spans.each do |span|
    if !span.duration
      return false
    end
  end
  true
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



234
235
236
# File 'lib/instana/tracing/trace.rb', line 234

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.



241
242
243
# File 'lib/instana/tracing/trace.rb', line 241

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)


251
252
253
# File 'lib/instana/tracing/trace.rb', line 251

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)


261
262
263
264
265
266
267
268
# File 'lib/instana/tracing/trace.rb', line 261

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`)



171
172
173
174
# File 'lib/instana/tracing/trace.rb', line 171

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



111
112
113
114
115
116
117
# File 'lib/instana/tracing/trace.rb', line 111

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)


208
209
210
# File 'lib/instana/tracing/trace.rb', line 208

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



218
219
220
221
222
223
224
225
226
227
# File 'lib/instana/tracing/trace.rb', line 218

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



133
134
135
136
137
138
139
140
141
142
# File 'lib/instana/tracing/trace.rb', line 133

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



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

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



185
186
187
188
189
190
191
192
# File 'lib/instana/tracing/trace.rb', line 185

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