Class: Instana::Trace
- Inherits:
-
Object
- Object
- Instana::Trace
- Defined in:
- lib/instana/tracing/trace.rb
Constant Summary collapse
- REGISTERED_SPANS =
[ :rack, :'net-http', :excon ]
Instance Attribute Summary collapse
-
#id ⇒ Integer
readonly
The ID for this trace.
-
#spans ⇒ Set
readonly
The collection of ‘Span` for this trace.
Instance Method Summary collapse
-
#add_async_error(e, ids) ⇒ Object
Log an error into an asynchronous span.
-
#add_async_info(kvs, ids) ⇒ Object
Log info into an asynchronous span.
-
#add_error(e, span = nil) ⇒ Object
Log an error into the current span.
-
#add_info(kvs, span = nil) ⇒ Object
Add KVs to the current span.
-
#complete? ⇒ Boolean
Indicates if every span of this trace has completed.
-
#current_span_id ⇒ Integer
Get the ID of the current span for this trace.
-
#current_span_name ⇒ Object
Get the name of the current span.
-
#current_span_name?(name) ⇒ Boolean
Check if the current span has the name value of <name>.
-
#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.
-
#end_async_span(kvs = {}, ids) ⇒ Object
End an asynchronous span.
-
#end_span(kvs = {}) ⇒ Object
Close out the current span and set the parent as the current span.
-
#finish(kvs = {}) ⇒ Object
Closes out the final span in this trace and runs any finalizer steps required.
-
#has_async? ⇒ Boolean
Indicates whether this trace has any asynchronous spans.
-
#has_error? ⇒ Boolean
Searches the set of spans and indicates if there is an error logged in one of them.
-
#initialize(name, kvs = {}, incoming_context = {}) ⇒ Trace
constructor
Initializes a new instance of Trace.
-
#new_async_span(name, kvs) ⇒ Object
Start a new asynchronous span.
-
#new_span(name, kvs) ⇒ Object
Start a new span as a child of @current_span.
-
#valid? ⇒ Boolean
Indicates whether all seems ok with this trace in it’s current state.
Constructor Details
#initialize(name, kvs = {}, incoming_context = {}) ⇒ Trace
Initializes a new instance of Trace
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/instana/tracing/trace.rb', line 22 def initialize(name, kvs = {}, incoming_context = {}) # The collection of spans that make # up this trace. @spans = Set.new # The current active span @current_span = nil # Generate a random 64bit ID for this trace @id = 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({ :s => @id, # Span ID :ts => ts_now, # Timestamp :ta => :ruby, # Agent :f => { :e => ::Instana.agent.report_pid, :h => ::Instana.agent.agent_uuid } # Entity Source }) # Check for custom tracing if !REGISTERED_SPANS.include?(name.to_sym) configure_custom_span(nil, name, kvs) else @current_span[:n] = name.to_sym @current_span[:data] = kvs end # Handle potential incoming context if incoming_context.empty? # No incoming context. Set trace ID the same # as this first span. @current_span[:t] = @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
#id ⇒ Integer (readonly)
Returns the ID for this trace.
6 7 8 |
# File 'lib/instana/tracing/trace.rb', line 6 def id @id end |
#spans ⇒ Set (readonly)
The collection of ‘Span` for this trace
10 11 12 |
# File 'lib/instana/tracing/trace.rb', line 10 def spans @spans end |
Instance Method Details
#add_async_error(e, ids) ⇒ Object
Log an error into an asynchronous span
225 226 227 228 229 |
# File 'lib/instana/tracing/trace.rb', line 225 def add_async_error(e, ids) @spans.each do |span| add_error(e, span) if span.id == ids[:span_id] end end |
#add_async_info(kvs, ids) ⇒ Object
Log info into an asynchronous span
212 213 214 215 216 217 218 |
# File 'lib/instana/tracing/trace.rb', line 212 def add_async_info(kvs, ids) @spans.each do |span| if span.id == ids[:span_id] add_info(kvs, span) end end end |
#add_error(e, span = nil) ⇒ Object
Log an error into the current span
132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/instana/tracing/trace.rb', line 132 def add_error(e, span = nil) span ||= @current_span span[:error] = true if span.key?(:ec) span[:ec] = span[:ec] + 1 else span[:ec] = 1 end end |
#add_info(kvs, span = nil) ⇒ Object
Add KVs to the current span
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/instana/tracing/trace.rb', line 106 def add_info(kvs, span = nil) span ||= @current_span if span.custom? if span[:data][:sdk].key?(:custom) span[:data][:sdk][:custom].merge!(kvs) else span[:data][:sdk][:custom] = kvs end else kvs.each_pair do |k,v| if !span[:data].key?(k) span[:data][k] = v elsif v.is_a?(Hash) && span[:data][k].is_a?(Hash) span[:data][k].merge!(v) else span[:data][k] = v end end end end |
#complete? ⇒ Boolean
Indicates if every span of this trace has completed. Useful when asynchronous spans potentially could run longer than the parent trace.
268 269 270 271 272 273 274 275 |
# File 'lib/instana/tracing/trace.rb', line 268 def complete? @spans.each do |span| if !span.duration return false end end true end |
#current_span_id ⇒ Integer
Get the ID of the current span for this trace. Used often to place in HTTP response headers.
305 306 307 |
# File 'lib/instana/tracing/trace.rb', line 305 def current_span_id @current_span.id end |
#current_span_name ⇒ Object
Get the name of the current span. Supports both registered spans and custom sdk spans.
312 313 314 |
# File 'lib/instana/tracing/trace.rb', line 312 def current_span_name @current_span.name end |
#current_span_name?(name) ⇒ Boolean
Check if the current span has the name value of <name>
322 323 324 |
# File 'lib/instana/tracing/trace.rb', line 322 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.
332 333 334 335 336 337 338 339 |
# File 'lib/instana/tracing/trace.rb', line 332 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 = {}, ids) ⇒ Object
End an asynchronous span
239 240 241 242 243 244 245 246 |
# File 'lib/instana/tracing/trace.rb', line 239 def end_async_span(kvs = {}, ids) @spans.each do |span| if span.id == ids[:span_id] span[:d] = ts_now - span[:ts] add_info(kvs, span) unless kvs.empty? end end end |
#end_span(kvs = {}) ⇒ Object
Close out the current span and set the parent as the current span
149 150 151 152 153 |
# File 'lib/instana/tracing/trace.rb', line 149 def end_span(kvs = {}) @current_span[:d] = ts_now - @current_span[:ts] add_info(kvs) unless kvs.empty? @current_span = @current_span.parent unless @current_span.is_root? end |
#finish(kvs = {}) ⇒ Object
Closes out the final span in this trace and runs any finalizer steps required. This should be called only on the root span to end the trace.
161 162 163 |
# File 'lib/instana/tracing/trace.rb', line 161 def finish(kvs = {}) end_span(kvs) end |
#has_async? ⇒ Boolean
Indicates whether this trace has any asynchronous spans.
279 280 281 |
# File 'lib/instana/tracing/trace.rb', line 279 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.
289 290 291 292 293 294 295 296 297 298 |
# File 'lib/instana/tracing/trace.rb', line 289 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.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/instana/tracing/trace.rb', line 178 def new_async_span(name, kvs) new_span = Span.new({ :s => generate_id, # Span ID :t => @id, # Trace ID (same as :s for root span) :p => @current_span.id, # Parent ID :ts => ts_now, # Timestamp :ta => :ruby, # Agent :async => true, # Asynchonous :f => { :e => Process.pid, :h => :agent_id } # Entity Source }) new_span.parent = @current_span @has_async = true # Check for custom tracing if !REGISTERED_SPANS.include?(name.to_sym) configure_custom_span(new_span, name, kvs) else new_span[:n] = name.to_sym new_span[:data] = kvs end # Add the new span to the span collection @spans.add(new_span) { :trace_id => new_span[:t], :span_id => new_span.id } end |
#new_span(name, kvs) ⇒ Object
Start a new span as a child of @current_span
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/instana/tracing/trace.rb', line 76 def new_span(name, kvs) return unless @current_span new_span = Span.new({ :s => generate_id, # Span ID :t => @id, # Trace ID (same as :s for root span) :p => @current_span.id, # Parent ID :ts => ts_now, # Timestamp :ta => :ruby, # Agent :f => { :e => Process.pid, :h => :agent_id } # Entity Source }) new_span.parent = @current_span @spans.add(new_span) @current_span = new_span # Check for custom tracing if !REGISTERED_SPANS.include?(name.to_sym) configure_custom_span(nil, name, kvs) else @current_span[:n] = name.to_sym @current_span[:data] = kvs end end |
#valid? ⇒ Boolean
Indicates whether all seems ok with this trace in it’s current state. Should be only called on finished traces.
257 258 259 260 261 262 263 |
# File 'lib/instana/tracing/trace.rb', line 257 def valid? @spans.each do |span| unless span.key?(:d) return false end end end |