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 = Time.now) ⇒ 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: Time.now, 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.
401 402 403 |
# File 'lib/instana/tracer.rb', line 401 def clear! self.current_trace = nil end |
#context ⇒ SpanContext
Retrieve the current context of the tracer.
350 351 352 353 |
# File 'lib/instana/tracer.rb', line 350 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.
389 390 391 |
# File 'lib/instana/tracer.rb', line 389 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>
395 396 397 |
# File 'lib/instana/tracer.rb', line 395 def current_span_name?(candidate) self.current_trace && self.current_trace.current_span.name == candidate end |
#extract(format, carrier) ⇒ SpanContext
Extract a span from a carrier
302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/instana/tracer.rb', line 302 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
283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/instana/tracer.rb', line 283 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.
174 175 176 177 |
# File 'lib/instana/tracer.rb', line 174 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
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/instana/tracer.rb', line 208 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
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/instana/tracer.rb', line 232 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
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/instana/tracer.rb', line 185 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 = Time.now) ⇒ 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 |
# File 'lib/instana/tracer.rb', line 138 def log_end(name, kvs = {}, end_time = Time.now) 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 !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 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.
383 384 385 |
# File 'lib/instana/tracer.rb', line 383 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.
369 370 371 |
# File 'lib/instana/tracer.rb', line 369 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: Time.now, tags: nil) ⇒ Span
Start a new span
264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/instana/tracer.rb', line 264 def start_span(operation_name, child_of: nil, start_time: Time.now, 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.
376 377 378 |
# File 'lib/instana/tracer.rb', line 376 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.
360 361 362 |
# File 'lib/instana/tracer.rb', line 360 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.
325 326 327 328 329 330 |
# File 'lib/instana/tracer.rb', line 325 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>
339 340 341 342 343 344 |
# File 'lib/instana/tracer.rb', line 339 def tracing_span?(name) if self.current_trace return self.current_trace.current_span.name == name end false end |