elastic-apm 4.1.0 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci/Jenkinsfile +1 -1
- data/.ci/docker/jruby/11-jdk/Dockerfile +1 -1
- data/.ci/docker/jruby/12-jdk/Dockerfile +1 -1
- data/.ci/docker/jruby/13-jdk/Dockerfile +1 -1
- data/.ci/docker/jruby/7-jdk/Dockerfile +1 -1
- data/.ci/docker/jruby/8-jdk/Dockerfile +1 -1
- data/.ci/jobs/apm-agent-ruby-mbp.yml +1 -0
- data/CHANGELOG.asciidoc +51 -0
- data/Gemfile +5 -4
- data/SECURITY.md +7 -0
- data/docker-compose.yml +1 -1
- data/docs/configuration.asciidoc +26 -2
- data/docs/metrics.asciidoc +92 -0
- data/elastic-apm.gemspec +8 -8
- data/lib/elastic_apm/agent.rb +4 -4
- data/lib/elastic_apm/central_config.rb +2 -2
- data/lib/elastic_apm/config.rb +20 -0
- data/lib/elastic_apm/context/request/socket.rb +1 -2
- data/lib/elastic_apm/fields.rb +98 -0
- data/lib/elastic_apm/instrumenter.rb +21 -19
- data/lib/elastic_apm/metadata/service_info.rb +1 -1
- data/lib/elastic_apm/metadata/system_info.rb +2 -1
- data/lib/elastic_apm/metrics/cpu_mem_set.rb +9 -6
- data/lib/elastic_apm/metrics/jvm_set.rb +88 -0
- data/lib/elastic_apm/metrics/metric.rb +2 -0
- data/lib/elastic_apm/metrics.rb +22 -8
- data/lib/elastic_apm/span/context/destination.rb +39 -58
- data/lib/elastic_apm/span.rb +11 -1
- data/lib/elastic_apm/spies/azure_storage_table.rb +148 -0
- data/lib/elastic_apm/spies/dynamo_db.rb +8 -9
- data/lib/elastic_apm/spies/faraday.rb +25 -11
- data/lib/elastic_apm/spies/http.rb +3 -4
- data/lib/elastic_apm/spies/mongo.rb +11 -3
- data/lib/elastic_apm/spies/net_http.rb +21 -14
- data/lib/elastic_apm/spies/s3.rb +11 -5
- data/lib/elastic_apm/spies/sequel.rb +1 -1
- data/lib/elastic_apm/spies/sns.rb +3 -9
- data/lib/elastic_apm/spies/sqs.rb +3 -11
- data/lib/elastic_apm/spies.rb +20 -0
- data/lib/elastic_apm/subscriber.rb +1 -0
- data/lib/elastic_apm/transport/connection/http.rb +3 -1
- data/lib/elastic_apm/transport/serializers/context_serializer.rb +1 -2
- data/lib/elastic_apm/transport/serializers/metadata_serializer.rb +6 -2
- data/lib/elastic_apm/transport/serializers/span_serializer.rb +4 -8
- data/lib/elastic_apm/transport/user_agent.rb +12 -6
- data/lib/elastic_apm/version.rb +1 -1
- data/lib/elastic_apm.rb +6 -2
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c396bc981217532f2d6775de89e9a2aa7a1bcd501100588bbd700d0f4f2eb590
|
4
|
+
data.tar.gz: 94f859585a09fc99f02a4bbd261193e0ed1f74bdb9463968692a16f277b1e4f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae66a68c4651f695361b2028bf76132e8bc257fc141d3ad2872786bbab10b8e19bc3609a84478de53e56ad0c15695ad7debbcf62c4af8997833d0cf7cc7f6d23
|
7
|
+
data.tar.gz: c6b9fd6f80de4139cac0dd040e45d56f869eb2ff8b3db38df376e898490b8c2a5523a9bb3f1ba73a8583356ae5647ec67835b994597dc3db8d72c62ee506794f
|
data/.ci/Jenkinsfile
CHANGED
@@ -39,7 +39,7 @@ pipeline {
|
|
39
39
|
quietPeriod(10)
|
40
40
|
}
|
41
41
|
triggers {
|
42
|
-
issueCommentTrigger(
|
42
|
+
issueCommentTrigger("(${obltGitHubComments()}|^run benchmark tests)")
|
43
43
|
}
|
44
44
|
parameters {
|
45
45
|
booleanParam(name: 'Run_As_Master_Branch', defaultValue: false, description: 'Allow to run any steps on a PR, some steps normally only run on master branch.')
|
data/CHANGELOG.asciidoc
CHANGED
@@ -35,6 +35,57 @@ endif::[]
|
|
35
35
|
[[release-notes-4.x]]
|
36
36
|
=== Ruby Agent version 4.x
|
37
37
|
|
38
|
+
[[release-notes-4.5.0]]
|
39
|
+
==== 4.5.0
|
40
|
+
|
41
|
+
[float]
|
42
|
+
===== Changed
|
43
|
+
|
44
|
+
- Stop collecting the field `http.request.socket.encrypted` {pull}1181[#1181]
|
45
|
+
|
46
|
+
[float]
|
47
|
+
===== Fixed
|
48
|
+
|
49
|
+
- Fixed MongoDB spy thread safety {pull}1202[#1202]
|
50
|
+
- Fixed span context fields for DynamoDB instrumentation {pull}1178[#1178]
|
51
|
+
- Fixed span context fields for S3 instrumentation {pull}1179[#1179]
|
52
|
+
- Update user agent info to match spec {pull}1182[#1182]
|
53
|
+
|
54
|
+
[[release-notes-4.4.0]]
|
55
|
+
==== 4.4.0
|
56
|
+
|
57
|
+
[float]
|
58
|
+
===== Added
|
59
|
+
- Optional span to be ended instead of current span {pull}1039[#1039]
|
60
|
+
- Config option `log_ecs_formatting` {pull}1053[#1053]
|
61
|
+
|
62
|
+
[float]
|
63
|
+
===== Fixed
|
64
|
+
- Fixed detecting Linux on Alpine for CPU/MEM metrics {pull}1057[#1057]
|
65
|
+
|
66
|
+
[[release-notes-4.3.0]]
|
67
|
+
==== 4.3.0
|
68
|
+
|
69
|
+
[float]
|
70
|
+
===== Added
|
71
|
+
|
72
|
+
- Add JVM memory metrics {pull}1040[#1040]
|
73
|
+
|
74
|
+
[[release-notes-4.2.0]]
|
75
|
+
==== 4.2.0
|
76
|
+
|
77
|
+
[float]
|
78
|
+
===== Added
|
79
|
+
|
80
|
+
- Add support for AWS Storage Table/CosmosDB {pull}999[#999]
|
81
|
+
|
82
|
+
[float]
|
83
|
+
===== Fixed
|
84
|
+
|
85
|
+
- Align HTTP span types/subtypes with spec {pull}1014[#1014]
|
86
|
+
- Passing a full URL as a path to `Net::HTTP` {pull}1029[#1029]
|
87
|
+
- Fix growing number of open file descriptors {pull}1033[#1033]
|
88
|
+
|
38
89
|
[[release-notes-4.1.0]]
|
39
90
|
==== 4.1.0
|
40
91
|
|
data/Gemfile
CHANGED
@@ -36,6 +36,8 @@ gem 'aws-sdk-dynamodb', require: nil
|
|
36
36
|
gem 'aws-sdk-s3', require: nil
|
37
37
|
gem 'aws-sdk-sqs', require: nil
|
38
38
|
gem 'aws-sdk-sns', require: nil
|
39
|
+
gem 'azure-storage-table', require: nil if RUBY_VERSION < '3.0'
|
40
|
+
gem 'ecs-logging', require: 'ecs_logging/logger'
|
39
41
|
gem 'elasticsearch', require: nil
|
40
42
|
gem 'fakeredis', require: nil
|
41
43
|
gem 'faraday', require: nil
|
@@ -60,10 +62,6 @@ gem 'sucker_punch', '~> 2.0', require: nil
|
|
60
62
|
gem 'yard', require: nil
|
61
63
|
gem 'yarjuf'
|
62
64
|
|
63
|
-
# See issue #6547 in the JRuby repo. When that bug is fixed,
|
64
|
-
# we can use the latest version of the i18n gem.
|
65
|
-
gem 'i18n', '< 1.8.8'
|
66
|
-
|
67
65
|
## Install Framework
|
68
66
|
GITHUB_REPOS = {
|
69
67
|
'grape' => 'ruby-grape/grape',
|
@@ -99,6 +97,9 @@ if frameworks_versions.key?('rails')
|
|
99
97
|
end
|
100
98
|
|
101
99
|
if RUBY_PLATFORM == 'java'
|
100
|
+
# See issue #6547 in the JRuby repo. It is fixed in JRuby 9.3
|
101
|
+
gem 'i18n', '< 1.8.8' if JRUBY_VERSION < '9.3'
|
102
|
+
|
102
103
|
case rails = frameworks_versions['rails']
|
103
104
|
when 'main'
|
104
105
|
gem 'activerecord-jdbcsqlite3-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', glob: 'activerecord-jdbcsqlite3-adapter/*.gemspec'
|
data/SECURITY.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
Thanks for your interest in the security of our products.
|
4
|
+
Our security policy can be found at [https://www.elastic.co/community/security](https://www.elastic.co/community/security).
|
5
|
+
|
6
|
+
## Reporting a Vulnerability
|
7
|
+
Please send security vulnerability reports to security@elastic.co.
|
data/docker-compose.yml
CHANGED
data/docs/configuration.asciidoc
CHANGED
@@ -240,7 +240,7 @@ NOTE: This feature requires APM Server and Kibana >= 7.3.
|
|
240
240
|
<<dynamic-configuration, image:./images/dynamic-config.svg[] >>
|
241
241
|
|
242
242
|
|============
|
243
|
-
| Environment | `Config` key | Default | Example
|
243
|
+
| Environment | `Config` key | Default | Example
|
244
244
|
| `ELASTIC_APM_CAPTURE_BODY` | `capture_body` | `"off"` | `"all"`
|
245
245
|
|============
|
246
246
|
|
@@ -502,7 +502,31 @@ Use this option to ignore certain URL patterns such as healthchecks or admin sec
|
|
502
502
|
| `ELASTIC_APM_INSTRUMENTED_RAKE_TASKS` | `instrumented_rake_tasks` | `[]` | `['my_task']`
|
503
503
|
|============
|
504
504
|
|
505
|
-
Elastic APM can instrument your Rake tasks.
|
505
|
+
Elastic APM can instrument your Rake tasks. This is an opt-in field, as they are used are for a multitude of things.
|
506
|
+
|
507
|
+
[float]
|
508
|
+
[[config-log-ecs-formatting]]
|
509
|
+
==== `log_ecs_formatting`
|
510
|
+
|
511
|
+
[options="header"]
|
512
|
+
|============
|
513
|
+
| Environment | `Config` key | Default
|
514
|
+
| `ELASTIC_APM_LOG_ECS_FORMATTING` | `log_ecs_formatting` | `off`
|
515
|
+
|============
|
516
|
+
|
517
|
+
This is an experimental option that configures the agent to use the logger from the `ecs-logging` gem. The two
|
518
|
+
valid options are `off` and `override`.
|
519
|
+
|
520
|
+
Setting this option to `override` will set the agent logger to a `EcsLogging::Logger` instance and all logged output
|
521
|
+
will be in ECS-compatible json.
|
522
|
+
|
523
|
+
The `ecs-logging` gem must be installed before the agent is started. If `log_ecs_formatting` is set to `override`,
|
524
|
+
the agent will attempt to require the gem and if it cannot be loaded, it will fall back to using the standard Ruby
|
525
|
+
`::Logger` and log the load error.
|
526
|
+
|
527
|
+
Note that if you're using Rails, the agent will ignore this option and use the Rails logger. If you want to use a
|
528
|
+
`EcsLogging::Logger` when using Rails, set the agent's logger config option explicitly to a `EcsLogging::Logger`
|
529
|
+
instance.
|
506
530
|
|
507
531
|
[float]
|
508
532
|
[[config-log-level]]
|
data/docs/metrics.asciidoc
CHANGED
@@ -141,3 +141,95 @@ The total time spent in garbage collection.
|
|
141
141
|
|
142
142
|
**NB:** You need to enable Ruby's GC Profiler for this to get reported.
|
143
143
|
You can do this at any time when your application boots by calling `GC::Profiler.enable`.
|
144
|
+
|
145
|
+
[float]
|
146
|
+
[[metrics-jvm-metrics]]
|
147
|
+
=== JVM Metrics
|
148
|
+
|
149
|
+
The following metrics are available when using JRuby. They use the ruby java API to gather metrics via MXBean.
|
150
|
+
|
151
|
+
[float]
|
152
|
+
[[metric-jvm.memory.heap.used]]
|
153
|
+
==== `jvm.memory.heap.used`
|
154
|
+
|
155
|
+
* *Type:* Long
|
156
|
+
* *Format:* Bytes
|
157
|
+
|
158
|
+
The amount of used heap memory in bytes.
|
159
|
+
|
160
|
+
[float]
|
161
|
+
[[metric-jvm.memory.heap.committed]]
|
162
|
+
==== `jvm.memory.heap.committed`
|
163
|
+
|
164
|
+
* *Type:* Long
|
165
|
+
* *Format:* Bytes
|
166
|
+
|
167
|
+
The amount of heap memory in bytes that is committed for the Java virtual machine to use. This amount of memory is
|
168
|
+
guaranteed for the Java virtual machine to use.
|
169
|
+
|
170
|
+
[float]
|
171
|
+
[[metric-jvm.memory.heap.max]]
|
172
|
+
==== `jvm.memory.heap.max`
|
173
|
+
|
174
|
+
* *Type:* Long
|
175
|
+
* *Format:* Bytes
|
176
|
+
|
177
|
+
The amount of heap memory in bytes that is committed for the Java virtual machine to use. This amount of memory is
|
178
|
+
guaranteed for the Java virtual machine to use.
|
179
|
+
|
180
|
+
[float]
|
181
|
+
[[metric-jvm.memory.non_heap.used]]
|
182
|
+
==== `jvm.memory.non_heap.used`
|
183
|
+
|
184
|
+
* *Type:* Long
|
185
|
+
* *Format:* Bytes
|
186
|
+
|
187
|
+
The amount of used non-heap memory in bytes.
|
188
|
+
|
189
|
+
[float]
|
190
|
+
[[metric-jvm.memory.non_heap.committed]]
|
191
|
+
==== `jvm.memory.non_heap.committed`
|
192
|
+
|
193
|
+
* *Type:* Long
|
194
|
+
* *Format:* Bytes
|
195
|
+
|
196
|
+
The amount of non-heap memory in bytes that is committed for the Java virtual machine to use. This amount of memory is
|
197
|
+
guaranteed for the Java virtual machine to use.
|
198
|
+
|
199
|
+
[float]
|
200
|
+
[[metric-jvm.memory.non_heap.max]]
|
201
|
+
==== `jvm.memory.non_heap.max`
|
202
|
+
|
203
|
+
* *Type:* Long
|
204
|
+
* *Format:* Bytes
|
205
|
+
|
206
|
+
The maximum amount of non-heap memory in bytes that can be used for memory management. If the maximum memory size is
|
207
|
+
undefined, the value is -1.
|
208
|
+
|
209
|
+
[float]
|
210
|
+
[[metric-jvm.memory.heap.pool.used]]
|
211
|
+
==== `jvm.memory.heap.pool.used`
|
212
|
+
|
213
|
+
* *Type:* Long
|
214
|
+
* *Format:* Bytes
|
215
|
+
|
216
|
+
The amount of used memory in bytes of the memory pool.
|
217
|
+
|
218
|
+
[float]
|
219
|
+
[[metric-jvm.memory.heap.pool.committed]]
|
220
|
+
==== `jvm.memory.heap.pool.committed`
|
221
|
+
|
222
|
+
* *Type:* Long
|
223
|
+
* *Format:* Bytes
|
224
|
+
|
225
|
+
The amount of memory in bytes that is committed for the memory pool. This amount of memory is guaranteed for this
|
226
|
+
specific pool.
|
227
|
+
|
228
|
+
[float]
|
229
|
+
[[metric-jvm.memory.heap.pool.max]]
|
230
|
+
==== `jvm.memory.heap.pool.max`
|
231
|
+
|
232
|
+
* *Type:* Long
|
233
|
+
* *Format:* Bytes
|
234
|
+
|
235
|
+
The maximum amount of memory in bytes that can be used for the memory pool.
|
data/elastic-apm.gemspec
CHANGED
@@ -20,15 +20,15 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
20
20
|
require 'elastic_apm/version'
|
21
21
|
|
22
22
|
Gem::Specification.new do |spec|
|
23
|
-
spec.name
|
24
|
-
spec.version
|
25
|
-
spec.authors
|
26
|
-
spec.email
|
23
|
+
spec.name = 'elastic-apm'
|
24
|
+
spec.version = ElasticAPM::VERSION
|
25
|
+
spec.authors = ['Mikkel Malmberg']
|
26
|
+
spec.email = ['mikkel@elastic.co']
|
27
27
|
|
28
|
-
spec.summary
|
29
|
-
spec.homepage
|
30
|
-
spec.metadata
|
31
|
-
spec.license
|
28
|
+
spec.summary = 'The official Elastic APM agent for Ruby'
|
29
|
+
spec.homepage = 'https://github.com/elastic/apm-agent-ruby'
|
30
|
+
spec.metadata = { 'source_code_uri' => 'https://github.com/elastic/apm-agent-ruby' }
|
31
|
+
spec.license = 'Apache-2.0'
|
32
32
|
spec.required_ruby_version = ">= 2.3.0"
|
33
33
|
|
34
34
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
data/lib/elastic_apm/agent.rb
CHANGED
@@ -211,8 +211,8 @@ module ElasticAPM
|
|
211
211
|
end
|
212
212
|
# rubocop:enable Metrics/ParameterLists
|
213
213
|
|
214
|
-
def end_span
|
215
|
-
instrumenter.end_span
|
214
|
+
def end_span(span = nil)
|
215
|
+
instrumenter.end_span(span)
|
216
216
|
end
|
217
217
|
|
218
218
|
def set_label(key, value)
|
@@ -280,8 +280,8 @@ module ElasticAPM
|
|
280
280
|
def detect_forking!
|
281
281
|
return if @pid == Process.pid
|
282
282
|
|
283
|
-
config.logger.debug
|
284
|
-
restarting threads in process [PID:#{Process.pid}]"
|
283
|
+
config.logger.debug(
|
284
|
+
"Forked process detected, restarting threads in process [PID:#{Process.pid}]")
|
285
285
|
|
286
286
|
central_config.handle_forking!
|
287
287
|
transport.handle_forking!
|
@@ -119,7 +119,7 @@ module ElasticAPM
|
|
119
119
|
end
|
120
120
|
|
121
121
|
if resp.status == 304
|
122
|
-
|
122
|
+
debug 'Received 304 Not Modified'
|
123
123
|
else
|
124
124
|
if resp.body && !resp.body.empty?
|
125
125
|
update = JSON.parse(resp.body.to_s)
|
@@ -169,7 +169,7 @@ module ElasticAPM
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def headers
|
172
|
-
{ '
|
172
|
+
{ 'If-None-Match': @etag }
|
173
173
|
end
|
174
174
|
|
175
175
|
def schedule_next_fetch(resp = nil)
|
data/lib/elastic_apm/config.rb
CHANGED
@@ -70,6 +70,7 @@ module ElasticAPM
|
|
70
70
|
option :ignore_url_patterns, type: :list, default: [], converter: RegexpList.new
|
71
71
|
option :instrument, type: :bool, default: true
|
72
72
|
option :instrumented_rake_tasks, type: :list, default: []
|
73
|
+
option :log_ecs_formatting, type: :string, default: 'off'
|
73
74
|
option :log_level, type: :int, default: Logger::INFO, converter: LogLevelMap.new
|
74
75
|
option :log_path, type: :string
|
75
76
|
option :metrics_interval, type: :int, default: '30s', converter: Duration.new
|
@@ -133,6 +134,7 @@ module ElasticAPM
|
|
133
134
|
def available_instrumentations
|
134
135
|
%w[
|
135
136
|
action_dispatch
|
137
|
+
azure_storage_table
|
136
138
|
delayed_job
|
137
139
|
dynamo_db
|
138
140
|
elasticsearch
|
@@ -245,11 +247,29 @@ module ElasticAPM
|
|
245
247
|
end
|
246
248
|
|
247
249
|
def build_logger
|
250
|
+
if self.log_ecs_formatting == 'override'
|
251
|
+
begin
|
252
|
+
return build_ecs_logger
|
253
|
+
rescue LoadError
|
254
|
+
logger.info "Attempted to use EcsLogging::Logger but the gem couldn't be " \
|
255
|
+
"loaded so a ::Logger was created instead. Check if you have the `ecs-logging` " \
|
256
|
+
"gem installed and attempt to start the agent again."
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
248
260
|
Logger.new(log_path == '-' ? $stdout : log_path).tap do |logger|
|
249
261
|
logger.level = log_level
|
250
262
|
end
|
251
263
|
end
|
252
264
|
|
265
|
+
def build_ecs_logger
|
266
|
+
require 'ecs_logging/logger'
|
267
|
+
|
268
|
+
::EcsLogging::Logger.new(log_path == '-' ? $stdout : log_path).tap do |logger|
|
269
|
+
logger.level = log_level
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
253
273
|
def app_type?(app)
|
254
274
|
if defined?(::Rails::Application) && app.is_a?(::Rails::Application)
|
255
275
|
return :rails
|
@@ -0,0 +1,98 @@
|
|
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
|
+
# An interface for creating simple, value holding objects that correspond to
|
22
|
+
# object fields in the API.
|
23
|
+
#
|
24
|
+
# Example:
|
25
|
+
# class MyThing
|
26
|
+
# include Fields
|
27
|
+
# field :name
|
28
|
+
# field :address, default: 'There'
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# MyThing.new(name: 'AJ').to_h
|
32
|
+
# # => { name: 'AJ' }
|
33
|
+
# MyThing.new().empty?
|
34
|
+
# # => true
|
35
|
+
module Fields
|
36
|
+
class Field
|
37
|
+
def initialize(key, default: nil)
|
38
|
+
@key = key
|
39
|
+
@default = default
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :key, :default
|
43
|
+
end
|
44
|
+
|
45
|
+
module InstanceMethods
|
46
|
+
def initialize(**attrs)
|
47
|
+
schema.each do |key, field|
|
48
|
+
send(:"#{key}=", field.default)
|
49
|
+
end
|
50
|
+
|
51
|
+
attrs.each do |key, value|
|
52
|
+
send(:"#{key}=", value)
|
53
|
+
end
|
54
|
+
|
55
|
+
super()
|
56
|
+
end
|
57
|
+
|
58
|
+
def empty?
|
59
|
+
self.class.schema.each do |key, field|
|
60
|
+
next if send(key).nil?
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_h
|
68
|
+
schema.each_with_object({}) do |(key, field), hsh|
|
69
|
+
hsh[key] = send(key)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def schema
|
76
|
+
self.class.schema
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module ClassMethods
|
81
|
+
def field(key, default: nil)
|
82
|
+
field = Field.new(key, default: default)
|
83
|
+
schema[key] = field
|
84
|
+
|
85
|
+
attr_accessor(key)
|
86
|
+
end
|
87
|
+
|
88
|
+
attr_reader :schema
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.included(cls)
|
92
|
+
cls.extend(ClassMethods)
|
93
|
+
cls.include(InstanceMethods)
|
94
|
+
|
95
|
+
cls.instance_variable_set(:@schema, {})
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -179,7 +179,8 @@ module ElasticAPM
|
|
179
179
|
context: nil,
|
180
180
|
trace_context: nil,
|
181
181
|
parent: nil,
|
182
|
-
sync: nil
|
182
|
+
sync: nil,
|
183
|
+
exit_span: nil
|
183
184
|
)
|
184
185
|
|
185
186
|
transaction =
|
@@ -197,6 +198,15 @@ module ElasticAPM
|
|
197
198
|
|
198
199
|
parent ||= (current_span || current_transaction)
|
199
200
|
|
201
|
+
# To not mess with breakdown metric stats, exit spans MUST not add
|
202
|
+
# sub-spans unless they share the same type and subtype.
|
203
|
+
if parent && parent.is_a?(Span) && parent.exit_span?
|
204
|
+
if parent.type != type || parent.subtype != subtype
|
205
|
+
debug "Skipping new span '#{name}' as its parent is an exit_span"
|
206
|
+
return
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
200
210
|
span = Span.new(
|
201
211
|
name: name,
|
202
212
|
subtype: subtype,
|
@@ -207,7 +217,8 @@ module ElasticAPM
|
|
207
217
|
type: type,
|
208
218
|
context: context,
|
209
219
|
stacktrace_builder: stacktrace_builder,
|
210
|
-
sync: sync
|
220
|
+
sync: sync,
|
221
|
+
exit_span: exit_span
|
211
222
|
)
|
212
223
|
|
213
224
|
if backtrace && transaction.span_frames_min_duration
|
@@ -222,8 +233,14 @@ module ElasticAPM
|
|
222
233
|
# rubocop:enable Metrics/CyclomaticComplexity
|
223
234
|
# rubocop:enable Metrics/PerceivedComplexity
|
224
235
|
|
225
|
-
def end_span
|
226
|
-
|
236
|
+
def end_span(span = nil)
|
237
|
+
if span
|
238
|
+
current_spans.delete(span)
|
239
|
+
else
|
240
|
+
span = current_spans.pop
|
241
|
+
end
|
242
|
+
|
243
|
+
return unless span
|
227
244
|
|
228
245
|
span.done
|
229
246
|
|
@@ -273,24 +290,9 @@ module ElasticAPM
|
|
273
290
|
'transaction.type': transaction.type
|
274
291
|
}
|
275
292
|
|
276
|
-
@metrics.get(:transaction).timer(
|
277
|
-
:'transaction.duration.sum.us',
|
278
|
-
tags: tags, reset_on_collect: true
|
279
|
-
).update(transaction.duration)
|
280
|
-
|
281
|
-
@metrics.get(:transaction).counter(
|
282
|
-
:'transaction.duration.count',
|
283
|
-
tags: tags, reset_on_collect: true
|
284
|
-
).inc!
|
285
|
-
|
286
293
|
return unless transaction.sampled?
|
287
294
|
return unless transaction.breakdown_metrics
|
288
295
|
|
289
|
-
@metrics.get(:breakdown).counter(
|
290
|
-
:'transaction.breakdown.count',
|
291
|
-
tags: tags, reset_on_collect: true
|
292
|
-
).inc!
|
293
|
-
|
294
296
|
span_tags = tags.merge('span.type': 'app')
|
295
297
|
|
296
298
|
@metrics.get(:breakdown).timer(
|
@@ -49,7 +49,7 @@ module ElasticAPM
|
|
49
49
|
)
|
50
50
|
@language = Language.new(name: 'ruby', version: RUBY_VERSION)
|
51
51
|
@runtime = lookup_runtime
|
52
|
-
@version = @config.service_version
|
52
|
+
@version = @config.service_version
|
53
53
|
end
|
54
54
|
|
55
55
|
attr_reader :name, :node_name, :environment, :agent, :framework,
|