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.
414 415 416 |
# File 'lib/instana/tracer.rb', line 414 def clear! self.current_trace = nil end |
#context ⇒ SpanContext
Retrieve the current context of the tracer.
363 364 365 366 |
# File 'lib/instana/tracer.rb', line 363 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.
402 403 404 |
# File 'lib/instana/tracer.rb', line 402 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>
408 409 410 |
# File 'lib/instana/tracer.rb', line 408 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
315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/instana/tracer.rb', line 315 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
296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/instana/tracer.rb', line 296 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.
187 188 189 190 |
# File 'lib/instana/tracer.rb', line 187 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
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/instana/tracer.rb', line 221 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
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/instana/tracer.rb', line 245 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
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/instana/tracer.rb', line 198 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.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/instana/tracer.rb', line 149 def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) return unless tracing? if ::Instana.debug? || ::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
97 98 99 100 |
# File 'lib/instana/tracer.rb', line 97 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
115 116 117 118 |
# File 'lib/instana/tracer.rb', line 115 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.
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/instana/tracer.rb', line 128 def log_exit(name, kvs = {}) return unless tracing? if ::Instana.debug? || ::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
106 107 108 109 |
# File 'lib/instana/tracer.rb', line 106 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).
85 86 87 88 89 |
# File 'lib/instana/tracer.rb', line 85 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.
396 397 398 |
# File 'lib/instana/tracer.rb', line 396 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.
382 383 384 |
# File 'lib/instana/tracer.rb', line 382 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) block.call 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
277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/instana/tracer.rb', line 277 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 68 |
# File 'lib/instana/tracer.rb', line 59 def trace(name, kvs = {}, &block) log_entry(name, kvs) result = block.call result 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.
389 390 391 |
# File 'lib/instana/tracer.rb', line 389 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.
373 374 375 |
# File 'lib/instana/tracer.rb', line 373 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.
338 339 340 341 342 343 |
# File 'lib/instana/tracer.rb', line 338 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>
352 353 354 355 356 357 |
# File 'lib/instana/tracer.rb', line 352 def tracing_span?(name) if self.current_trace return self.current_trace.current_span.name == name end false end |