Class: Instana::Tracer
- Inherits:
-
Object
- Object
- Instana::Tracer
- Extended by:
- ThreadLocal
- Defined in:
- lib/instana/tracer.rb
Class Method Summary collapse
Instance Method Summary collapse
-
#clear! ⇒ Object
Used in the test suite, this resets the tracer to non-tracing state.
-
#context ⇒ SpanContext
Retrieve the current context of the tracer.
-
#current_span ⇒ Object
Helper method to retrieve the currently active span for the active trace.
-
#current_span_name?(candidate) ⇒ Boolean
Indicates if the name of the current span matches <candidate>.
-
#extract(format, carrier) ⇒ SpanContext
Extract a span from a carrier.
-
#inject(span_context, format, carrier) ⇒ Object
Inject a span into the given carrier.
-
#log_async_entry(name, kvs) ⇒ Hash
Starts a new asynchronous span on the current trace.
-
#log_async_error(e, span) ⇒ Object
Add an error to an asynchronous span.
-
#log_async_exit(_name, kvs, span) ⇒ Object
Closes out an asynchronous span.
-
#log_async_info(kvs, span) ⇒ Object
Add info to an asynchronous span.
-
#log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) ⇒ Object
Closes out the current span in the current trace and queues the trace for reporting.
-
#log_entry(name, kvs = {}) ⇒ Object
Will establish a new span as a child of the current span in an existing trace.
-
#log_error(e) ⇒ Object
Add an error to the current span.
-
#log_exit(name, kvs = {}) ⇒ Object
Closes out the current span.
-
#log_info(kvs) ⇒ Object
Add info to the current span.
-
#log_start_or_continue(name, kvs = {}, incoming_context = {}) ⇒ Object
Will start a new trace or continue an on-going one (such as from incoming remote requests with context headers).
-
#span_id ⇒ Object
Returns the current [Span] ID for the active trace (if there is one), otherwise nil.
-
#span_id_header ⇒ String
Take the current span_id and convert it to a header compatible formate.
-
#start_or_continue_trace(name, kvs = {}, incoming_context = {}, &block) ⇒ Object
Will start a new trace or continue an on-going one (such as from incoming remote requests with context headers).
-
#start_span(operation_name, child_of: nil, start_time: ::Instana::Util.now_in_ms, tags: nil) ⇒ Span
Start a new span.
-
#trace(name, kvs = {}, &block) ⇒ Object
Trace a block of code within the context of the exiting trace.
-
#trace_id ⇒ Object
Returns the trace ID for the active trace (if there is one), otherwise nil.
-
#trace_id_header ⇒ String
Take the current trace_id and convert it to a header compatible format.
-
#tracing? ⇒ Boolean
Indicates if we’re are currently in the process of collecting a trace.
-
#tracing_span?(name) ⇒ Boolean
Indicates if we’re tracing and the current span name matches <name>.
Methods included from ThreadLocal
Class Method Details
Instance Method Details
#clear! ⇒ Object
Used in the test suite, this resets the tracer to non-tracing state.
413 414 415 |
# File 'lib/instana/tracer.rb', line 413 def clear! self.current_trace = nil end |
#context ⇒ SpanContext
Retrieve the current context of the tracer.
362 363 364 365 |
# File 'lib/instana/tracer.rb', line 362 def context return nil unless tracing? self.current_trace.current_span.context end |
#current_span ⇒ Object
Helper method to retrieve the currently active span for the active trace.
401 402 403 |
# File 'lib/instana/tracer.rb', line 401 def current_span self.current_trace ? self.current_trace.current_span : nil end |
#current_span_name?(candidate) ⇒ Boolean
Indicates if the name of the current span matches <candidate>
407 408 409 |
# File 'lib/instana/tracer.rb', line 407 def current_span_name?(candidate) self.current_trace && self.current_trace.current_span.name == candidate.to_sym end |
#extract(format, carrier) ⇒ SpanContext
Extract a span from a carrier
314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/instana/tracer.rb', line 314 def extract(format, carrier) case format when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY ::Instana.logger.debug 'Unsupported extract format' when OpenTracing::FORMAT_RACK ::Instana::SpanContext.new(::Instana::Util.header_to_id(carrier['HTTP_X_INSTANA_T']), ::Instana::Util.header_to_id(carrier['HTTP_X_INSTANA_S'])) else ::Instana.logger.debug 'Unknown inject format' nil end end |
#inject(span_context, format, carrier) ⇒ Object
Inject a span into the given carrier
295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/instana/tracer.rb', line 295 def inject(span_context, format, carrier) case format when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY ::Instana.logger.debug 'Unsupported inject format' when OpenTracing::FORMAT_RACK carrier['X-Instana-T'] = ::Instana::Util.id_to_header(span_context.trace_id) carrier['X-Instana-S'] = ::Instana::Util.id_to_header(span_context.span_id) else ::Instana.logger.debug 'Unknown inject format' end end |
#log_async_entry(name, kvs) ⇒ Hash
Starts a new asynchronous span on the current trace.
186 187 188 189 |
# File 'lib/instana/tracer.rb', line 186 def log_async_entry(name, kvs) return unless tracing? self.current_trace.new_async_span(name, kvs) end |
#log_async_error(e, span) ⇒ Object
Add an error to an asynchronous span
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/instana/tracer.rb', line 220 def log_async_error(e, span) # Asynchronous spans can persist longer than the parent # trace. With the trace ID, we check the current trace # but otherwise, we search staged traces. if tracing? && self.current_trace.id == span.context.trace_id self.current_trace.add_async_error(e, span) else trace = ::Instana.processor.staged_trace(span.context.trace_id) if trace trace.add_async_error(e, span) else ::Instana.logger.debug "#{__method__}: Couldn't find staged trace. #{span.inspect}" end end end |
#log_async_exit(_name, kvs, span) ⇒ Object
Closes out an asynchronous span
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/instana/tracer.rb', line 244 def log_async_exit(_name, kvs, span) # An asynchronous span can end after the current trace has # already completed so we make sure that we end the span # on the right trace. if tracing? && self.current_trace.id == span.context.trace_id self.current_trace.end_async_span(kvs, span) else # Different trace from current so find the staged trace # and close out the span on it. trace = ::Instana.processor.staged_trace(span.context.trace_id) if trace trace.end_async_span(kvs, span) else ::Instana.logger.debug "#{__method__}: Couldn't find staged trace. #{span.inspect}" end end end |
#log_async_info(kvs, span) ⇒ Object
Add info to an asynchronous span
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/instana/tracer.rb', line 197 def log_async_info(kvs, span) # Asynchronous spans can persist longer than the parent # trace. With the trace ID, we check the current trace # but otherwise, we search staged traces. if tracing? && self.current_trace.id == span.context.trace_id self.current_trace.add_async_info(kvs, span) else trace = ::Instana.processor.staged_trace(span.context.trace_id) if trace trace.add_async_info(kvs, span) else ::Instana.logger.debug "#{__method__}: Couldn't find staged trace. #{span.inspect}" end end end |
#log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) ⇒ Object
‘name` isn’t really required but helps keep sanity that
Closes out the current span in the current trace and queues the trace for reporting
we’re ending the span that we really want to close out.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/instana/tracer.rb', line 148 def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) return unless tracing? if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST') unless current_span_name?(name) ::Instana.logger.debug "Span mismatch: Attempt to end #{name} span but #{current_span.name} is active." end end self.current_trace.finish(kvs, end_time) if ::Instana.agent.ready? if !self.current_trace.has_async? || (self.current_trace.has_async? && self.current_trace.complete?) Instana.processor.add(self.current_trace) else # This trace still has outstanding/uncompleted asynchronous spans. # Put it in the staging queue until the async span closes out or # 5 minutes has passed. Whichever comes first. Instana.processor.stage(self.current_trace) end end self.current_trace = nil end |
#log_entry(name, kvs = {}) ⇒ Object
Will establish a new span as a child of the current span in an existing trace
96 97 98 99 |
# File 'lib/instana/tracer.rb', line 96 def log_entry(name, kvs = {}) return unless tracing? self.current_trace.new_span(name, kvs) end |
#log_error(e) ⇒ Object
Add an error to the current span
114 115 116 117 |
# File 'lib/instana/tracer.rb', line 114 def log_error(e) return unless tracing? self.current_trace.add_error(e) end |
#log_exit(name, kvs = {}) ⇒ Object
‘name` isn’t really required but helps keep sanity that
Closes out the current span
we’re closing out the span that we really want to close out.
127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/instana/tracer.rb', line 127 def log_exit(name, kvs = {}) return unless tracing? if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST') unless current_span_name?(name) ::Instana.logger.debug "Span mismatch: Attempt to exit #{name} span but #{current_span.name} is active." end end self.current_trace.end_span(kvs) end |
#log_info(kvs) ⇒ Object
Add info to the current span
105 106 107 108 |
# File 'lib/instana/tracer.rb', line 105 def log_info(kvs) return unless tracing? self.current_trace.add_info(kvs) end |
#log_start_or_continue(name, kvs = {}, incoming_context = {}) ⇒ Object
Will start a new trace or continue an on-going one (such as from incoming remote requests with context headers).
84 85 86 87 88 |
# File 'lib/instana/tracer.rb', line 84 def log_start_or_continue(name, kvs = {}, incoming_context = {}) return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled] ::Instana.logger.debug "#{__method__} passed a block. Use `start_or_continue` instead!" if block_given? self.current_trace = ::Instana::Trace.new(name, kvs, incoming_context) end |
#span_id ⇒ Object
Returns the current [Span] ID for the active trace (if there is one), otherwise nil.
395 396 397 |
# File 'lib/instana/tracer.rb', line 395 def span_id self.current_trace ? current_trace.current_span_id : nil end |
#span_id_header ⇒ String
Take the current span_id and convert it to a header compatible formate.
381 382 383 |
# File 'lib/instana/tracer.rb', line 381 def span_id_header ::Instana::Util.id_to_header(span_id) end |
#start_or_continue_trace(name, kvs = {}, incoming_context = {}, &block) ⇒ Object
Will start a new trace or continue an on-going one (such as from incoming remote requests with context headers).
38 39 40 41 42 43 44 45 46 |
# File 'lib/instana/tracer.rb', line 38 def start_or_continue_trace(name, kvs = {}, incoming_context = {}, &block) log_start_or_continue(name, kvs, incoming_context) yield rescue Exception => e log_error(e) raise ensure log_end(name) end |
#start_span(operation_name, child_of: nil, start_time: ::Instana::Util.now_in_ms, tags: nil) ⇒ Span
Start a new span
276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/instana/tracer.rb', line 276 def start_span(operation_name, child_of: nil, start_time: ::Instana::Util.now_in_ms, tags: nil) # return unless ::Instana.agent.ready? if tracing? span = self.current_trace.new_span(operation_name, , start_time, child_of) else self.current_trace = ::Instana::Trace.new(operation_name, , nil, start_time) span = self.current_trace.current_span end span.() span end |
#trace(name, kvs = {}, &block) ⇒ Object
Trace a block of code within the context of the exiting trace
Example usage:
::Instana.tracer.trace(:dbwork, { :db_name => @db.name }) do
@db.select(1)
end
59 60 61 62 63 64 65 66 67 |
# File 'lib/instana/tracer.rb', line 59 def trace(name, kvs = {}, &block) log_entry(name, kvs) yield rescue Exception => e log_error(e) raise ensure log_exit(name) end |
#trace_id ⇒ Object
Returns the trace ID for the active trace (if there is one), otherwise nil.
388 389 390 |
# File 'lib/instana/tracer.rb', line 388 def trace_id self.current_trace ? self.current_trace.id : nil end |
#trace_id_header ⇒ String
Take the current trace_id and convert it to a header compatible format.
372 373 374 |
# File 'lib/instana/tracer.rb', line 372 def trace_id_header ::Instana::Util.id_to_header(trace_id) end |
#tracing? ⇒ Boolean
Indicates if we’re are currently in the process of collecting a trace. This is false when the host agent isn available.
337 338 339 340 341 342 |
# File 'lib/instana/tracer.rb', line 337 def tracing? # The non-nil value of this instance variable # indicates if we are currently tracing # in this thread or not. self.current_trace ? true : false end |
#tracing_span?(name) ⇒ Boolean
Indicates if we’re tracing and the current span name matches <name>
351 352 353 354 355 356 |
# File 'lib/instana/tracer.rb', line 351 def tracing_span?(name) if self.current_trace return self.current_trace.current_span.name == name end false end |