lib/appoptics_apm/xtrace.rb in appoptics_apm-4.6.0 vs lib/appoptics_apm/xtrace.rb in appoptics_apm-4.7.0
- old
+ new
@@ -3,53 +3,65 @@
module AppOpticsAPM
##
# Methods to act on, manipulate or investigate an X-Trace
# value
+ #
+ # TODO add unit tests
module XTrace
class << self
##
# AppOpticsAPM::XTrace.valid?
#
- # Perform basic validation on a potential X-Trace ID
+ # Perform basic validation on a potential X-Trace Id
+ # returns true if it is from a valid context
#
def valid?(xtrace)
# Shouldn't be nil
return false unless xtrace
# The X-Trace ID shouldn't be an initialized empty ID
return false if (xtrace =~ /^2b0000000/i) == 0
# Valid X-Trace IDs have a length of 60 bytes and start with '2b'
- return false unless xtrace.length == 60 && (xtrace =~ /^2b/i) == 0
-
- true
+ xtrace.length == 60 && (xtrace =~ /^2b/i) == 0
rescue StandardError => e
AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
AppOpticsAPM.logger.debug e.backtrace
false
end
def sampled?(xtrace)
valid?(xtrace) && xtrace[59].to_i & 1 == 1
end
+ def ok?(xtrace)
+ # Valid X-Trace IDs have a length of 60 bytes and start with '2b'
+ xtrace && xtrace.length == 60 && (xtrace =~ /^2b/i) == 0
+ rescue StandardError => e
+ AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
+ AppOpticsAPM.logger.debug e.backtrace
+ false
+ end
+
def set_sampled(xtrace)
xtrace[59] = (xtrace[59].hex | 1).to_s(16).upcase
+ xtrace
end
def unset_sampled(xtrace)
xtrace[59] = (~(~xtrace[59].hex | 1)).to_s(16).upcase
+ xtrace
end
##
# AppOpticsAPM::XTrace.task_id
#
# Extract and return the task_id portion of an X-Trace ID
#
def task_id(xtrace)
- return nil unless AppOpticsAPM::XTrace.valid?(xtrace)
+ return nil unless ok?(xtrace)
xtrace[2..41]
rescue StandardError => e
AppOpticsAPM.logger.debug "[appoptics_apm/xtrace] #{e.message}"
AppOpticsAPM.logger.debug e.backtrace
@@ -77,21 +89,22 @@
# In the case of service calls such as external HTTP requests, we
# pass along X-Trace headers so that request context can be maintained
# across servers and applications.
#
# Remote requests can return a X-Trace header in which case we want
- # to pickup on and continue the context in most cases.
+ # to pickup and continue the context in most cases.
#
# +start+ is the context just before the outgoing request
# +finish+ is the context returned to us (as an HTTP response header
# if that be the case)
#
def continue_service_context(start, finish)
if AppOpticsAPM::XTrace.valid?(finish) && AppOpticsAPM.tracing?
# Assure that we received back a valid X-Trace with the same task_id
# and the sampling bit is set, otherwise it is a response from a non-sampling service
- if AppOpticsAPM::XTrace.task_id(start) == AppOpticsAPM::XTrace.task_id(finish) && AppOpticsAPM::XTrace.sampled?(finish)
+ if AppOpticsAPM::XTrace.task_id(start) == AppOpticsAPM::XTrace.task_id(finish) &&
+ AppOpticsAPM::XTrace.sampled?(finish)
AppOpticsAPM::Context.fromString(finish)
else
AppOpticsAPM.logger.debug "[XTrace] Sampling flag unset or mismatched start and finish ids:\n#{start}\n#{finish}"
end
end