elastic-apm 4.5.0 → 4.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci/.jenkins_exclude.yml +94 -37
- data/.ci/.jenkins_framework.yml +4 -3
- data/.ci/.jenkins_main_framework.yml +4 -0
- data/.ci/.jenkins_ruby.yml +1 -1
- data/.ci/.jenkins_ruby_benchmarks.yml +6 -0
- data/.ci/Jenkinsfile +46 -36
- data/.ci/docker/jruby/11-jdk/Dockerfile +8 -3
- data/.ci/docker/jruby/12-jdk/Dockerfile +5 -2
- data/.ci/docker/jruby/13-jdk/Dockerfile +5 -2
- data/.ci/docker/jruby/7-jdk/Dockerfile +6 -3
- data/.ci/docker/jruby/8-jdk/Dockerfile +8 -3
- data/.ci/docker/jruby/README.md +1 -1
- data/.ci/docker/jruby/run.sh +33 -9
- data/.ci/docker/jruby/test.sh +17 -2
- data/.ci/jobs/apm-agent-ruby-mbp.yml +1 -1
- data/.ci/snapshoty.yml +34 -0
- data/.ci/update-specs.yml +108 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +5 -5
- data/.github/workflows/update-specs.yml +30 -0
- data/.pre-commit-config.yaml +2 -2
- data/CHANGELOG.asciidoc +55 -1
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +15 -4
- data/README.md +1 -1
- data/Rakefile +4 -4
- data/bench/report.rb +1 -1
- data/docker-compose.yml +6 -0
- 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/faraday.rb +13 -4
- 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 +4 -2
- data/lib/elastic_apm/trace_context.rb +1 -1
- data/lib/elastic_apm/transport/base.rb +1 -3
- data/lib/elastic_apm/transport/connection/http.rb +9 -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 +32 -9
- data/.ci/.jenkins_master_framework.yml +0 -4
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
|
@@ -103,10 +103,19 @@ module ElasticAPM
|
|
103
103
|
ElasticAPM::Spies.without_net_http do
|
104
104
|
trace_context = span&.trace_context || transaction.trace_context
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
begin
|
107
|
+
result = super(method, url, body, headers) do |req|
|
108
|
+
trace_context.apply_headers { |k, v| req[k] = v }
|
109
|
+
yield req if block
|
110
|
+
end
|
111
|
+
rescue Faraday::ClientError, Faraday::ServerError => e # Faraday::Response::RaiseError
|
112
|
+
status = e.response[:status]
|
113
|
+
http = span&.context&.http
|
114
|
+
if http && status
|
115
|
+
http.status_code = status.to_s
|
116
|
+
span.outcome = Span::Outcome.from_http_status(status)
|
117
|
+
end
|
118
|
+
raise e
|
110
119
|
end
|
111
120
|
|
112
121
|
if (http = span&.context&.http)
|
@@ -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
|
|
@@ -92,6 +92,8 @@ module ElasticAPM
|
|
92
92
|
|
93
93
|
extend Forwardable
|
94
94
|
|
95
|
+
ENTRY_SPLIT_REGEX = /\s*[\n,]+\s*/
|
96
|
+
|
95
97
|
def initialize(entries: {}, sample_rate: nil)
|
96
98
|
@entries = entries
|
97
99
|
|
@@ -107,7 +109,7 @@ module ElasticAPM
|
|
107
109
|
split_by_nl_and_comma(header)
|
108
110
|
.each_with_object({}) do |entry, hsh|
|
109
111
|
k, v = entry.split('=')
|
110
|
-
|
112
|
+
next unless k && v && !k.empty? && !v.empty?
|
111
113
|
hsh[k] =
|
112
114
|
case k
|
113
115
|
when 'es' then EsEntry.new(v)
|
@@ -140,7 +142,7 @@ module ElasticAPM
|
|
140
142
|
# Rack handles this by joining the headers under the same key,
|
141
143
|
# separated by newlines.
|
142
144
|
# See https://www.rubydoc.info/github/rack/rack/file/SPEC
|
143
|
-
String(str).split(
|
145
|
+
String(str).split(ENTRY_SPLIT_REGEX).flatten
|
144
146
|
end
|
145
147
|
end
|
146
148
|
end
|
@@ -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
|
|
@@ -75,7 +75,15 @@ module ElasticAPM
|
|
75
75
|
@closed.make_true
|
76
76
|
|
77
77
|
@wr&.close
|
78
|
-
|
78
|
+
|
79
|
+
if @request&.join(5)
|
80
|
+
@rd&.close
|
81
|
+
return
|
82
|
+
end
|
83
|
+
|
84
|
+
@rd&.close
|
85
|
+
|
86
|
+
return if @request.nil?
|
79
87
|
|
80
88
|
error(
|
81
89
|
'%s: APM Server not responding in time, terminating request',
|
@@ -117,8 +125,6 @@ module ElasticAPM
|
|
117
125
|
error(
|
118
126
|
"Couldn't establish connection to APM Server:\n%p", e.inspect
|
119
127
|
)
|
120
|
-
ensure
|
121
|
-
@rd&.close
|
122
128
|
end
|
123
129
|
end
|
124
130
|
end
|