elastic-apm 4.5.1 → 4.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci/.exclude.yml +193 -0
- data/.ci/{.jenkins_framework.yml → .framework.yml} +3 -2
- data/.ci/.main_framework.yml +4 -0
- data/.ci/.ruby.yml +10 -0
- 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/scripts/bench.sh +52 -0
- data/.ci/scripts/install-build-system.sh +5 -0
- data/.ci/snapshoty.yml +33 -0
- data/.ci/updatecli.d/update-gherkin-specs.yml +126 -0
- data/.ci/updatecli.d/update-json-specs.yml +130 -0
- data/.ci/updatecli.d/update-specs.yml +118 -0
- data/.github/dependabot.yml +17 -1
- data/.github/workflows/README.md +58 -0
- data/.github/workflows/ci-docs.yml +20 -0
- data/.github/workflows/ci.yml +70 -0
- data/.github/workflows/coverage-reporter.yml +34 -0
- data/.github/workflows/microbenchmark.yml +48 -0
- data/.github/workflows/opentelemetry.yml +27 -0
- data/.github/workflows/release.yml +71 -0
- data/.github/workflows/run-matrix.yml +56 -0
- data/.github/workflows/snapshoty.yml +35 -0
- data/.github/workflows/test-reporter.yml +24 -0
- data/.github/workflows/updatecli.yml +28 -0
- data/.pre-commit-config.yaml +0 -2
- data/CHANGELOG.asciidoc +73 -1
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +28 -8
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/bench/report.rb +1 -1
- data/bench/rubyprof.rb +1 -0
- data/bin/run-tests +10 -1
- data/docker-compose.yml +10 -1
- data/docs/configuration.asciidoc +12 -9
- data/docs/index.asciidoc +2 -2
- data/docs/{log-correlation.asciidoc → logs.asciidoc} +29 -2
- data/docs/opentracing.asciidoc +1 -1
- data/docs/redirects.asciidoc +9 -0
- 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/context_builder.rb +6 -3
- 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/cloud_info.rb +9 -7
- 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 +24 -20
- 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 +8 -8
- data/lib/elastic_apm/spies/action_dispatch.rb +11 -3
- data/lib/elastic_apm/spies/faraday.rb +20 -4
- 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/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/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 +46 -17
- data/.ci/.jenkins_exclude.yml +0 -134
- data/.ci/.jenkins_main_framework.yml +0 -4
- data/.ci/.jenkins_ruby.yml +0 -10
- data/.ci/Jenkinsfile +0 -441
- data/.ci/jobs/apm-agent-ruby-downstream.yml +0 -38
- data/.ci/jobs/apm-agent-ruby-linting-mbp.yml +0 -39
- data/.ci/jobs/apm-agent-ruby-mbp.yml +0 -43
- data/.ci/jobs/apm-agent-ruby.yml +0 -4
- data/.ci/jobs/defaults.yml +0 -24
- data/.ci/linting.groovy +0 -32
- data/.ci/packer_cache.sh +0 -16
- /data/.ci/{.jenkins_codecov.yml → .codecov.yml} +0 -0
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 +
|
@@ -44,7 +44,7 @@ module ElasticAPM
|
|
44
44
|
request = context.request
|
45
45
|
|
46
46
|
request.socket = Context::Request::Socket.new(req)
|
47
|
-
request.http_version = build_http_version
|
47
|
+
request.http_version = build_http_version req
|
48
48
|
request.method = req.request_method
|
49
49
|
request.url = Context::Request::Url.new(req)
|
50
50
|
|
@@ -55,6 +55,9 @@ module ElasticAPM
|
|
55
55
|
request.env = env if config.capture_env?
|
56
56
|
|
57
57
|
request.cookies = req.cookies.dup
|
58
|
+
unless request.cookies.empty?
|
59
|
+
request.headers['Cookie'] = SKIPPED if request.headers.has_key?('Cookie')
|
60
|
+
end
|
58
61
|
|
59
62
|
context
|
60
63
|
end
|
@@ -104,8 +107,8 @@ module ElasticAPM
|
|
104
107
|
key.gsub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
|
105
108
|
end
|
106
109
|
|
107
|
-
def build_http_version(
|
108
|
-
return unless (http_version =
|
110
|
+
def build_http_version(req)
|
111
|
+
return unless (http_version = req.env['HTTP_VERSION'])
|
109
112
|
http_version.gsub(%r{HTTP/}, '')
|
110
113
|
end
|
111
114
|
end
|
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
|
|
@@ -94,16 +94,18 @@ module ElasticAPM
|
|
94
94
|
return unless resp.status == 200
|
95
95
|
return unless (metadata = JSON.parse(resp.body.to_s))
|
96
96
|
|
97
|
-
zone = metadata["instance"]["zone"]&.split("/")&.at(-1)
|
98
|
-
|
99
97
|
self.provider = "gcp"
|
100
|
-
self.
|
101
|
-
|
102
|
-
|
103
|
-
|
98
|
+
self.project_id = metadata["project"]["projectId"]
|
99
|
+
|
100
|
+
return unless metadata['instance']
|
101
|
+
|
102
|
+
zone = metadata["instance"]["zone"]&.split("/")&.at(-1)
|
104
103
|
self.availability_zone = zone
|
105
104
|
self.region = zone.split("-")[0..-2].join("-")
|
106
|
-
|
105
|
+
|
106
|
+
self.instance_id = metadata["instance"]["id"].to_s
|
107
|
+
self.instance_name = metadata["instance"]["name"]
|
108
|
+
self.machine_type = metadata["instance"]["machineType"]&.split("/")&.at(-1)
|
107
109
|
rescue HTTP::TimeoutError, HTTP::ConnectionError
|
108
110
|
nil
|
109
111
|
end
|
@@ -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
@@ -50,27 +50,9 @@ module ElasticAPM
|
|
50
50
|
return
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
# Only set the @sets once, in case we stop
|
56
|
-
# and start again.
|
57
|
-
if @sets.nil?
|
58
|
-
sets = {
|
59
|
-
system: CpuMemSet,
|
60
|
-
vm: VMSet,
|
61
|
-
breakdown: BreakdownSet,
|
62
|
-
transaction: TransactionSet
|
63
|
-
}
|
64
|
-
if defined?(JVMSet)
|
65
|
-
debug "Enabling JVM metrics collection"
|
66
|
-
sets[:jvm] = JVMSet
|
67
|
-
end
|
53
|
+
define_sets
|
68
54
|
|
69
|
-
|
70
|
-
debug "Adding metrics collector '#{kls}'"
|
71
|
-
_sets_[key] = kls.new(config)
|
72
|
-
end
|
73
|
-
end
|
55
|
+
debug 'Starting metrics'
|
74
56
|
|
75
57
|
@timer_task = Concurrent::TimerTask.execute(
|
76
58
|
run_now: true,
|
@@ -135,6 +117,28 @@ module ElasticAPM
|
|
135
117
|
arr.concat(samples)
|
136
118
|
end
|
137
119
|
end
|
120
|
+
|
121
|
+
def define_sets
|
122
|
+
# Only set the @sets once, in case we stop
|
123
|
+
# and start again.
|
124
|
+
return unless @sets.nil?
|
125
|
+
|
126
|
+
sets = {
|
127
|
+
system: CpuMemSet,
|
128
|
+
vm: VMSet,
|
129
|
+
breakdown: BreakdownSet,
|
130
|
+
transaction: TransactionSet
|
131
|
+
}
|
132
|
+
if defined?(JVMSet)
|
133
|
+
debug "Enabling JVM metrics collection"
|
134
|
+
sets[:jvm] = JVMSet
|
135
|
+
end
|
136
|
+
|
137
|
+
@sets = sets.each_with_object({}) do |(key, kls), _sets_|
|
138
|
+
debug "Adding metrics collector '#{kls}'"
|
139
|
+
_sets_[key] = kls.new(config)
|
140
|
+
end
|
141
|
+
end
|
138
142
|
end
|
139
143
|
end
|
140
144
|
end
|
@@ -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
|
@@ -22,30 +22,30 @@ module ElasticAPM
|
|
22
22
|
module SpanHelpers
|
23
23
|
# @api private
|
24
24
|
module ClassMethods
|
25
|
-
def span_class_method(method, name = nil, type = nil)
|
26
|
-
__span_method_on(singleton_class, method, name, type)
|
25
|
+
def span_class_method(method, name = nil, type = nil, **kwargs)
|
26
|
+
__span_method_on(singleton_class, method, name, type, **kwargs)
|
27
27
|
end
|
28
28
|
|
29
|
-
def span_method(method, name = nil, type = nil)
|
30
|
-
__span_method_on(self, method, name, type)
|
29
|
+
def span_method(method, name = nil, type = nil, **kwargs)
|
30
|
+
__span_method_on(self, method, name, type, **kwargs)
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
-
def __span_method_on(klass, method, name = nil, type = nil)
|
35
|
+
def __span_method_on(klass, method, name = nil, type = nil, **kwargs)
|
36
36
|
name ||= method.to_s
|
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
|
44
44
|
|
45
|
-
ElasticAPM.with_span name.to_s, type.to_s do
|
45
|
+
ElasticAPM.with_span name.to_s, type.to_s, **kwargs do
|
46
46
|
super(*args, &block)
|
47
47
|
end
|
48
|
-
end
|
48
|
+
end)
|
49
49
|
end)
|
50
50
|
end
|
51
51
|
end
|
@@ -24,11 +24,19 @@ module ElasticAPM
|
|
24
24
|
class ActionDispatchSpy
|
25
25
|
# @api private
|
26
26
|
module Ext
|
27
|
-
def render_exception(
|
28
|
-
context = ElasticAPM.build_context(
|
27
|
+
def render_exception(request, exception_or_wrapper)
|
28
|
+
context = ElasticAPM.build_context(
|
29
|
+
rack_env: request, for_type: :error
|
30
|
+
)
|
31
|
+
exception =
|
32
|
+
if exception_or_wrapper.is_a?(ActionDispatch::ExceptionWrapper)
|
33
|
+
exception_or_wrapper.exception
|
34
|
+
else
|
35
|
+
exception_or_wrapper
|
36
|
+
end
|
29
37
|
ElasticAPM.report(exception, context: context, handled: false)
|
30
38
|
|
31
|
-
super(
|
39
|
+
super(request, exception_or_wrapper)
|
32
40
|
end
|
33
41
|
end
|
34
42
|
|
@@ -103,10 +103,26 @@ 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 =
|
113
|
+
if e.respond_to?(:response_status)
|
114
|
+
e.response_status
|
115
|
+
elsif e.response && e.response.respond_to?(:status)
|
116
|
+
e.response.status
|
117
|
+
elsif e.response && e.response.respond_to?(:fetch)
|
118
|
+
e.response[:status]
|
119
|
+
end
|
120
|
+
http = span&.context&.http
|
121
|
+
if http && status
|
122
|
+
http.status_code = status.to_s
|
123
|
+
span.outcome = Span::Outcome.from_http_status(status)
|
124
|
+
end
|
125
|
+
raise e
|
110
126
|
end
|
111
127
|
|
112
128
|
if (http = span&.context&.http)
|