class Instana::Tracer
Public Class Methods
# File lib/instana/tracer.rb, line 11 def method_missing(method, *args, &block) if ::Instana.tracer.respond_to?(method) ::Instana.tracer.send(method, *args, &block) else super end end
# File lib/instana/tracer.rb, line 20 def initialize(logger: Instana.logger) @current_span = Concurrent::ThreadLocalVar.new @logger = logger end
Public Instance Methods
Used in the test suite, this resets the tracer to non-tracing state.
# File lib/instana/tracer.rb, line 303 def clear! self.current_span = nil end
Retrieve the current context of the tracer.
@return [SpanContext] or nil if not tracing
# File lib/instana/tracer.rb, line 296 def context return unless self.current_span self.current_span.context end
@return [Instana::Span, NilClass] the current active span or nil if we are not tracing
# File lib/instana/tracer.rb, line 26 def current_span @current_span.value end
@param [Instana::Span, NilClas] v the new current span Set the value of the current span
# File lib/instana/tracer.rb, line 32 def current_span=(v) @current_span.value = v end
Starts a new asynchronous span on the current trace.
@param name [String] the name of the span to create @param kvs [Hash] list of key values to be reported in the span
@return [Hash] the context: Trace ID and Span
ID in the form of
:trace_id => 12345 :span_id => 12345
# File lib/instana/tracer.rb, line 224 def log_async_entry(name, kvs) return unless self.current_span new_span = Span.new(name, parent_ctx: self.current_span) new_span.set_tags(kvs) unless kvs.empty? new_span end
Add an error to an asynchronous span
@param e [Exception] Add exception to the current span @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
# File lib/instana/tracer.rb, line 246 def log_async_error(e, span) span.add_error(e) end
Closes out an asynchronous span
@param name [String] the name of the async span to exit (close out) @param kvs [Hash] list of additional key/values to be reported in the span (or use {}) @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
# File lib/instana/tracer.rb, line 256 def log_async_exit(_name, kvs, span) span.set_tags(kvs) unless kvs.empty? span.close end
Add info to an asynchronous span
@param kvs [Hash] list of key values to be reported in the span @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
# File lib/instana/tracer.rb, line 237 def log_async_info(kvs, span) span.set_tags(kvs) end
Closes out the current span in the current trace and queues the trace for reporting
@note `name` isn't really required but helps keep sanity that we're ending the span that we really want to close out.
@param name [String] the name of the span to end @param kvs [Hash] list of key values to be reported in the span
# File lib/instana/tracer.rb, line 199 def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms) return unless self.current_span if self.current_span.name != name @logger.warn "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active." end self.current_span.set_tags(kvs) self.current_span.close(end_time) self.current_span = nil end
Will establish a new span as a child of the current span in an existing trace
@param name [String, Symbol] the name of the span to create @param kvs [Hash] list of key values to be reported in the span
# File lib/instana/tracer.rb, line 135 def log_entry(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil) return unless self.current_span || child_of new_span = if child_of.is_a?(::Instana::Span) || child_of.is_a?(::Instana::SpanContext) Span.new(name, parent_ctx: child_of, start_time: start_time) else Span.new(name, parent_ctx: self.current_span, start_time: start_time) end new_span.set_tags(kvs) if kvs self.current_span = new_span end
Add an error to the current span
@param e [Exception] Add exception to the current span
# File lib/instana/tracer.rb, line 160 def log_error(e) return unless self.current_span self.current_span.add_error(e) end
Closes out the current span
@note `name` isn't really required but helps keep sanity that we're closing out the span that we really want to close out.
@param name [String, Symbol] the name of the span to exit (close out) @param kvs [Hash] list of key values to be reported in the span
# File lib/instana/tracer.rb, line 173 def log_exit(name, kvs = {}) return unless self.current_span if self.current_span.name != name @logger.warn "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active." end self.current_span.set_tags(kvs) self.current_span.close if self.current_span.parent self.current_span = self.current_span.parent else self.current_span = nil end end
Add info to the current span
@param kvs [Hash] list of key values to be reported in the span
# File lib/instana/tracer.rb, line 151 def log_info(kvs) return unless self.current_span self.current_span.set_tags(kvs) end
Will start a new trace or continue an on-going one (such as from incoming remote requests with context headers).
@param name [String, Symbol] the name of the span to start @param kvs [Hash] list of key values to be reported in the span @param incoming_context [SpanContext or Hash] specifies the incoming context. At a
minimum, it should specify :trace_id and :span_id from the following: :trace_id the trace ID (must be an unsigned hex-string) :span_id the ID of the parent span (must be an unsigned hex-string) :level specifies data collection level (optional)
# File lib/instana/tracer.rb, line 97 def log_start_or_continue(name, kvs = {}, incoming_context = nil) return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled] # Handle the potential variations on `incoming_context` if incoming_context if incoming_context.is_a?(Hash) if !incoming_context.empty? parent_context = SpanContext.new( incoming_context[:trace_id], incoming_context[:span_id], incoming_context[:level], { external_trace_id: incoming_context[:external_trace_id], external_state: incoming_context[:external_state] } ) end else parent_context = incoming_context end end if parent_context self.current_span = Span.new(name, parent_ctx: parent_context) else self.current_span = Span.new(name) end self.current_span.set_tags(kvs) unless kvs.empty? self.current_span end
Will start a new trace or continue an on-going one (such as from incoming remote requests with context headers).
@param name [String, Symbol] the name of the span to start @param kvs [Hash] list of key values to be reported in the span @param incoming_context [Hash] specifies the incoming context. At a
minimum, it should specify :trace_id and :span_id from the following: @:trace_id the trace ID (must be an unsigned hex-string) :span_id the ID of the parent span (must be an unsigned hex-string) :level specifies data collection level (optional)
# File lib/instana/tracer.rb, line 51 def start_or_continue_trace(name, kvs = {}, incoming_context = nil, &block) span = log_start_or_continue(name, kvs, incoming_context) yield(span) rescue Exception => e log_error(e) raise ensure log_end(name) end
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
@param name [String, Symbol] the name of the span to start @param kvs [Hash] list of key values to be reported in this new span
# File lib/instana/tracer.rb, line 72 def trace(name, kvs = {}, &block) span = log_entry(name, kvs) yield(span) rescue Exception => e log_error(e) raise ensure log_exit(name) end
Indicates if we're are currently in the process of collecting a trace. This is false when the host agent isn available.
@return [Boolean] true or false on whether we are currently tracing or not
# File lib/instana/tracer.rb, line 271 def tracing? # The non-nil value of this instance variable # indicates if we are currently tracing # in this thread or not. self.current_span ? true : false end
Indicates if we're tracing and the current span name matches <name>
@param name [Symbol] the name to check against the current span
@return [Boolean]
# File lib/instana/tracer.rb, line 285 def tracing_span?(name) if self.current_span return self.current_span.name == name end false end