instana 1.10.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|