elastic-apm 4.5.0 → 4.6.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 +4 -4
- data/.ci/.jenkins_exclude.yml +86 -29
- data/.ci/.jenkins_framework.yml +4 -3
- data/.ci/{.jenkins_master_framework.yml → .jenkins_main_framework.yml} +0 -0
- data/.ci/.jenkins_ruby.yml +1 -1
- data/.ci/.jenkins_ruby_benchmarks.yml +6 -0
- data/.ci/Jenkinsfile +16 -37
- data/.ci/jobs/apm-agent-ruby-mbp.yml +1 -1
- data/.github/PULL_REQUEST_TEMPLATE.md +5 -5
- data/.pre-commit-config.yaml +2 -2
- data/CHANGELOG.asciidoc +38 -0
- data/CONTRIBUTING.md +2 -2
- data/Gemfile +11 -2
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/bench/report.rb +1 -1
- data/docs/api.asciidoc +2 -2
- data/docs/configuration.asciidoc +7 -5
- data/docs/introduction.asciidoc +3 -3
- data/docs/log-correlation.asciidoc +1 -1
- data/docs/upgrading.asciidoc +1 -1
- data/elastic-apm.gemspec +3 -2
- data/lib/elastic_apm/central_config.rb +5 -0
- data/lib/elastic_apm/config/server_info.rb +50 -0
- data/lib/elastic_apm/config.rb +25 -4
- data/lib/elastic_apm/error.rb +2 -1
- data/lib/elastic_apm/error_builder.rb +1 -0
- data/lib/elastic_apm/instrumenter.rb +4 -2
- data/lib/elastic_apm/metadata/system_info/container_info.rb +4 -3
- data/lib/elastic_apm/metadata/system_info.rb +1 -1
- data/lib/elastic_apm/metrics.rb +1 -4
- data/lib/elastic_apm/span/context/links.rb +32 -0
- data/lib/elastic_apm/span/context/service.rb +55 -0
- data/lib/elastic_apm/span/context.rb +19 -3
- data/lib/elastic_apm/span.rb +3 -0
- data/lib/elastic_apm/span_helpers.rb +2 -2
- data/lib/elastic_apm/spies/elasticsearch.rb +11 -1
- data/lib/elastic_apm/spies/mongo.rb +5 -12
- data/lib/elastic_apm/spies/racecar.rb +77 -0
- data/lib/elastic_apm/spies/redis.rb +1 -1
- data/lib/elastic_apm/spies/sequel.rb +9 -0
- data/lib/elastic_apm/spies/sns.rb +1 -1
- data/lib/elastic_apm/spies/sqs.rb +1 -0
- data/lib/elastic_apm/trace_context/tracestate.rb +1 -1
- data/lib/elastic_apm/trace_context.rb +1 -1
- data/lib/elastic_apm/transport/base.rb +1 -3
- data/lib/elastic_apm/transport/serializers/span_serializer.rb +25 -0
- data/lib/elastic_apm/version.rb +1 -1
- data/lib/elastic_apm.rb +1 -0
- metadata +29 -9
data/elastic-apm.gemspec
CHANGED
@@ -22,8 +22,8 @@ require 'elastic_apm/version'
|
|
22
22
|
Gem::Specification.new do |spec|
|
23
23
|
spec.name = 'elastic-apm'
|
24
24
|
spec.version = ElasticAPM::VERSION
|
25
|
-
spec.authors = ['Mikkel Malmberg']
|
26
|
-
spec.email = ['
|
25
|
+
spec.authors = ['Mikkel Malmberg', 'Emily Stolfo']
|
26
|
+
spec.email = ['info@elastic.co']
|
27
27
|
|
28
28
|
spec.summary = 'The official Elastic APM agent for Ruby'
|
29
29
|
spec.homepage = 'https://github.com/elastic/apm-agent-ruby'
|
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
|
|
37
37
|
|
38
38
|
spec.add_dependency('concurrent-ruby', '~> 1.0')
|
39
39
|
spec.add_dependency('http', '>= 3.0')
|
40
|
+
spec.add_runtime_dependency('ruby2_keywords')
|
40
41
|
|
41
42
|
spec.require_paths = ['lib']
|
42
43
|
end
|
@@ -181,6 +181,11 @@ module ElasticAPM
|
|
181
181
|
DEFAULT_MAX_AGE
|
182
182
|
end
|
183
183
|
|
184
|
+
if seconds < 5
|
185
|
+
debug "Next fetch is too low (#{seconds}s) - increasing to default"
|
186
|
+
seconds = 5
|
187
|
+
end
|
188
|
+
|
184
189
|
@scheduled_task =
|
185
190
|
Concurrent::ScheduledTask
|
186
191
|
.execute(seconds) { fetch_and_apply_config }
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module ElasticAPM
|
21
|
+
class Config
|
22
|
+
# @api private
|
23
|
+
class ServerInfo
|
24
|
+
attr_reader :payload, :config, :http
|
25
|
+
|
26
|
+
VERSION_8_0 = '8.0'
|
27
|
+
VERSION_0 = '0'
|
28
|
+
|
29
|
+
def initialize(config)
|
30
|
+
@config = config
|
31
|
+
@http = Transport::Connection::Http.new(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
def execute
|
35
|
+
resp = http.get(config.server_url)
|
36
|
+
@payload = JSON.parse(resp.body)
|
37
|
+
rescue
|
38
|
+
@payload = { "version" => VERSION_0 }
|
39
|
+
end
|
40
|
+
|
41
|
+
def version
|
42
|
+
@version ||= begin
|
43
|
+
execute
|
44
|
+
payload["version"] ? payload["version"].to_s : VERSION_0
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
data/lib/elastic_apm/config.rb
CHANGED
@@ -24,14 +24,17 @@ require 'elastic_apm/config/options'
|
|
24
24
|
require 'elastic_apm/config/round_float'
|
25
25
|
require 'elastic_apm/config/regexp_list'
|
26
26
|
require 'elastic_apm/config/wildcard_pattern_list'
|
27
|
+
require 'elastic_apm/deprecations'
|
28
|
+
require 'elastic_apm/config/server_info'
|
27
29
|
|
28
30
|
module ElasticAPM
|
29
31
|
# @api private
|
30
32
|
class Config
|
31
33
|
extend Options
|
34
|
+
extend Deprecations
|
32
35
|
|
33
36
|
SANITIZE_FIELD_NAMES_DEFAULT =
|
34
|
-
%w[password passwd pwd secret *key *token* *session* *credit* *card*
|
37
|
+
%w[password passwd pwd secret *key *token* *session* *credit* *card* *auth* set-cookie].freeze
|
35
38
|
|
36
39
|
# rubocop:disable Layout/LineLength, Layout/ExtraSpacing
|
37
40
|
option :config_file, type: :string, default: 'config/elastic_apm.yml'
|
@@ -70,7 +73,7 @@ module ElasticAPM
|
|
70
73
|
option :ignore_url_patterns, type: :list, default: [], converter: RegexpList.new
|
71
74
|
option :instrument, type: :bool, default: true
|
72
75
|
option :instrumented_rake_tasks, type: :list, default: []
|
73
|
-
option :
|
76
|
+
option :log_ecs_reformatting, type: :string, default: 'off'
|
74
77
|
option :log_level, type: :int, default: Logger::INFO, converter: LogLevelMap.new
|
75
78
|
option :log_path, type: :string
|
76
79
|
option :metrics_interval, type: :int, default: '30s', converter: Duration.new
|
@@ -98,6 +101,16 @@ module ElasticAPM
|
|
98
101
|
option :use_elastic_traceparent_header, type: :bool, default: true
|
99
102
|
option :verify_server_cert, type: :bool, default: true
|
100
103
|
|
104
|
+
def log_ecs_formatting
|
105
|
+
log_ecs_reformatting
|
106
|
+
end
|
107
|
+
|
108
|
+
def log_ecs_formatting=(value)
|
109
|
+
@options[:log_ecs_reformatting].set(value)
|
110
|
+
end
|
111
|
+
|
112
|
+
deprecate :log_ecs_formatting, :log_ecs_reformatting
|
113
|
+
|
101
114
|
# rubocop:enable Layout/LineLength, Layout/ExtraSpacing
|
102
115
|
def initialize(options = {})
|
103
116
|
@options = load_schema
|
@@ -116,7 +129,9 @@ module ElasticAPM
|
|
116
129
|
|
117
130
|
yield self if block_given?
|
118
131
|
|
119
|
-
self.logger
|
132
|
+
if self.logger.nil? || self.log_path
|
133
|
+
self.logger = build_logger
|
134
|
+
end
|
120
135
|
|
121
136
|
@__view_paths ||= []
|
122
137
|
@__root_path ||= Dir.pwd
|
@@ -144,6 +159,7 @@ module ElasticAPM
|
|
144
159
|
mongo
|
145
160
|
net_http
|
146
161
|
rake
|
162
|
+
racecar
|
147
163
|
redis
|
148
164
|
resque
|
149
165
|
s3
|
@@ -229,6 +245,10 @@ module ElasticAPM
|
|
229
245
|
super.split.first + '>'
|
230
246
|
end
|
231
247
|
|
248
|
+
def version
|
249
|
+
@version ||= ServerInfo.new(self).version
|
250
|
+
end
|
251
|
+
|
232
252
|
private
|
233
253
|
|
234
254
|
def load_config_file
|
@@ -247,7 +267,7 @@ module ElasticAPM
|
|
247
267
|
end
|
248
268
|
|
249
269
|
def build_logger
|
250
|
-
if self.
|
270
|
+
if self.log_ecs_reformatting == 'override'
|
251
271
|
begin
|
252
272
|
return build_ecs_logger
|
253
273
|
rescue LoadError
|
@@ -294,6 +314,7 @@ module ElasticAPM
|
|
294
314
|
self.framework_name ||= 'Ruby on Rails'
|
295
315
|
self.framework_version ||= ::Rails::VERSION::STRING
|
296
316
|
self.logger ||= ::Rails.logger
|
317
|
+
self.log_level ||= ::Rails.logger.log_level
|
297
318
|
|
298
319
|
self.__root_path = ::Rails.root.to_s
|
299
320
|
self.__view_paths = app.config.paths['app/views'].existent +
|
data/lib/elastic_apm/error.rb
CHANGED
@@ -33,7 +33,7 @@ module ElasticAPM
|
|
33
33
|
end
|
34
34
|
|
35
35
|
attr_accessor :id, :culprit, :exception, :log, :transaction_id,
|
36
|
-
:transaction, :context, :parent_id, :trace_id
|
36
|
+
:transaction_name, :transaction, :context, :parent_id, :trace_id
|
37
37
|
attr_reader :timestamp
|
38
38
|
|
39
39
|
def inspect
|
@@ -41,6 +41,7 @@ module ElasticAPM
|
|
41
41
|
" culprit:#{culprit}" \
|
42
42
|
" timestamp:#{timestamp}" \
|
43
43
|
" transaction_id:#{transaction_id}" \
|
44
|
+
" transaction_name:#{transaction_name}" \
|
44
45
|
" trace_id:#{trace_id}" \
|
45
46
|
" exception:#{exception.inspect}" \
|
46
47
|
'>'
|
@@ -124,7 +124,7 @@ module ElasticAPM
|
|
124
124
|
sample_rate = trace_context.tracestate.sample_rate
|
125
125
|
else
|
126
126
|
sampled = random_sample?(config)
|
127
|
-
sample_rate = config.transaction_sample_rate
|
127
|
+
sample_rate = sampled ? config.transaction_sample_rate : 0
|
128
128
|
end
|
129
129
|
|
130
130
|
transaction =
|
@@ -150,7 +150,9 @@ module ElasticAPM
|
|
150
150
|
|
151
151
|
transaction.done result
|
152
152
|
|
153
|
-
|
153
|
+
if transaction.sampled? || @config.version < Config::ServerInfo::VERSION_8_0
|
154
|
+
enqueue.call transaction
|
155
|
+
end
|
154
156
|
|
155
157
|
update_transaction_metrics(transaction)
|
156
158
|
|
@@ -33,14 +33,15 @@ module ElasticAPM
|
|
33
33
|
|
34
34
|
attr_reader :cgroup_path
|
35
35
|
|
36
|
-
def read!
|
36
|
+
def read!(hostname)
|
37
37
|
read_from_cgroup!
|
38
|
+
self.kubernetes_pod_name = hostname if kubernetes_pod_uid
|
38
39
|
read_from_env!
|
39
40
|
self
|
40
41
|
end
|
41
42
|
|
42
|
-
def self.read!
|
43
|
-
new.read!
|
43
|
+
def self.read!(hostname)
|
44
|
+
new.read!(hostname)
|
44
45
|
end
|
45
46
|
|
46
47
|
def container
|
@@ -29,7 +29,7 @@ module ElasticAPM
|
|
29
29
|
@architecture = gem_platform.cpu
|
30
30
|
@platform = gem_platform.os
|
31
31
|
|
32
|
-
container_info = ContainerInfo.read!
|
32
|
+
container_info = ContainerInfo.read!(@detected_hostname)
|
33
33
|
@container = container_info.container
|
34
34
|
@kubernetes = container_info.kubernetes
|
35
35
|
end
|
data/lib/elastic_apm/metrics.rb
CHANGED
@@ -36,8 +36,6 @@ module ElasticAPM
|
|
36
36
|
class Registry
|
37
37
|
include Logging
|
38
38
|
|
39
|
-
TIMEOUT_INTERVAL = 5 # seconds
|
40
|
-
|
41
39
|
def initialize(config, &block)
|
42
40
|
@config = config
|
43
41
|
@callback = block
|
@@ -76,8 +74,7 @@ module ElasticAPM
|
|
76
74
|
|
77
75
|
@timer_task = Concurrent::TimerTask.execute(
|
78
76
|
run_now: true,
|
79
|
-
execution_interval: config.metrics_interval
|
80
|
-
timeout_interval: TIMEOUT_INTERVAL
|
77
|
+
execution_interval: config.metrics_interval
|
81
78
|
) do
|
82
79
|
begin
|
83
80
|
debug 'Collecting metrics'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module ElasticAPM
|
21
|
+
class Span
|
22
|
+
class Context
|
23
|
+
# @api private
|
24
|
+
class Links < Array
|
25
|
+
# @api private
|
26
|
+
class Link < Struct.new(:trace_id, :span_id)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
# frozen_string_literal: true
|
19
|
+
|
20
|
+
module ElasticAPM
|
21
|
+
class Span
|
22
|
+
class Context
|
23
|
+
# @api private
|
24
|
+
class Service
|
25
|
+
include Fields
|
26
|
+
|
27
|
+
field :target
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
class Target
|
31
|
+
include Fields
|
32
|
+
|
33
|
+
field :name, default: ''
|
34
|
+
field :type, default: ''
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(target: nil, **attrs)
|
38
|
+
super(**attrs)
|
39
|
+
|
40
|
+
self.target = build_target(target)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def build_target(target = nil)
|
46
|
+
return Target.new unless target
|
47
|
+
return target if target.is_a?(Target)
|
48
|
+
|
49
|
+
Target.new(**target)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -27,7 +27,9 @@ module ElasticAPM
|
|
27
27
|
http: nil,
|
28
28
|
labels: {},
|
29
29
|
sync: nil,
|
30
|
-
message: nil
|
30
|
+
message: nil,
|
31
|
+
service: nil,
|
32
|
+
links: nil
|
31
33
|
)
|
32
34
|
@sync = sync
|
33
35
|
@db = db && Db.new(**db)
|
@@ -43,6 +45,16 @@ module ElasticAPM
|
|
43
45
|
when Hash then Message.new(**message)
|
44
46
|
end
|
45
47
|
@labels = labels
|
48
|
+
@service =
|
49
|
+
case service
|
50
|
+
when Service then service
|
51
|
+
when Hash then Service.new(**service)
|
52
|
+
end
|
53
|
+
@links =
|
54
|
+
case links
|
55
|
+
when Links then links
|
56
|
+
when Array then Links.new(links)
|
57
|
+
end
|
46
58
|
end
|
47
59
|
|
48
60
|
attr_reader(
|
@@ -50,10 +62,11 @@ module ElasticAPM
|
|
50
62
|
:http,
|
51
63
|
:labels,
|
52
64
|
:sync,
|
53
|
-
:message
|
65
|
+
:message,
|
66
|
+
:links
|
54
67
|
)
|
55
68
|
|
56
|
-
attr_accessor :destination
|
69
|
+
attr_accessor :destination, :service
|
57
70
|
end
|
58
71
|
end
|
59
72
|
end
|
@@ -62,3 +75,6 @@ require 'elastic_apm/span/context/db'
|
|
62
75
|
require 'elastic_apm/span/context/http'
|
63
76
|
require 'elastic_apm/span/context/destination'
|
64
77
|
require 'elastic_apm/span/context/message'
|
78
|
+
require 'elastic_apm/span/context/service'
|
79
|
+
require 'elastic_apm/span/context/links'
|
80
|
+
|
data/lib/elastic_apm/span.rb
CHANGED
@@ -145,6 +145,9 @@ module ElasticAPM
|
|
145
145
|
service: service,
|
146
146
|
cloud: cloud
|
147
147
|
)
|
148
|
+
context.service = Span::Context::Service.new(
|
149
|
+
target: Span::Context::Service::Target.new(name: context.destination.service.name, type: context.destination.service.type )
|
150
|
+
)
|
148
151
|
end
|
149
152
|
|
150
153
|
def inspect
|
@@ -37,7 +37,7 @@ module ElasticAPM
|
|
37
37
|
type ||= Span::DEFAULT_TYPE
|
38
38
|
|
39
39
|
klass.prepend(Module.new do
|
40
|
-
define_method(method) do |*args, &block|
|
40
|
+
ruby2_keywords(define_method(method) do |*args, &block|
|
41
41
|
unless ElasticAPM.current_transaction
|
42
42
|
return super(*args, &block)
|
43
43
|
end
|
@@ -45,7 +45,7 @@ module ElasticAPM
|
|
45
45
|
ElasticAPM.with_span name.to_s, type.to_s do
|
46
46
|
super(*args, &block)
|
47
47
|
end
|
48
|
-
end
|
48
|
+
end)
|
49
49
|
end)
|
50
50
|
end
|
51
51
|
end
|
@@ -79,7 +79,11 @@ module ElasticAPM
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def install
|
82
|
-
::
|
82
|
+
if defined?(::Elastic::Transport::Client)
|
83
|
+
::Elastic::Transport::Client.prepend(Ext)
|
84
|
+
elsif defined?(::Elasticsearch::Transport::Client)
|
85
|
+
::Elasticsearch::Transport::Client.prepend(Ext)
|
86
|
+
end
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
@@ -88,5 +92,11 @@ module ElasticAPM
|
|
88
92
|
'elasticsearch-transport',
|
89
93
|
ElasticsearchSpy.new
|
90
94
|
)
|
95
|
+
|
96
|
+
register(
|
97
|
+
'Elastic::Transport::Client',
|
98
|
+
'elastic-transport',
|
99
|
+
ElasticsearchSpy.new
|
100
|
+
)
|
91
101
|
end
|
92
102
|
end
|
@@ -37,14 +37,8 @@ module ElasticAPM
|
|
37
37
|
|
38
38
|
EVENT_KEY = :__elastic_instrumenter_mongo_events_key
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
Thread.current[EVENT_KEY] ||= {}
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def initialize
|
47
|
-
@collection = Collection.new
|
40
|
+
def events
|
41
|
+
Thread.current[EVENT_KEY] ||= []
|
48
42
|
end
|
49
43
|
|
50
44
|
def started(event)
|
@@ -78,7 +72,7 @@ module ElasticAPM
|
|
78
72
|
# and the collection name is at the key `collection`
|
79
73
|
collection =
|
80
74
|
if event.command[event.command_name] == 1 ||
|
81
|
-
|
75
|
+
event.command[event.command_name].is_a?(BSON::Int64)
|
82
76
|
event.command[:collection]
|
83
77
|
else
|
84
78
|
event.command[event.command_name]
|
@@ -97,14 +91,13 @@ module ElasticAPM
|
|
97
91
|
context: build_context(event)
|
98
92
|
)
|
99
93
|
|
100
|
-
|
94
|
+
events << span
|
101
95
|
end
|
102
96
|
|
103
97
|
def pop_event(event)
|
104
|
-
span = @collection.events.delete(event.operation_id)
|
105
98
|
return unless (curr = ElasticAPM.current_span)
|
106
99
|
|
107
|
-
curr ==
|
100
|
+
curr == events[-1] && ElasticAPM.end_span(events.pop)
|
108
101
|
end
|
109
102
|
|
110
103
|
def build_context(event)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
3
|
+
# this work for additional information regarding copyright
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
6
|
+
# not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
12
|
+
# software distributed under the License is distributed on an
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14
|
+
# KIND, either express or implied. See the License for the
|
15
|
+
# specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'active_support/notifications'
|
20
|
+
require 'active_support/subscriber'
|
21
|
+
|
22
|
+
# frozen_string_literal: true
|
23
|
+
module ElasticAPM
|
24
|
+
# @api private
|
25
|
+
module Spies
|
26
|
+
# @api private
|
27
|
+
class RacecarSpy
|
28
|
+
TYPE = 'kafka'
|
29
|
+
SUBTYPE = 'racecar'
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
class ConsumerSubscriber < ActiveSupport::Subscriber
|
33
|
+
def start_process_message(event)
|
34
|
+
start_process_transaction(event: event, kind: 'process_message')
|
35
|
+
end
|
36
|
+
def process_message(_event)
|
37
|
+
ElasticAPM.end_transaction
|
38
|
+
end
|
39
|
+
|
40
|
+
def start_process_batch(event)
|
41
|
+
start_process_transaction(event: event, kind: 'process_batch')
|
42
|
+
end
|
43
|
+
def process_batch(_event)
|
44
|
+
ElasticAPM.end_transaction
|
45
|
+
end
|
46
|
+
|
47
|
+
private # only public methods will be subscribed
|
48
|
+
|
49
|
+
def start_process_transaction(event:, kind:)
|
50
|
+
ElasticAPM.start_transaction(kind, TYPE)
|
51
|
+
ElasticAPM.current_transaction.context.set_service(framework_name: 'racecar', framework_version: Racecar::VERSION)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class ProducerSubscriber < ActiveSupport::Subscriber
|
56
|
+
def start_deliver_message(event)
|
57
|
+
ElasticAPM.start_transaction('deliver_message',TYPE)
|
58
|
+
ElasticAPM.current_transaction.context.set_service(framework_name: 'racecar', framework_version: Racecar::VERSION)
|
59
|
+
end
|
60
|
+
|
61
|
+
def deliver_message(_event)
|
62
|
+
ElasticAPM.end_transaction
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def install
|
67
|
+
ConsumerSubscriber.attach_to(:racecar)
|
68
|
+
ProducerSubscriber.attach_to(:racecar)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
register 'Racecar', 'racecar', RacecarSpy.new
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
rescue LoadError
|
76
|
+
# no active support available
|
77
|
+
end
|
@@ -44,8 +44,17 @@ module ElasticAPM
|
|
44
44
|
name =
|
45
45
|
ElasticAPM::Spies::SequelSpy.summarizer.summarize sql
|
46
46
|
|
47
|
+
db_name = ''
|
48
|
+
# postgresql shows current database
|
49
|
+
db_name = connection&.db.to_s if connection.respond_to?(:db)
|
50
|
+
# sqlite may expose a filename
|
51
|
+
db_name = connection&.filename.to_s if db_name == '' && connection.respond_to?(:filename)
|
52
|
+
# fall back to adapter class name
|
53
|
+
db_name = connection.class.to_s if db_name == ''
|
54
|
+
|
47
55
|
context = ElasticAPM::Span::Context.new(
|
48
56
|
db: { statement: sql, type: 'sql', user: opts[:user] },
|
57
|
+
service: {target: {type: subtype, name: db_name }},
|
49
58
|
destination: { service: { resource: subtype } }
|
50
59
|
)
|
51
60
|
|
@@ -35,7 +35,6 @@ module ElasticAPM
|
|
35
35
|
include Logging
|
36
36
|
|
37
37
|
WATCHER_EXECUTION_INTERVAL = 5
|
38
|
-
WATCHER_TIMEOUT_INTERVAL = 4
|
39
38
|
WORKER_JOIN_TIMEOUT = 5
|
40
39
|
|
41
40
|
def initialize(config)
|
@@ -112,8 +111,7 @@ module ElasticAPM
|
|
112
111
|
|
113
112
|
def create_watcher
|
114
113
|
@watcher = Concurrent::TimerTask.execute(
|
115
|
-
execution_interval: WATCHER_EXECUTION_INTERVAL
|
116
|
-
timeout_interval: WATCHER_TIMEOUT_INTERVAL
|
114
|
+
execution_interval: WATCHER_EXECUTION_INTERVAL
|
117
115
|
) { ensure_worker_count }
|
118
116
|
end
|
119
117
|
|