Class: Instana::Tracer
- Inherits:
-
Object
- Object
- Instana::Tracer
- Extended by:
- ThreadLocal
- Defined in:
- lib/instana/tracer.rb
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
Instance Method Details
#clear! ⇒ Object
Used in the test suite, this resets the tracer to non-tracing state.
403 404 405 |
# File 'lib/instana/tracer.rb', line 403 def clear! self.current_trace = nil end |
#context ⇒ SpanContext
Retrieve the current context of the tracer.
352 353 354 355 |
# File 'lib/instana/tracer.rb', line 352 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.
391 392 393 |
# File 'lib/instana/tracer.rb', line 391 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>
397 398 399 |
# File 'lib/instana/tracer.rb', line 397 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
304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/instana/tracer.rb', line 304 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
285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/instana/tracer.rb', line 285 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.
176 177 178 179 |
# File 'lib/instana/tracer.rb', line 176 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
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/instana/tracer.rb', line 210 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
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/instana/tracer.rb', line 234 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
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/instana/tracer.rb', line 187 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.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/instana/tracer.rb', line 138 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
86 87 88 89 |
# File 'lib/instana/tracer.rb', line 86 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
104 105 106 107 |
# File 'lib/instana/tracer.rb', line 104 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.
117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/instana/tracer.rb', line 117 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
95 96 97 98 |
# File 'lib/instana/tracer.rb', line 95 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).
74 75 76 77 78 |
# File 'lib/instana/tracer.rb', line 74 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.
385 386 387 |
# File 'lib/instana/tracer.rb', line 385 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.
371 372 373 |
# File 'lib/instana/tracer.rb', line 371 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).
27 28 29 30 31 32 33 34 35 |
# File 'lib/instana/tracer.rb', line 27 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
266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/instana/tracer.rb', line 266 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
48 49 50 51 52 53 54 55 56 57 |
# File 'lib/instana/tracer.rb', line 48 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.
378 379 380 |
# File 'lib/instana/tracer.rb', line 378 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.
362 363 364 |
# File 'lib/instana/tracer.rb', line 362 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.
327 328 329 330 331 332 |
# File 'lib/instana/tracer.rb', line 327 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>
341 342 343 344 345 346 |
# File 'lib/instana/tracer.rb', line 341 def tracing_span?(name) if self.current_trace return self.current_trace.current_span.name == name end false end |