instana 1.10.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +23 -0
- data/.gitignore +16 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +43 -0
- data/Configuration.md +149 -0
- data/Dockerfile +13 -0
- data/Gemfile +41 -0
- data/LICENSE +21 -0
- data/README.md +102 -0
- data/Rakefile +56 -0
- data/Tracing.md +145 -0
- data/Troubleshooting.md +32 -0
- data/benchmarks/Gemfile +7 -0
- data/benchmarks/id_generation.rb +12 -0
- data/benchmarks/opentracing.rb +26 -0
- data/benchmarks/rack_vanilla_vs_traced.rb +80 -0
- data/benchmarks/stackprof_rack_tracing.rb +77 -0
- data/benchmarks/time_processing.rb +12 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/examples/opentracing.rb +31 -0
- data/examples/tracing.rb +80 -0
- data/gemfiles/libraries.gemfile +71 -0
- data/gemfiles/rails32.gemfile +51 -0
- data/gemfiles/rails42.gemfile +50 -0
- data/gemfiles/rails50.gemfile +52 -0
- data/instana.gemspec +46 -0
- data/lib/instana.rb +12 -0
- data/lib/instana/agent.rb +441 -0
- data/lib/instana/agent/helpers.rb +61 -0
- data/lib/instana/agent/hooks.rb +37 -0
- data/lib/instana/agent/tasks.rb +48 -0
- data/lib/instana/base.rb +54 -0
- data/lib/instana/collector.rb +116 -0
- data/lib/instana/collectors/gc.rb +57 -0
- data/lib/instana/collectors/memory.rb +34 -0
- data/lib/instana/collectors/thread.rb +30 -0
- data/lib/instana/config.rb +79 -0
- data/lib/instana/eum/eum-test.js.erb +16 -0
- data/lib/instana/eum/eum.js.erb +14 -0
- data/lib/instana/frameworks/cuba.rb +6 -0
- data/lib/instana/frameworks/instrumentation/abstract_mysql_adapter.rb +58 -0
- data/lib/instana/frameworks/instrumentation/action_controller.rb +183 -0
- data/lib/instana/frameworks/instrumentation/action_view.rb +43 -0
- data/lib/instana/frameworks/instrumentation/active_record.rb +27 -0
- data/lib/instana/frameworks/instrumentation/mysql2_adapter.rb +81 -0
- data/lib/instana/frameworks/instrumentation/mysql_adapter.rb +56 -0
- data/lib/instana/frameworks/instrumentation/postgresql_adapter.rb +71 -0
- data/lib/instana/frameworks/rails.rb +42 -0
- data/lib/instana/frameworks/roda.rb +6 -0
- data/lib/instana/frameworks/sinatra.rb +9 -0
- data/lib/instana/helpers.rb +40 -0
- data/lib/instana/instrumentation.rb +21 -0
- data/lib/instana/instrumentation/dalli.rb +78 -0
- data/lib/instana/instrumentation/excon.rb +74 -0
- data/lib/instana/instrumentation/grpc.rb +84 -0
- data/lib/instana/instrumentation/net-http.rb +66 -0
- data/lib/instana/instrumentation/rack.rb +77 -0
- data/lib/instana/instrumentation/redis.rb +82 -0
- data/lib/instana/instrumentation/resque.rb +131 -0
- data/lib/instana/instrumentation/rest-client.rb +34 -0
- data/lib/instana/instrumentation/sidekiq-client.rb +45 -0
- data/lib/instana/instrumentation/sidekiq-worker.rb +54 -0
- data/lib/instana/opentracing/carrier.rb +4 -0
- data/lib/instana/opentracing/tracer.rb +18 -0
- data/lib/instana/rack.rb +10 -0
- data/lib/instana/setup.rb +36 -0
- data/lib/instana/test.rb +40 -0
- data/lib/instana/thread_local.rb +15 -0
- data/lib/instana/tracer.rb +392 -0
- data/lib/instana/tracing/processor.rb +92 -0
- data/lib/instana/tracing/span.rb +401 -0
- data/lib/instana/tracing/span_context.rb +33 -0
- data/lib/instana/util.rb +261 -0
- data/lib/instana/version.rb +4 -0
- data/lib/oj_check.rb +16 -0
- data/lib/opentracing.rb +6 -0
- data/test/agent/agent_test.rb +143 -0
- data/test/apps/cuba.rb +15 -0
- data/test/apps/grpc_server.rb +81 -0
- data/test/apps/roda.rb +10 -0
- data/test/apps/sinatra.rb +5 -0
- data/test/benchmarks/bench_id_generation.rb +12 -0
- data/test/benchmarks/bench_opentracing.rb +13 -0
- data/test/config_test.rb +37 -0
- data/test/frameworks/cuba_test.rb +44 -0
- data/test/frameworks/rack_test.rb +167 -0
- data/test/frameworks/rails/actioncontroller_test.rb +93 -0
- data/test/frameworks/rails/actionview3_test.rb +255 -0
- data/test/frameworks/rails/actionview4_test.rb +254 -0
- data/test/frameworks/rails/actionview5_test.rb +221 -0
- data/test/frameworks/rails/activerecord3_test.rb +134 -0
- data/test/frameworks/rails/activerecord4_test.rb +134 -0
- data/test/frameworks/rails/activerecord5_test.rb +87 -0
- data/test/frameworks/roda_test.rb +44 -0
- data/test/frameworks/sinatra_test.rb +44 -0
- data/test/instana_test.rb +27 -0
- data/test/instrumentation/dalli_test.rb +253 -0
- data/test/instrumentation/excon_test.rb +147 -0
- data/test/instrumentation/grpc_test.rb +377 -0
- data/test/instrumentation/net-http_test.rb +160 -0
- data/test/instrumentation/redis_test.rb +119 -0
- data/test/instrumentation/resque_test.rb +128 -0
- data/test/instrumentation/rest-client_test.rb +55 -0
- data/test/instrumentation/sidekiq-client_test.rb +125 -0
- data/test/instrumentation/sidekiq-worker_test.rb +173 -0
- data/test/jobs/resque_error_job.rb +22 -0
- data/test/jobs/resque_fast_job.rb +20 -0
- data/test/jobs/sidekiq_job_1.rb +6 -0
- data/test/jobs/sidekiq_job_2.rb +7 -0
- data/test/models/block.rb +18 -0
- data/test/servers/grpc_50051.rb +20 -0
- data/test/servers/helpers/sidekiq_worker_initializer.rb +27 -0
- data/test/servers/rackapp_6511.rb +25 -0
- data/test/servers/rails_3205.rb +167 -0
- data/test/servers/sidekiq/worker.rb +27 -0
- data/test/test_helper.rb +145 -0
- data/test/tracing/custom_test.rb +158 -0
- data/test/tracing/id_management_test.rb +130 -0
- data/test/tracing/opentracing_test.rb +335 -0
- data/test/tracing/trace_test.rb +67 -0
- data/test/tracing/tracer_async_test.rb +198 -0
- data/test/tracing/tracer_test.rb +223 -0
- metadata +327 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module OpenTracing
|
|
2
|
+
class << self
|
|
3
|
+
# Text format for #inject and #extract
|
|
4
|
+
FORMAT_TEXT_MAP = 1
|
|
5
|
+
|
|
6
|
+
# Binary format for #inject and #extract
|
|
7
|
+
FORMAT_BINARY = 2
|
|
8
|
+
|
|
9
|
+
# Ruby Specific format to handle how Rack changes environment variables.
|
|
10
|
+
FORMAT_RACK = 3
|
|
11
|
+
|
|
12
|
+
attr_accessor :global_tracer
|
|
13
|
+
|
|
14
|
+
def method_missing(method_name, *args, &block)
|
|
15
|
+
@global_tracer.send(method_name, *args, &block)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/instana/rack.rb
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# This file exists to just make the Instana::Rack require calls a bit more
|
|
2
|
+
# user friendly.
|
|
3
|
+
#
|
|
4
|
+
# The real file is in the instrumentation subdirectory:
|
|
5
|
+
# lib/instana/instrumentation/rack.rb
|
|
6
|
+
#
|
|
7
|
+
# require 'instana/rack'
|
|
8
|
+
# config.middleware.use ::Instana::Rack
|
|
9
|
+
#
|
|
10
|
+
require 'instana/instrumentation/rack'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'oj_check'
|
|
2
|
+
|
|
3
|
+
require "instana/base"
|
|
4
|
+
require "instana/config"
|
|
5
|
+
require "instana/agent"
|
|
6
|
+
require "instana/collector"
|
|
7
|
+
require "instana/tracer"
|
|
8
|
+
require "instana/tracing/processor"
|
|
9
|
+
require "instana/instrumentation"
|
|
10
|
+
|
|
11
|
+
::Instana.setup
|
|
12
|
+
::Instana.agent.setup
|
|
13
|
+
|
|
14
|
+
# Register the metric collectors
|
|
15
|
+
unless RUBY_PLATFORM == 'java'.freeze
|
|
16
|
+
require 'instana/collectors/gc'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
require 'instana/collectors/memory'
|
|
20
|
+
require 'instana/collectors/thread'
|
|
21
|
+
|
|
22
|
+
# Require supported OpenTracing interfaces
|
|
23
|
+
require "opentracing"
|
|
24
|
+
|
|
25
|
+
# The Instana agent is now setup. The only remaining
|
|
26
|
+
# task for a complete boot is to call
|
|
27
|
+
# `Instana.agent.start` in the thread of your choice.
|
|
28
|
+
# This can be in a simple `Thread.new` block or
|
|
29
|
+
# any other thread system you may use (e.g. actor
|
|
30
|
+
# threads).
|
|
31
|
+
#
|
|
32
|
+
# Note that `start` should only be called once per process.
|
|
33
|
+
#
|
|
34
|
+
# Thread.new do
|
|
35
|
+
# ::Instana.agent.start
|
|
36
|
+
# end
|
data/lib/instana/test.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Instana
|
|
2
|
+
class Test
|
|
3
|
+
class << self
|
|
4
|
+
# Used at the start of the test suite to configure required environment
|
|
5
|
+
# variables (if missing)
|
|
6
|
+
#
|
|
7
|
+
def setup_environment
|
|
8
|
+
# Set defaults if not set
|
|
9
|
+
ENV['MEMCACHED_HOST'] ||= '127.0.0.1:11211'
|
|
10
|
+
ENV['TRAVIS_PSQL_HOST'] ||= "127.0.0.1"
|
|
11
|
+
ENV['TRAVIS_PSQL_USER'] ||= "postgres"
|
|
12
|
+
ENV['TRAVIS_MYSQL_HOST'] ||= "127.0.0.1"
|
|
13
|
+
ENV['TRAVIS_MYSQL_USER'] ||= "root"
|
|
14
|
+
|
|
15
|
+
if ENV['DB_FLAVOR'] == 'postgresql'
|
|
16
|
+
ENV['DATABASE_URL'] = "postgresql://#{ENV['TRAVIS_PSQL_USER']}:#{ENV['TRAVIS_PSQL_PASS']}@#{ENV['TRAVIS_PSQL_HOST']}:5432/travis_ci_test"
|
|
17
|
+
elsif ENV['DB_FLAVOR'] == 'mysql'
|
|
18
|
+
ENV['DATABASE_URL'] = "mysql://#{ENV['TRAVIS_MYSQL_USER']}:#{ENV['TRAVIS_MYSQL_PASS']}@#{ENV['TRAVIS_MYSQL_HOST']}:3306/travis_ci_test"
|
|
19
|
+
else
|
|
20
|
+
ENV['DB_FLAVOR'] ||= 'mysql2'
|
|
21
|
+
ENV['DATABASE_URL'] = "mysql2://#{ENV['TRAVIS_MYSQL_USER']}:#{ENV['TRAVIS_MYSQL_PASS']}@#{ENV['TRAVIS_MYSQL_HOST']}:3306/travis_ci_test"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
Instana.logger.warn "Database connect string configured to: #{ENV['DATABASE_URL']}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def postgresql?
|
|
28
|
+
ENV['DB_FLAVOR'] == 'postgresql'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def mysql2?
|
|
32
|
+
ENV['DB_FLAVOR'] == 'mysql2'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def mysql?
|
|
36
|
+
ENV['DB_FLAVOR'] == 'mysql'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Instana
|
|
2
|
+
module ThreadLocal
|
|
3
|
+
def thread_local(name)
|
|
4
|
+
key = "__#{self}_#{name}__".intern
|
|
5
|
+
|
|
6
|
+
define_method(name) do
|
|
7
|
+
Thread.current[key]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
define_method(name.to_s + '=') do |value|
|
|
11
|
+
Thread.current[key] = value
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
require "instana/thread_local"
|
|
2
|
+
require "instana/tracing/span"
|
|
3
|
+
require "instana/tracing/span_context"
|
|
4
|
+
|
|
5
|
+
module Instana
|
|
6
|
+
class Tracer
|
|
7
|
+
extend ::Instana::ThreadLocal
|
|
8
|
+
|
|
9
|
+
thread_local :current_span
|
|
10
|
+
|
|
11
|
+
# Support ::Instana::Tracer.xxx call style for the instantiated tracer
|
|
12
|
+
class << self
|
|
13
|
+
def method_missing(method, *args, &block)
|
|
14
|
+
if ::Instana.tracer.respond_to?(method)
|
|
15
|
+
::Instana.tracer.send(method, *args, &block)
|
|
16
|
+
else
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#######################################
|
|
23
|
+
# Tracing blocks API methods
|
|
24
|
+
#######################################
|
|
25
|
+
|
|
26
|
+
# Will start a new trace or continue an on-going one (such as
|
|
27
|
+
# from incoming remote requests with context headers).
|
|
28
|
+
#
|
|
29
|
+
# @param name [String] the name of the span to start
|
|
30
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
31
|
+
# @param incoming_context [Hash] specifies the incoming context. At a
|
|
32
|
+
# minimum, it should specify :trace_id and :span_id from the following:
|
|
33
|
+
# @:trace_id the trace ID (must be an unsigned hex-string)
|
|
34
|
+
# :span_id the ID of the parent span (must be an unsigned hex-string)
|
|
35
|
+
# :level specifies data collection level (optional)
|
|
36
|
+
#
|
|
37
|
+
def start_or_continue_trace(name, kvs = {}, incoming_context = nil, &block)
|
|
38
|
+
log_start_or_continue(name, kvs, incoming_context)
|
|
39
|
+
yield
|
|
40
|
+
rescue Exception => e
|
|
41
|
+
log_error(e)
|
|
42
|
+
raise
|
|
43
|
+
ensure
|
|
44
|
+
log_end(name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Trace a block of code within the context of the exiting trace
|
|
48
|
+
#
|
|
49
|
+
# Example usage:
|
|
50
|
+
#
|
|
51
|
+
# ::Instana.tracer.trace(:dbwork, { :db_name => @db.name }) do
|
|
52
|
+
# @db.select(1)
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# @param name [String] the name of the span to start
|
|
56
|
+
# @param kvs [Hash] list of key values to be reported in this new span
|
|
57
|
+
#
|
|
58
|
+
def trace(name, kvs = {}, &block)
|
|
59
|
+
log_entry(name, kvs)
|
|
60
|
+
yield
|
|
61
|
+
rescue Exception => e
|
|
62
|
+
log_error(e)
|
|
63
|
+
raise
|
|
64
|
+
ensure
|
|
65
|
+
log_exit(name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#######################################
|
|
69
|
+
# Lower level tracing API methods
|
|
70
|
+
#######################################
|
|
71
|
+
|
|
72
|
+
# Will start a new trace or continue an on-going one (such as
|
|
73
|
+
# from incoming remote requests with context headers).
|
|
74
|
+
#
|
|
75
|
+
# @param name [String] the name of the span to start
|
|
76
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
77
|
+
# @param incoming_context [SpanContext or Hash] specifies the incoming context. At a
|
|
78
|
+
# minimum, it should specify :trace_id and :span_id from the following:
|
|
79
|
+
# :trace_id the trace ID (must be an unsigned hex-string)
|
|
80
|
+
# :span_id the ID of the parent span (must be an unsigned hex-string)
|
|
81
|
+
# :level specifies data collection level (optional)
|
|
82
|
+
#
|
|
83
|
+
def log_start_or_continue(name, kvs = {}, incoming_context = nil)
|
|
84
|
+
return if !::Instana.agent.ready? || !::Instana.config[:tracing][:enabled]
|
|
85
|
+
::Instana.logger.debug { "#{__method__} passed a block. Use `start_or_continue` instead!" } if block_given?
|
|
86
|
+
|
|
87
|
+
# Handle the potential variations on `incoming_context`
|
|
88
|
+
if incoming_context
|
|
89
|
+
if incoming_context.is_a?(Hash)
|
|
90
|
+
if !incoming_context.empty?
|
|
91
|
+
parent_context = SpanContext.new(incoming_context[:trace_id], incoming_context[:span_id], incoming_context[:level])
|
|
92
|
+
end
|
|
93
|
+
else
|
|
94
|
+
parent_context = incoming_context
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if parent_context
|
|
99
|
+
self.current_span = Span.new(name, parent_ctx: parent_context)
|
|
100
|
+
else
|
|
101
|
+
self.current_span = Span.new(name)
|
|
102
|
+
end
|
|
103
|
+
self.current_span.set_tags(kvs) unless kvs.empty?
|
|
104
|
+
self.current_span
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Will establish a new span as a child of the current span
|
|
108
|
+
# in an existing trace
|
|
109
|
+
#
|
|
110
|
+
# @param name [String] the name of the span to create
|
|
111
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
112
|
+
#
|
|
113
|
+
def log_entry(name, kvs = nil, start_time = ::Instana::Util.now_in_ms, child_of = nil)
|
|
114
|
+
return unless self.current_span || child_of
|
|
115
|
+
|
|
116
|
+
if child_of && (child_of.is_a?(::Instana::Span) || child_of.is_a?(::Instana::SpanContext))
|
|
117
|
+
new_span = Span.new(name, parent_ctx: child_of, start_time: start_time)
|
|
118
|
+
else
|
|
119
|
+
new_span = Span.new(name, parent_ctx: self.current_span, start_time: start_time)
|
|
120
|
+
end
|
|
121
|
+
new_span.set_tags(kvs) if kvs
|
|
122
|
+
self.current_span = new_span
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Add info to the current span
|
|
126
|
+
#
|
|
127
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
128
|
+
#
|
|
129
|
+
def log_info(kvs)
|
|
130
|
+
return unless self.current_span
|
|
131
|
+
self.current_span.set_tags(kvs)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Add an error to the current span
|
|
135
|
+
#
|
|
136
|
+
# @param e [Exception] Add exception to the current span
|
|
137
|
+
#
|
|
138
|
+
def log_error(e)
|
|
139
|
+
return unless self.current_span
|
|
140
|
+
self.current_span.add_error(e)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Closes out the current span
|
|
144
|
+
#
|
|
145
|
+
# @note `name` isn't really required but helps keep sanity that
|
|
146
|
+
# we're closing out the span that we really want to close out.
|
|
147
|
+
#
|
|
148
|
+
# @param name [String] the name of the span to exit (close out)
|
|
149
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
150
|
+
#
|
|
151
|
+
def log_exit(name, kvs = {})
|
|
152
|
+
return unless self.current_span
|
|
153
|
+
|
|
154
|
+
if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST')
|
|
155
|
+
unless self.current_span.name == name
|
|
156
|
+
::Instana.logger.debug "Span mismatch: Attempt to exit #{name} span but #{self.current_span.name} is active."
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
self.current_span.set_tags(kvs)
|
|
161
|
+
self.current_span.close
|
|
162
|
+
|
|
163
|
+
if self.current_span.parent
|
|
164
|
+
self.current_span = self.current_span.parent
|
|
165
|
+
else
|
|
166
|
+
self.current_span = nil
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Closes out the current span in the current trace
|
|
171
|
+
# and queues the trace for reporting
|
|
172
|
+
#
|
|
173
|
+
# @note `name` isn't really required but helps keep sanity that
|
|
174
|
+
# we're ending the span that we really want to close out.
|
|
175
|
+
#
|
|
176
|
+
# @param name [String] the name of the span to end
|
|
177
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
178
|
+
#
|
|
179
|
+
def log_end(name, kvs = {}, end_time = ::Instana::Util.now_in_ms)
|
|
180
|
+
return unless self.current_span
|
|
181
|
+
|
|
182
|
+
if ENV.key?('INSTANA_DEBUG') || ENV.key?('INSTANA_TEST')
|
|
183
|
+
unless self.current_span.name == name
|
|
184
|
+
::Instana.logger.debug "Span mismatch: Attempt to end #{name} span but #{self.current_span.name} is active."
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
self.current_span.set_tags(kvs)
|
|
189
|
+
self.current_span.close(end_time)
|
|
190
|
+
self.current_span = nil
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
###########################################################################
|
|
194
|
+
# Asynchronous API methods
|
|
195
|
+
###########################################################################
|
|
196
|
+
|
|
197
|
+
# Starts a new asynchronous span on the current trace.
|
|
198
|
+
#
|
|
199
|
+
# @param name [String] the name of the span to create
|
|
200
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
201
|
+
#
|
|
202
|
+
# @return [Hash] the context: Trace ID and Span ID in the form of
|
|
203
|
+
# :trace_id => 12345
|
|
204
|
+
# :span_id => 12345
|
|
205
|
+
#
|
|
206
|
+
def log_async_entry(name, kvs)
|
|
207
|
+
return unless self.current_span
|
|
208
|
+
|
|
209
|
+
new_span = Span.new(name, parent_ctx: self.current_span)
|
|
210
|
+
new_span.set_tags(kvs) unless kvs.empty?
|
|
211
|
+
new_span
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Add info to an asynchronous span
|
|
215
|
+
#
|
|
216
|
+
# @param kvs [Hash] list of key values to be reported in the span
|
|
217
|
+
# @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
|
|
218
|
+
#
|
|
219
|
+
def log_async_info(kvs, span)
|
|
220
|
+
span.set_tags(kvs)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Add an error to an asynchronous span
|
|
224
|
+
#
|
|
225
|
+
# @param e [Exception] Add exception to the current span
|
|
226
|
+
# @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
|
|
227
|
+
#
|
|
228
|
+
def log_async_error(e, span)
|
|
229
|
+
span.add_error(e)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Closes out an asynchronous span
|
|
233
|
+
#
|
|
234
|
+
# @param name [String] the name of the async span to exit (close out)
|
|
235
|
+
# @param kvs [Hash] list of additional key/values to be reported in the span (or use {})
|
|
236
|
+
# @param span [Span] the span for this Async op (previously returned from `log_async_entry`)
|
|
237
|
+
#
|
|
238
|
+
def log_async_exit(_name, kvs, span)
|
|
239
|
+
span.set_tags(kvs) unless kvs.empty?
|
|
240
|
+
span.close
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
###########################################################################
|
|
244
|
+
# OpenTracing Support
|
|
245
|
+
###########################################################################
|
|
246
|
+
|
|
247
|
+
# Start a new span
|
|
248
|
+
#
|
|
249
|
+
# @param operation_name [String] The name of the operation represented by the span
|
|
250
|
+
# @param child_of [Span] A span to be used as the ChildOf reference
|
|
251
|
+
# @param start_time [Time] the start time of the span
|
|
252
|
+
# @param tags [Hash] Starting tags for the span
|
|
253
|
+
#
|
|
254
|
+
# @return [Span]
|
|
255
|
+
#
|
|
256
|
+
def start_span(operation_name, child_of: nil, start_time: ::Instana::Util.now_in_ms, tags: nil)
|
|
257
|
+
if child_of && (child_of.is_a?(::Instana::Span) || child_of.is_a?(::Instana::SpanContext))
|
|
258
|
+
new_span = Span.new(operation_name, parent_ctx: child_of, start_time: start_time)
|
|
259
|
+
else
|
|
260
|
+
new_span = Span.new(operation_name, start_time: start_time)
|
|
261
|
+
end
|
|
262
|
+
new_span.set_tags(tags) if tags
|
|
263
|
+
new_span
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Inject a span into the given carrier
|
|
267
|
+
#
|
|
268
|
+
# @param span_context [SpanContext]
|
|
269
|
+
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
|
|
270
|
+
# @param carrier [Carrier]
|
|
271
|
+
#
|
|
272
|
+
def inject(span_context, format, carrier)
|
|
273
|
+
case format
|
|
274
|
+
when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY
|
|
275
|
+
::Instana.logger.debug 'Unsupported inject format'
|
|
276
|
+
when OpenTracing::FORMAT_RACK
|
|
277
|
+
carrier['X-Instana-T'] = ::Instana::Util.id_to_header(span_context.trace_id)
|
|
278
|
+
carrier['X-Instana-S'] = ::Instana::Util.id_to_header(span_context.span_id)
|
|
279
|
+
else
|
|
280
|
+
::Instana.logger.debug 'Unknown inject format'
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Extract a span from a carrier
|
|
285
|
+
#
|
|
286
|
+
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
|
|
287
|
+
# @param carrier [Carrier]
|
|
288
|
+
#
|
|
289
|
+
# @return [SpanContext]
|
|
290
|
+
#
|
|
291
|
+
def extract(format, carrier)
|
|
292
|
+
case format
|
|
293
|
+
when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY
|
|
294
|
+
::Instana.logger.debug 'Unsupported extract format'
|
|
295
|
+
when OpenTracing::FORMAT_RACK
|
|
296
|
+
::Instana::SpanContext.new(::Instana::Util.header_to_id(carrier['HTTP_X_INSTANA_T']),
|
|
297
|
+
::Instana::Util.header_to_id(carrier['HTTP_X_INSTANA_S']))
|
|
298
|
+
else
|
|
299
|
+
::Instana.logger.debug 'Unknown inject format'
|
|
300
|
+
nil
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
###########################################################################
|
|
305
|
+
# Helper methods
|
|
306
|
+
###########################################################################
|
|
307
|
+
|
|
308
|
+
# Indicates if we're are currently in the process of
|
|
309
|
+
# collecting a trace. This is false when the host agent isn
|
|
310
|
+
# available.
|
|
311
|
+
#
|
|
312
|
+
# @return [Boolean] true or false on whether we are currently tracing or not
|
|
313
|
+
#
|
|
314
|
+
def tracing?
|
|
315
|
+
# The non-nil value of this instance variable
|
|
316
|
+
# indicates if we are currently tracing
|
|
317
|
+
# in this thread or not.
|
|
318
|
+
self.current_span ? true : false
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Indicates if we're tracing and the current span name matches
|
|
322
|
+
# <name>
|
|
323
|
+
#
|
|
324
|
+
# @param name [Symbol] the name to check against the current span
|
|
325
|
+
#
|
|
326
|
+
# @return [Boolean]
|
|
327
|
+
#
|
|
328
|
+
def tracing_span?(name)
|
|
329
|
+
if self.current_span
|
|
330
|
+
return self.current_span.name == name
|
|
331
|
+
end
|
|
332
|
+
false
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Retrieve the current context of the tracer.
|
|
336
|
+
#
|
|
337
|
+
# @return [SpanContext] or nil if not tracing
|
|
338
|
+
#
|
|
339
|
+
def context
|
|
340
|
+
return unless self.current_span
|
|
341
|
+
self.current_span.context
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Take the current trace_id and convert it to a header compatible
|
|
345
|
+
# format.
|
|
346
|
+
#
|
|
347
|
+
# @return [String] a hexadecimal representation of the current trace ID
|
|
348
|
+
#
|
|
349
|
+
def trace_id_header
|
|
350
|
+
if self.current_span
|
|
351
|
+
self.current_span.context.trace_id_header
|
|
352
|
+
else
|
|
353
|
+
""
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Take the current span_id and convert it to a header compatible
|
|
358
|
+
# formate.
|
|
359
|
+
#
|
|
360
|
+
# @return [String] a hexadecimal representation of the current span ID
|
|
361
|
+
#
|
|
362
|
+
def span_id_header
|
|
363
|
+
if self.current_span
|
|
364
|
+
self.current_span.context.span_id_header
|
|
365
|
+
else
|
|
366
|
+
""
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Returns the trace ID for the active trace (if there is one),
|
|
371
|
+
# otherwise nil.
|
|
372
|
+
#
|
|
373
|
+
def trace_id
|
|
374
|
+
self.current_span ? self.current_span.id : nil
|
|
375
|
+
::Instana.logger.debug("tracer.trace_id will deprecated in a future version.")
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# Returns the current [Span] ID for the active trace (if there is one),
|
|
379
|
+
# otherwise nil.
|
|
380
|
+
#
|
|
381
|
+
def span_id
|
|
382
|
+
self.current_span ? self.current_span.span_id : nil
|
|
383
|
+
::Instana.logger.debug("tracer.span_id will deprecated in a future version.")
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Used in the test suite, this resets the tracer to non-tracing state.
|
|
387
|
+
#
|
|
388
|
+
def clear!
|
|
389
|
+
self.current_span = nil
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|