elastic-apm 4.0.0 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci/jobs/apm-agent-ruby-mbp.yml +1 -0
- data/.github/dependabot.yml +16 -0
- data/CHANGELOG.asciidoc +55 -0
- data/Gemfile +2 -0
- data/SECURITY.md +7 -0
- data/docker-compose.yml +1 -1
- data/docs/configuration.asciidoc +25 -1
- data/docs/metrics.asciidoc +92 -0
- data/lib/elastic_apm/agent.rb +4 -4
- data/lib/elastic_apm/central_config.rb +4 -3
- data/lib/elastic_apm/config.rb +20 -0
- data/lib/elastic_apm/fields.rb +88 -0
- data/lib/elastic_apm/instrumenter.rb +8 -2
- data/lib/elastic_apm/metadata/cloud_info.rb +32 -5
- data/lib/elastic_apm/metadata/system_info.rb +14 -4
- data/lib/elastic_apm/metrics/cpu_mem_set.rb +6 -6
- data/lib/elastic_apm/metrics/jvm_set.rb +88 -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 +18 -0
- data/lib/elastic_apm/span_helpers.rb +3 -3
- data/lib/elastic_apm/spies/azure_storage_table.rb +148 -0
- data/lib/elastic_apm/spies/dynamo_db.rb +2 -8
- data/lib/elastic_apm/spies/faraday.rb +25 -11
- data/lib/elastic_apm/spies/http.rb +3 -4
- data/lib/elastic_apm/spies/net_http.rb +21 -14
- data/lib/elastic_apm/spies/s3.rb +4 -7
- 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/metadata_serializer.rb +3 -2
- data/lib/elastic_apm/transport/serializers/span_serializer.rb +4 -8
- data/lib/elastic_apm/version.rb +1 -1
- data/lib/elastic_apm.rb +6 -2
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bd0b20acebcfa91bc6e5d4e580c6a1a5f8da35b06152a4fe949c76380667e58
|
4
|
+
data.tar.gz: 85935357d8a1831233cb8ab837564b38ff800e29a0cf1891fd4ba6263bb1a0d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6eabaee4c14440607bdc5b5a0e53fd8b3844e0756a16cf6ef0da4b2a5431e7c1b441d0ef6329baf7d89f165f44031aa6a8396541930576acf54b254a787994cc
|
7
|
+
data.tar.gz: e601985643738456350d49ba9c261ccc17a0259651830230cf353d20c241403846f73c3ce371ab5b6f1a97b1223ac797ddfc1b764333e51055ff53104becd212
|
@@ -0,0 +1,16 @@
|
|
1
|
+
version: 2
|
2
|
+
updates:
|
3
|
+
- package-ecosystem: bundler
|
4
|
+
directory: "/"
|
5
|
+
schedule:
|
6
|
+
interval: daily
|
7
|
+
open-pull-requests-limit: 10
|
8
|
+
ignore:
|
9
|
+
- dependency-name: sucker_punch
|
10
|
+
versions:
|
11
|
+
- "> 2.0"
|
12
|
+
- dependency-name: i18n
|
13
|
+
versions:
|
14
|
+
- 1.8.10
|
15
|
+
- 1.8.8
|
16
|
+
- 1.8.9
|
data/CHANGELOG.asciidoc
CHANGED
@@ -35,6 +35,61 @@ endif::[]
|
|
35
35
|
[[release-notes-4.x]]
|
36
36
|
=== Ruby Agent version 4.x
|
37
37
|
|
38
|
+
[[release-notes-4.4.0]]
|
39
|
+
==== 4.4.0
|
40
|
+
|
41
|
+
[float]
|
42
|
+
===== Added
|
43
|
+
- Optional span to be ended instead of current span {pull}1039[#1039]
|
44
|
+
- Config option `log_ecs_formatting` {pull}1053[#1053]
|
45
|
+
|
46
|
+
[float]
|
47
|
+
===== Fixed
|
48
|
+
- Fixed detecting Linux on Alpine for CPU/MEM metrics {pull}1057[#1057]
|
49
|
+
|
50
|
+
[[release-notes-4.3.0]]
|
51
|
+
==== 4.3.0
|
52
|
+
|
53
|
+
[float]
|
54
|
+
===== Added
|
55
|
+
|
56
|
+
- Add JVM memory metrics {pull}1040[#1040]
|
57
|
+
|
58
|
+
[[release-notes-4.2.0]]
|
59
|
+
==== 4.2.0
|
60
|
+
|
61
|
+
[float]
|
62
|
+
===== Added
|
63
|
+
|
64
|
+
- Add support for AWS Storage Table/CosmosDB {pull}999[#999]
|
65
|
+
|
66
|
+
[float]
|
67
|
+
===== Fixed
|
68
|
+
|
69
|
+
- Align HTTP span types/subtypes with spec {pull}1014[#1014]
|
70
|
+
- Passing a full URL as a path to `Net::HTTP` {pull}1029[#1029]
|
71
|
+
- Fix growing number of open file descriptors {pull}1033[#1033]
|
72
|
+
|
73
|
+
[[release-notes-4.1.0]]
|
74
|
+
==== 4.1.0
|
75
|
+
|
76
|
+
[float]
|
77
|
+
===== Added
|
78
|
+
|
79
|
+
- Azure App Services instance metadata {pull}1007[#1007]
|
80
|
+
|
81
|
+
[float]
|
82
|
+
===== Changed
|
83
|
+
|
84
|
+
- `hostname` is now reported split by `configured_hostname` and `detected_hostname` {pull}1009[#1009]
|
85
|
+
|
86
|
+
[float]
|
87
|
+
===== Fixed
|
88
|
+
- `service_node_name` is now correctly reported as `service.node.configured_name` {pull}1009[#1009]
|
89
|
+
- Fix JSON parsing when using yajl-ruby {pull}1012[#1012]
|
90
|
+
- Fix SpanHelpers when methods take blocks {pull}1013[#1013]
|
91
|
+
- Fix missing `environment` param when fetching from Central Config {pull}1014[#1014]
|
92
|
+
|
38
93
|
[[release-notes-4.0.0]]
|
39
94
|
==== 4.0.0
|
40
95
|
|
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
|
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
@@ -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. Theis is an opt-in field, as they are used are for a multitude of things.
|
505
|
+
Elastic APM can instrument your Rake tasks. Theis 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/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)
|
@@ -164,11 +164,12 @@ module ElasticAPM
|
|
164
164
|
@server_url ||=
|
165
165
|
config.server_url +
|
166
166
|
'/config/v1/agents' \
|
167
|
-
"?service.name=#{CGI.escape(config.service_name)}"
|
167
|
+
"?service.name=#{CGI.escape(config.service_name)}" \
|
168
|
+
"&service.environment=#{CGI.escape(config.environment || '')}"
|
168
169
|
end
|
169
170
|
|
170
171
|
def headers
|
171
|
-
{ '
|
172
|
+
{ 'If-None-Match': @etag }
|
172
173
|
end
|
173
174
|
|
174
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,88 @@
|
|
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, optional: true
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# MyThing.new(name: 'AJ').to_h
|
32
|
+
# # => { name: 'AJ' }
|
33
|
+
# MyThing.new().empty?
|
34
|
+
# # => true
|
35
|
+
module Fields
|
36
|
+
module InstanceMethods
|
37
|
+
def initialize(**attrs)
|
38
|
+
attrs.each do |key, value|
|
39
|
+
self.send(:"#{key}=", value)
|
40
|
+
end
|
41
|
+
|
42
|
+
super()
|
43
|
+
end
|
44
|
+
|
45
|
+
def empty?
|
46
|
+
self.class.fields.each do |key|
|
47
|
+
next if send(key)
|
48
|
+
next if optionals.include?(key)
|
49
|
+
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_h
|
57
|
+
self.class.fields.each_with_object({}) do |key, fields|
|
58
|
+
fields[key] = send(key)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def optionals
|
65
|
+
self.class.optionals
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module ClassMethods
|
70
|
+
def field(key, optional: false)
|
71
|
+
attr_accessor(key)
|
72
|
+
|
73
|
+
fields.push(key)
|
74
|
+
optionals.push(key) if optional
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_reader :fields, :optionals
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.included(cls)
|
81
|
+
cls.extend(ClassMethods)
|
82
|
+
cls.include(InstanceMethods)
|
83
|
+
|
84
|
+
cls.instance_variable_set(:@fields, [])
|
85
|
+
cls.instance_variable_set(:@optionals, [])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -222,8 +222,14 @@ module ElasticAPM
|
|
222
222
|
# rubocop:enable Metrics/CyclomaticComplexity
|
223
223
|
# rubocop:enable Metrics/PerceivedComplexity
|
224
224
|
|
225
|
-
def end_span
|
226
|
-
|
225
|
+
def end_span(span = nil)
|
226
|
+
if span
|
227
|
+
current_spans.delete(span)
|
228
|
+
else
|
229
|
+
span = current_spans.pop
|
230
|
+
end
|
231
|
+
|
232
|
+
return unless span
|
227
233
|
|
228
234
|
span.done
|
229
235
|
|
@@ -57,9 +57,9 @@ module ElasticAPM
|
|
57
57
|
when "gcp"
|
58
58
|
fetch_gcp
|
59
59
|
when "azure"
|
60
|
-
fetch_azure
|
60
|
+
fetch_azure || read_azure_app_services
|
61
61
|
when "auto"
|
62
|
-
fetch_aws || fetch_gcp || fetch_azure
|
62
|
+
fetch_aws || fetch_gcp || fetch_azure || read_azure_app_services
|
63
63
|
when "none"
|
64
64
|
nil
|
65
65
|
else
|
@@ -76,7 +76,7 @@ module ElasticAPM
|
|
76
76
|
resp = @client.get(AWS_URI)
|
77
77
|
|
78
78
|
return unless resp.status == 200
|
79
|
-
return unless (metadata = JSON.parse(resp.body))
|
79
|
+
return unless (metadata = JSON.parse(resp.body.to_s))
|
80
80
|
|
81
81
|
self.provider = "aws"
|
82
82
|
self.account_id = metadata["accountId"]
|
@@ -92,7 +92,7 @@ module ElasticAPM
|
|
92
92
|
resp = @client.headers("Metadata-Flavor" => "Google").get(GCP_URI)
|
93
93
|
|
94
94
|
return unless resp.status == 200
|
95
|
-
return unless (metadata = JSON.parse(resp.body))
|
95
|
+
return unless (metadata = JSON.parse(resp.body.to_s))
|
96
96
|
|
97
97
|
zone = metadata["instance"]["zone"]&.split("/")&.at(-1)
|
98
98
|
|
@@ -112,7 +112,7 @@ module ElasticAPM
|
|
112
112
|
resp = @client.headers("Metadata" => "true").get(AZURE_URI)
|
113
113
|
|
114
114
|
return unless resp.status == 200
|
115
|
-
return unless (metadata = JSON.parse(resp.body))
|
115
|
+
return unless (metadata = JSON.parse(resp.body.to_s))
|
116
116
|
|
117
117
|
self.provider = 'azure'
|
118
118
|
self.account_id = metadata["subscriptionId"]
|
@@ -125,6 +125,33 @@ module ElasticAPM
|
|
125
125
|
rescue HTTP::TimeoutError, HTTP::ConnectionError
|
126
126
|
nil
|
127
127
|
end
|
128
|
+
|
129
|
+
def read_azure_app_services
|
130
|
+
owner_name, instance_id, site_name, resource_group =
|
131
|
+
ENV.values_at(
|
132
|
+
'WEBSITE_OWNER_NAME',
|
133
|
+
'WEBSITE_INSTANCE_ID',
|
134
|
+
'WEBSITE_SITE_NAME',
|
135
|
+
'WEBSITE_RESOURCE_GROUP'
|
136
|
+
)
|
137
|
+
|
138
|
+
return unless owner_name && instance_id && site_name && resource_group
|
139
|
+
|
140
|
+
self.provider = 'azure'
|
141
|
+
self.instance_id = instance_id
|
142
|
+
self.instance_name = site_name
|
143
|
+
self.project_name = resource_group
|
144
|
+
self.account_id, self.region = parse_azure_app_services_owner_name(owner_name)
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def parse_azure_app_services_owner_name(owner_name)
|
150
|
+
id, rest = owner_name.split('+')
|
151
|
+
*_, region = rest.split('-')
|
152
|
+
region.gsub!(/webspace.*$/, '')
|
153
|
+
[id, region]
|
154
|
+
end
|
128
155
|
end
|
129
156
|
end
|
130
157
|
end
|
@@ -24,7 +24,8 @@ module ElasticAPM
|
|
24
24
|
def initialize(config)
|
25
25
|
@config = config
|
26
26
|
|
27
|
-
@
|
27
|
+
@configured_hostname = @config.hostname
|
28
|
+
@detected_hostname = detect_hostname
|
28
29
|
@architecture = gem_platform.cpu
|
29
30
|
@platform = gem_platform.os
|
30
31
|
|
@@ -33,14 +34,23 @@ module ElasticAPM
|
|
33
34
|
@kubernetes = container_info.kubernetes
|
34
35
|
end
|
35
36
|
|
36
|
-
attr_reader
|
37
|
+
attr_reader(
|
38
|
+
:detected_hostname,
|
39
|
+
:configured_hostname,
|
40
|
+
:architecture,
|
41
|
+
:platform,
|
42
|
+
:container,
|
43
|
+
:kubernetes
|
44
|
+
)
|
37
45
|
|
38
46
|
def gem_platform
|
39
47
|
@gem_platform ||= Gem::Platform.local
|
40
48
|
end
|
41
49
|
|
42
|
-
|
43
|
-
|
50
|
+
private
|
51
|
+
|
52
|
+
def detect_hostname
|
53
|
+
`hostname`.chomp
|
44
54
|
end
|
45
55
|
end
|
46
56
|
end
|
@@ -62,8 +62,8 @@ module ElasticAPM
|
|
62
62
|
def initialize(config)
|
63
63
|
super
|
64
64
|
|
65
|
-
@sampler =
|
66
|
-
read! # set
|
65
|
+
@sampler = sampler_for_os(Metrics.os)
|
66
|
+
read! # set initial values to calculate deltas from
|
67
67
|
end
|
68
68
|
|
69
69
|
attr_reader :config
|
@@ -75,11 +75,11 @@ module ElasticAPM
|
|
75
75
|
|
76
76
|
private
|
77
77
|
|
78
|
-
def
|
79
|
-
case
|
80
|
-
when
|
78
|
+
def sampler_for_os(os)
|
79
|
+
case os
|
80
|
+
when /^linux/ then Linux.new
|
81
81
|
else
|
82
|
-
warn "Disabling system metrics, unsupported
|
82
|
+
warn "Disabling system metrics, unsupported host OS '#{os}'"
|
83
83
|
disable!
|
84
84
|
nil
|
85
85
|
end
|
@@ -0,0 +1,88 @@
|
|
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
|
+
require 'java'
|
21
|
+
|
22
|
+
module ElasticAPM
|
23
|
+
module Metrics
|
24
|
+
# @api private
|
25
|
+
class JVMSet < Set
|
26
|
+
include Logging
|
27
|
+
|
28
|
+
MAX_TRIES = 3
|
29
|
+
|
30
|
+
def initialize(*args)
|
31
|
+
super
|
32
|
+
|
33
|
+
@error_count = 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def collect
|
37
|
+
read!
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def read!
|
42
|
+
return if disabled?
|
43
|
+
|
44
|
+
heap = platform_bean.get_heap_memory_usage
|
45
|
+
non_heap = platform_bean.get_non_heap_memory_usage
|
46
|
+
|
47
|
+
gauge(:"jvm.memory.heap.used").value = heap.get_used
|
48
|
+
gauge(:"jvm.memory.heap.committed").value = heap.get_committed
|
49
|
+
gauge(:"jvm.memory.heap.max").value = heap.get_max
|
50
|
+
|
51
|
+
gauge(:"jvm.memory.non_heap.used").value = non_heap.get_used
|
52
|
+
gauge(:"jvm.memory.non_heap.committed").value = non_heap.get_committed
|
53
|
+
gauge(:"jvm.memory.non_heap.max").value = non_heap.get_max
|
54
|
+
|
55
|
+
pool_beans.each do |bean|
|
56
|
+
next unless bean.type.name == "HEAP"
|
57
|
+
|
58
|
+
tags = { name: bean.get_name }
|
59
|
+
|
60
|
+
gauge(:"jvm.memory.heap.pool.used", tags: tags).value = bean.get_usage.get_used
|
61
|
+
gauge(:"jvm.memory.heap.pool.committed", tags: tags).value = bean.get_usage.get_committed
|
62
|
+
gauge(:"jvm.memory.heap.pool.max", tags: tags).value = bean.get_usage.get_max
|
63
|
+
end
|
64
|
+
rescue Exception => e
|
65
|
+
error("JVM metrics encountered error: %s", e)
|
66
|
+
debug("Backtrace:") { e.backtrace.join("\n") }
|
67
|
+
|
68
|
+
@error_count += 1
|
69
|
+
if @error_count >= MAX_TRIES
|
70
|
+
disable!
|
71
|
+
error("Disabling JVM metrics after #{MAX_TRIES} errors", e)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def platform_bean
|
78
|
+
@platform_bean ||= java.lang.management.ManagementFactory.getPlatformMXBean(
|
79
|
+
java.lang.management.MemoryMXBean.java_class
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
def pool_beans
|
84
|
+
@pool_beans ||= java.lang.management.ManagementFactory.getMemoryPoolMXBeans()
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|