atatus 1.0.0
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/.gitignore +16 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +57 -0
- data/LICENSE +65 -0
- data/LICENSE-THIRD-PARTY +205 -0
- data/README.md +13 -0
- data/Rakefile +19 -0
- data/atatus.gemspec +36 -0
- data/atatus.yml +2 -0
- data/bench/.gitignore +2 -0
- data/bench/app.rb +53 -0
- data/bench/benchmark.rb +36 -0
- data/bench/report.rb +55 -0
- data/bench/rubyprof.rb +39 -0
- data/bench/stackprof.rb +23 -0
- data/bin/build_docs +5 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/bin/with_framework +7 -0
- data/lib/atatus.rb +325 -0
- data/lib/atatus/agent.rb +260 -0
- data/lib/atatus/central_config.rb +141 -0
- data/lib/atatus/central_config/cache_control.rb +34 -0
- data/lib/atatus/collector/base.rb +329 -0
- data/lib/atatus/collector/builder.rb +317 -0
- data/lib/atatus/collector/transport.rb +72 -0
- data/lib/atatus/config.rb +248 -0
- data/lib/atatus/config/bytes.rb +25 -0
- data/lib/atatus/config/duration.rb +23 -0
- data/lib/atatus/config/options.rb +134 -0
- data/lib/atatus/config/regexp_list.rb +13 -0
- data/lib/atatus/context.rb +33 -0
- data/lib/atatus/context/request.rb +11 -0
- data/lib/atatus/context/request/socket.rb +19 -0
- data/lib/atatus/context/request/url.rb +42 -0
- data/lib/atatus/context/response.rb +22 -0
- data/lib/atatus/context/user.rb +42 -0
- data/lib/atatus/context_builder.rb +97 -0
- data/lib/atatus/deprecations.rb +22 -0
- data/lib/atatus/error.rb +22 -0
- data/lib/atatus/error/exception.rb +46 -0
- data/lib/atatus/error/log.rb +24 -0
- data/lib/atatus/error_builder.rb +76 -0
- data/lib/atatus/instrumenter.rb +224 -0
- data/lib/atatus/internal_error.rb +6 -0
- data/lib/atatus/logging.rb +55 -0
- data/lib/atatus/metadata.rb +19 -0
- data/lib/atatus/metadata/process_info.rb +18 -0
- data/lib/atatus/metadata/service_info.rb +61 -0
- data/lib/atatus/metadata/system_info.rb +35 -0
- data/lib/atatus/metadata/system_info/container_info.rb +121 -0
- data/lib/atatus/metadata/system_info/hw_info.rb +118 -0
- data/lib/atatus/metadata/system_info/os_info.rb +31 -0
- data/lib/atatus/metrics.rb +98 -0
- data/lib/atatus/metrics/cpu_mem.rb +240 -0
- data/lib/atatus/metrics/vm.rb +60 -0
- data/lib/atatus/metricset.rb +19 -0
- data/lib/atatus/middleware.rb +76 -0
- data/lib/atatus/naively_hashable.rb +21 -0
- data/lib/atatus/normalizers.rb +68 -0
- data/lib/atatus/normalizers/action_controller.rb +27 -0
- data/lib/atatus/normalizers/action_mailer.rb +26 -0
- data/lib/atatus/normalizers/action_view.rb +77 -0
- data/lib/atatus/normalizers/active_record.rb +45 -0
- data/lib/atatus/opentracing.rb +346 -0
- data/lib/atatus/rails.rb +61 -0
- data/lib/atatus/railtie.rb +30 -0
- data/lib/atatus/span.rb +125 -0
- data/lib/atatus/span/context.rb +40 -0
- data/lib/atatus/span_helpers.rb +44 -0
- data/lib/atatus/spies.rb +86 -0
- data/lib/atatus/spies/action_dispatch.rb +28 -0
- data/lib/atatus/spies/delayed_job.rb +68 -0
- data/lib/atatus/spies/elasticsearch.rb +36 -0
- data/lib/atatus/spies/faraday.rb +70 -0
- data/lib/atatus/spies/http.rb +44 -0
- data/lib/atatus/spies/json.rb +22 -0
- data/lib/atatus/spies/mongo.rb +87 -0
- data/lib/atatus/spies/net_http.rb +70 -0
- data/lib/atatus/spies/rake.rb +45 -0
- data/lib/atatus/spies/redis.rb +27 -0
- data/lib/atatus/spies/sequel.rb +47 -0
- data/lib/atatus/spies/sidekiq.rb +89 -0
- data/lib/atatus/spies/sinatra.rb +41 -0
- data/lib/atatus/spies/tilt.rb +27 -0
- data/lib/atatus/sql_summarizer.rb +35 -0
- data/lib/atatus/stacktrace.rb +16 -0
- data/lib/atatus/stacktrace/frame.rb +52 -0
- data/lib/atatus/stacktrace_builder.rb +104 -0
- data/lib/atatus/subscriber.rb +77 -0
- data/lib/atatus/trace_context.rb +85 -0
- data/lib/atatus/transaction.rb +100 -0
- data/lib/atatus/transport/base.rb +174 -0
- data/lib/atatus/transport/connection.rb +156 -0
- data/lib/atatus/transport/connection/http.rb +116 -0
- data/lib/atatus/transport/connection/proxy_pipe.rb +75 -0
- data/lib/atatus/transport/filters.rb +43 -0
- data/lib/atatus/transport/filters/secrets_filter.rb +74 -0
- data/lib/atatus/transport/serializers.rb +93 -0
- data/lib/atatus/transport/serializers/context_serializer.rb +85 -0
- data/lib/atatus/transport/serializers/error_serializer.rb +77 -0
- data/lib/atatus/transport/serializers/metadata_serializer.rb +70 -0
- data/lib/atatus/transport/serializers/metricset_serializer.rb +28 -0
- data/lib/atatus/transport/serializers/span_serializer.rb +80 -0
- data/lib/atatus/transport/serializers/transaction_serializer.rb +37 -0
- data/lib/atatus/transport/worker.rb +73 -0
- data/lib/atatus/util.rb +42 -0
- data/lib/atatus/util/inflector.rb +93 -0
- data/lib/atatus/util/lru_cache.rb +48 -0
- data/lib/atatus/util/prefixed_logger.rb +18 -0
- data/lib/atatus/util/throttle.rb +35 -0
- data/lib/atatus/version.rb +5 -0
- data/vendor/.gitkeep +0 -0
- metadata +190 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
module Normalizers
|
|
5
|
+
module ActionController
|
|
6
|
+
# @api private
|
|
7
|
+
class ProcessActionNormalizer < Normalizer
|
|
8
|
+
register 'process_action.action_controller'
|
|
9
|
+
|
|
10
|
+
TYPE = 'app'
|
|
11
|
+
SUBTYPE = 'controller'
|
|
12
|
+
ACTION = 'action'
|
|
13
|
+
|
|
14
|
+
def normalize(transaction, _name, payload)
|
|
15
|
+
transaction.name = endpoint(payload)
|
|
16
|
+
[transaction.name, TYPE, SUBTYPE, ACTION, nil]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def endpoint(payload)
|
|
22
|
+
"#{payload[:controller]}##{payload[:action]}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
module Normalizers
|
|
5
|
+
module ActionMailer
|
|
6
|
+
# @api private
|
|
7
|
+
class ProcessActionNormalizer < Normalizer
|
|
8
|
+
register 'process.action_mailer'
|
|
9
|
+
|
|
10
|
+
TYPE = 'app'
|
|
11
|
+
SUBTYPE = 'mailer'
|
|
12
|
+
ACTION = 'action'
|
|
13
|
+
|
|
14
|
+
def normalize(_transaction, _name, payload)
|
|
15
|
+
[endpoint(payload), TYPE, SUBTYPE, ACTION, nil]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def endpoint(payload)
|
|
21
|
+
"#{payload[:mailer]}##{payload[:action]}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
module Normalizers
|
|
5
|
+
module ActionView
|
|
6
|
+
# @api private
|
|
7
|
+
class RenderNormalizer < Normalizer
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def normalize_render(payload, type, subtype, action)
|
|
11
|
+
[path_for(payload[:identifier]), type, subtype, action, nil]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def path_for(path)
|
|
15
|
+
return 'Unknown template' unless path
|
|
16
|
+
return path unless path.start_with?('/')
|
|
17
|
+
|
|
18
|
+
view_path(path) || gem_path(path) || 'Absolute path'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def view_path(path)
|
|
22
|
+
root = @config.__view_paths.find { |vp| path.start_with?(vp) }
|
|
23
|
+
return unless root
|
|
24
|
+
|
|
25
|
+
strip_root(root, path)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def gem_path(path)
|
|
29
|
+
root = Gem.path.find { |gp| path.start_with? gp }
|
|
30
|
+
return unless root
|
|
31
|
+
|
|
32
|
+
format '$GEM_PATH/%s', strip_root(root, path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def strip_root(root, path)
|
|
36
|
+
start = root.length + 1
|
|
37
|
+
path[start, path.length]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @api private
|
|
42
|
+
class RenderTemplateNormalizer < RenderNormalizer
|
|
43
|
+
register 'render_template.action_view'
|
|
44
|
+
TYPE = 'template'
|
|
45
|
+
SUBTYPE = 'view'
|
|
46
|
+
|
|
47
|
+
def normalize(_transaction, _name, payload)
|
|
48
|
+
normalize_render(payload, TYPE, SUBTYPE, nil)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @api private
|
|
53
|
+
class RenderPartialNormalizer < RenderNormalizer
|
|
54
|
+
register 'render_partial.action_view'
|
|
55
|
+
TYPE = 'template'
|
|
56
|
+
SUBTYPE = 'view'
|
|
57
|
+
ACTION = 'partial'
|
|
58
|
+
|
|
59
|
+
def normalize(_transaction, _name, payload)
|
|
60
|
+
normalize_render(payload, TYPE, SUBTYPE, ACTION)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @api private
|
|
65
|
+
class RenderCollectionNormalizer < RenderNormalizer
|
|
66
|
+
register 'render_collection.action_view'
|
|
67
|
+
TYPE = 'template'
|
|
68
|
+
SUBTYPE = 'view'
|
|
69
|
+
ACTION = 'collection'
|
|
70
|
+
|
|
71
|
+
def normalize(_transaction, _name, payload)
|
|
72
|
+
normalize_render(payload, TYPE, SUBTYPE, ACTION)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'atatus/sql_summarizer'
|
|
4
|
+
|
|
5
|
+
module Atatus
|
|
6
|
+
module Normalizers
|
|
7
|
+
module ActiveRecord
|
|
8
|
+
# @api private
|
|
9
|
+
class SqlNormalizer < Normalizer
|
|
10
|
+
register 'sql.active_record'
|
|
11
|
+
|
|
12
|
+
TYPE = 'db'
|
|
13
|
+
ACTION = 'sql'
|
|
14
|
+
|
|
15
|
+
def initialize(*args)
|
|
16
|
+
super
|
|
17
|
+
|
|
18
|
+
@subtype = lookup_adapter || 'unknown'
|
|
19
|
+
@summarizer = SqlSummarizer.new
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def normalize(_transaction, _name, payload)
|
|
23
|
+
return :skip if %w[SCHEMA CACHE].include?(payload[:name])
|
|
24
|
+
|
|
25
|
+
name = summarize(payload[:sql]) || payload[:name]
|
|
26
|
+
context =
|
|
27
|
+
Span::Context.new(db: { statement: payload[:sql], type: 'sql' })
|
|
28
|
+
[name, TYPE, @subtype, ACTION, context]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def summarize(sql)
|
|
34
|
+
@summarizer.summarize(sql)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def lookup_adapter
|
|
38
|
+
::ActiveRecord::Base.connection.adapter_name.downcase
|
|
39
|
+
rescue StandardError
|
|
40
|
+
nil
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'atatus'
|
|
4
|
+
require 'opentracing'
|
|
5
|
+
|
|
6
|
+
module Atatus
|
|
7
|
+
module OpenTracing
|
|
8
|
+
# @api private
|
|
9
|
+
class Span
|
|
10
|
+
def initialize(atatus_span, span_context)
|
|
11
|
+
@atatus_span = atatus_span
|
|
12
|
+
@span_context = span_context
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :atatus_span
|
|
16
|
+
|
|
17
|
+
def operation_name=(name)
|
|
18
|
+
atatus_span.name = name
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def context
|
|
22
|
+
@span_context
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# rubocop:disable Metrics/MethodLength
|
|
26
|
+
def set_label(key, val)
|
|
27
|
+
if atatus_span.is_a?(Transaction)
|
|
28
|
+
case key.to_s
|
|
29
|
+
when 'type'
|
|
30
|
+
atatus_span.type = val
|
|
31
|
+
when 'result'
|
|
32
|
+
atatus_span.result = val
|
|
33
|
+
when /user\.(\w+)/
|
|
34
|
+
set_user_value($1, val)
|
|
35
|
+
else
|
|
36
|
+
atatus_span.context.labels[key] = val
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
atatus_span.context.labels[key] = val
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
# rubocop:enable Metrics/MethodLength
|
|
43
|
+
|
|
44
|
+
def set_baggage_item(_key, _value)
|
|
45
|
+
Atatus.agent.config.logger.warn(
|
|
46
|
+
'Baggage is not supported by Atatus'
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_baggage_item(_key)
|
|
51
|
+
Atatus.agent.config.logger.warn(
|
|
52
|
+
'Baggage is not supported by Atatus'
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
|
59
|
+
def log_kv(timestamp: nil, **fields)
|
|
60
|
+
if (exception = fields[:'error.object'])
|
|
61
|
+
Atatus.report exception
|
|
62
|
+
elsif (message = fields[:message])
|
|
63
|
+
Atatus.report_message message
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
|
67
|
+
|
|
68
|
+
# rubocop:disable Metrics/MethodLength
|
|
69
|
+
def finish(clock_end: Util.monotonic_micros, end_time: nil)
|
|
70
|
+
return unless (instrumenter = Atatus.agent&.instrumenter)
|
|
71
|
+
|
|
72
|
+
if end_time
|
|
73
|
+
warn '[Atatus] DEPRECATED: Setting a custom end time as a ' \
|
|
74
|
+
'`Time` is deprecated. Use `clock_end:` and monotonic time instead.'
|
|
75
|
+
clock_end = end_time
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
atatus_span.done clock_end: clock_end
|
|
79
|
+
|
|
80
|
+
case atatus_span
|
|
81
|
+
when Atatus::Transaction
|
|
82
|
+
instrumenter.current_transaction = nil
|
|
83
|
+
when Atatus::Span
|
|
84
|
+
instrumenter.current_spans.delete(atatus_span)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
instrumenter.enqueue.call atatus_span
|
|
88
|
+
end
|
|
89
|
+
# rubocop:enable Metrics/MethodLength
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def set_user_value(key, value)
|
|
94
|
+
return unless atatus_span.is_a?(Transaction)
|
|
95
|
+
|
|
96
|
+
setter = :"#{key}="
|
|
97
|
+
return unless atatus_span.context.user.respond_to?(setter)
|
|
98
|
+
atatus_span.context.user.send(setter, value)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @api private
|
|
103
|
+
class SpanContext
|
|
104
|
+
def initialize(trace_context:, baggage: nil)
|
|
105
|
+
if baggage
|
|
106
|
+
Atatus.agent.config.logger.warn(
|
|
107
|
+
'Baggage is not supported by Atatus'
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
@trace_context = trace_context
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
attr_accessor :trace_context
|
|
115
|
+
|
|
116
|
+
def self.from_trace_context(trace_context)
|
|
117
|
+
new(trace_context: trace_context)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @api private
|
|
122
|
+
class Scope
|
|
123
|
+
def initialize(span, scope_stack, finish_on_close:)
|
|
124
|
+
@span = span
|
|
125
|
+
@scope_stack = scope_stack
|
|
126
|
+
@finish_on_close = finish_on_close
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
attr_reader :span
|
|
130
|
+
|
|
131
|
+
def atatus_span
|
|
132
|
+
span.atatus_span
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def close
|
|
136
|
+
@span.finish if @finish_on_close
|
|
137
|
+
@scope_stack.pop
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# @api private
|
|
142
|
+
class ScopeStack
|
|
143
|
+
KEY = :__atatus_ot_scope_stack
|
|
144
|
+
|
|
145
|
+
def push(scope)
|
|
146
|
+
scopes << scope
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def pop
|
|
150
|
+
scopes.pop
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def last
|
|
154
|
+
scopes.last
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
def scopes
|
|
160
|
+
Thread.current[KEY] ||= []
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# @api private
|
|
165
|
+
class ScopeManager
|
|
166
|
+
def initialize
|
|
167
|
+
@scope_stack = ScopeStack.new
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def activate(span, finish_on_close: true)
|
|
171
|
+
return active if active && active.span == span
|
|
172
|
+
|
|
173
|
+
scope = Scope.new(span, @scope_stack, finish_on_close: finish_on_close)
|
|
174
|
+
@scope_stack.push scope
|
|
175
|
+
scope
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def active
|
|
179
|
+
@scope_stack.last
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# rubocop:disable Metrics/ClassLength
|
|
184
|
+
# A custom tracer to use the OpenTracing API with Atatus
|
|
185
|
+
class Tracer
|
|
186
|
+
def initialize
|
|
187
|
+
@scope_manager = ScopeManager.new
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
attr_reader :scope_manager
|
|
191
|
+
|
|
192
|
+
def active_span
|
|
193
|
+
scope_manager.active&.span
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
|
|
197
|
+
def start_active_span(
|
|
198
|
+
operation_name,
|
|
199
|
+
child_of: nil,
|
|
200
|
+
references: nil,
|
|
201
|
+
start_time: Time.now,
|
|
202
|
+
labels: {},
|
|
203
|
+
ignore_active_scope: false,
|
|
204
|
+
finish_on_close: true,
|
|
205
|
+
**
|
|
206
|
+
)
|
|
207
|
+
span = start_span(
|
|
208
|
+
operation_name,
|
|
209
|
+
child_of: child_of,
|
|
210
|
+
references: references,
|
|
211
|
+
start_time: start_time,
|
|
212
|
+
labels: labels,
|
|
213
|
+
ignore_active_scope: ignore_active_scope
|
|
214
|
+
)
|
|
215
|
+
scope = scope_manager.activate(span, finish_on_close: finish_on_close)
|
|
216
|
+
|
|
217
|
+
if block_given?
|
|
218
|
+
begin
|
|
219
|
+
yield scope
|
|
220
|
+
ensure
|
|
221
|
+
scope.close
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
scope
|
|
226
|
+
end
|
|
227
|
+
# rubocop:enable Metrics/MethodLength, Metrics/ParameterLists
|
|
228
|
+
|
|
229
|
+
# rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
|
|
230
|
+
# rubocop:disable Metrics/AbcSize
|
|
231
|
+
def start_span(
|
|
232
|
+
operation_name,
|
|
233
|
+
child_of: nil,
|
|
234
|
+
references: nil,
|
|
235
|
+
start_time: Time.now,
|
|
236
|
+
labels: {},
|
|
237
|
+
ignore_active_scope: false,
|
|
238
|
+
**
|
|
239
|
+
)
|
|
240
|
+
span_context = prepare_span_context(
|
|
241
|
+
child_of: child_of,
|
|
242
|
+
references: references,
|
|
243
|
+
ignore_active_scope: ignore_active_scope
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if span_context
|
|
247
|
+
trace_context =
|
|
248
|
+
span_context &&
|
|
249
|
+
span_context.respond_to?(:trace_context) &&
|
|
250
|
+
span_context.trace_context
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
atatus_span =
|
|
254
|
+
if Atatus.current_transaction
|
|
255
|
+
Atatus.start_span(
|
|
256
|
+
operation_name,
|
|
257
|
+
trace_context: trace_context
|
|
258
|
+
)
|
|
259
|
+
else
|
|
260
|
+
Atatus.start_transaction(
|
|
261
|
+
operation_name,
|
|
262
|
+
trace_context: trace_context
|
|
263
|
+
)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# if no Atatus APM agent is running or transaction not sampled
|
|
267
|
+
unless atatus_span
|
|
268
|
+
return ::OpenTracing::Span::NOOP_INSTANCE
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
span_context ||=
|
|
272
|
+
SpanContext.from_trace_context(atatus_span.trace_context)
|
|
273
|
+
|
|
274
|
+
labels.each do |key, value|
|
|
275
|
+
atatus_span.context.labels[key] = value
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
atatus_span.start Util.micros(start_time)
|
|
279
|
+
|
|
280
|
+
Span.new(atatus_span, span_context)
|
|
281
|
+
end
|
|
282
|
+
# rubocop:enable Metrics/AbcSize
|
|
283
|
+
# rubocop:enable Metrics/MethodLength, Metrics/ParameterLists
|
|
284
|
+
|
|
285
|
+
def inject(span_context, format, carrier)
|
|
286
|
+
case format
|
|
287
|
+
when ::OpenTracing::FORMAT_RACK
|
|
288
|
+
carrier['atatus-traceparent'] = span_context.to_header
|
|
289
|
+
else
|
|
290
|
+
warn 'Only injection via HTTP headers and Rack is available'
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def extract(format, carrier)
|
|
295
|
+
case format
|
|
296
|
+
when ::OpenTracing::FORMAT_RACK
|
|
297
|
+
Atatus::TraceContext
|
|
298
|
+
.parse(carrier['HTTP_ATATUS_APM_TRACEPARENT'])
|
|
299
|
+
else
|
|
300
|
+
warn 'Only extraction from HTTP headers via Rack is available'
|
|
301
|
+
nil
|
|
302
|
+
end
|
|
303
|
+
rescue Atatus::TraceContext::InvalidTraceparentHeader
|
|
304
|
+
nil
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
private
|
|
308
|
+
|
|
309
|
+
def prepare_span_context(
|
|
310
|
+
child_of:,
|
|
311
|
+
references:,
|
|
312
|
+
ignore_active_scope:
|
|
313
|
+
)
|
|
314
|
+
context_from_child_of(child_of) ||
|
|
315
|
+
context_from_references(references) ||
|
|
316
|
+
context_from_active_scope(ignore_active_scope)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def context_from_child_of(child_of)
|
|
320
|
+
return unless child_of
|
|
321
|
+
child_of.respond_to?(:context) ? child_of.context : child_of
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def context_from_references(references)
|
|
325
|
+
return if !references || references.none?
|
|
326
|
+
|
|
327
|
+
child_of = references.find do |reference|
|
|
328
|
+
reference.type == ::OpenTracing::Reference::CHILD_OF
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
(child_of || references.first).context
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def context_from_active_scope(ignore_active_scope)
|
|
335
|
+
if ignore_active_scope
|
|
336
|
+
Atatus.agent&.config&.logger&.warn(
|
|
337
|
+
'ignore_active_scope might lead to unexpeced results'
|
|
338
|
+
)
|
|
339
|
+
return
|
|
340
|
+
end
|
|
341
|
+
@scope_manager.active&.span&.context
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
# rubocop:enable Metrics/ClassLength
|
|
345
|
+
end
|
|
346
|
+
end
|