elastic-apm 3.15.1 → 4.2.0
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 +13 -0
- data/.ci/.jenkins_ruby.yml +0 -1
- data/.ci/Jenkinsfile +1 -0
- data/.github/dependabot.yml +16 -0
- data/.rubocop.yml +0 -7
- data/CHANGELOG.asciidoc +77 -4
- data/Gemfile +4 -1
- data/README.md +12 -0
- data/SECURITY.md +7 -0
- data/bench/report.rb +1 -1
- data/bin/run-bdd +17 -0
- data/bin/run-tests +1 -1
- data/docker-compose.yml +1 -1
- data/docs/configuration.asciidoc +62 -147
- data/docs/release-notes.asciidoc +1 -0
- data/docs/upgrading.asciidoc +0 -27
- data/lib/elastic_apm.rb +12 -1
- data/lib/elastic_apm/agent.rb +7 -3
- data/lib/elastic_apm/central_config.rb +8 -7
- data/lib/elastic_apm/config.rb +2 -88
- data/lib/elastic_apm/config/regexp_list.rb +1 -1
- data/lib/elastic_apm/config/wildcard_pattern_list.rb +1 -1
- data/lib/elastic_apm/context/response.rb +1 -3
- data/lib/elastic_apm/fields.rb +88 -0
- data/lib/elastic_apm/grpc.rb +2 -4
- data/lib/elastic_apm/instrumenter.rb +1 -1
- 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 +1 -1
- data/lib/elastic_apm/normalizers.rb +2 -2
- data/lib/elastic_apm/normalizers/rails/active_record.rb +3 -3
- data/lib/elastic_apm/opentracing.rb +3 -2
- data/lib/elastic_apm/span.rb +26 -1
- data/lib/elastic_apm/span/context.rb +2 -1
- data/lib/elastic_apm/span/context/destination.rb +53 -40
- data/lib/elastic_apm/span_helpers.rb +6 -8
- data/lib/elastic_apm/spies.rb +20 -0
- data/lib/elastic_apm/spies/action_dispatch.rb +10 -9
- data/lib/elastic_apm/spies/azure_storage_table.rb +148 -0
- data/lib/elastic_apm/spies/dynamo_db.rb +12 -12
- data/lib/elastic_apm/spies/elasticsearch.rb +32 -29
- data/lib/elastic_apm/spies/faraday.rb +83 -63
- data/lib/elastic_apm/spies/http.rb +33 -34
- data/lib/elastic_apm/spies/mongo.rb +5 -3
- data/lib/elastic_apm/spies/net_http.rb +59 -56
- data/lib/elastic_apm/spies/rake.rb +28 -26
- data/lib/elastic_apm/spies/redis.rb +11 -10
- data/lib/elastic_apm/spies/resque.rb +18 -21
- data/lib/elastic_apm/spies/s3.rb +14 -15
- data/lib/elastic_apm/spies/sequel.rb +42 -48
- data/lib/elastic_apm/spies/sidekiq.rb +13 -15
- data/lib/elastic_apm/spies/sinatra.rb +20 -21
- data/lib/elastic_apm/spies/sns.rb +39 -44
- data/lib/elastic_apm/spies/sqs.rb +21 -31
- data/lib/elastic_apm/spies/tilt.rb +10 -9
- data/lib/elastic_apm/sql/tokenizer.rb +21 -5
- data/lib/elastic_apm/stacktrace_builder.rb +3 -1
- data/lib/elastic_apm/subscriber.rb +1 -0
- data/lib/elastic_apm/trace_context.rb +5 -13
- data/lib/elastic_apm/trace_context/traceparent.rb +5 -6
- data/lib/elastic_apm/transport/connection.rb +1 -1
- data/lib/elastic_apm/transport/connection/http.rb +4 -2
- data/lib/elastic_apm/transport/connection/proxy_pipe.rb +1 -2
- data/lib/elastic_apm/transport/filters/hash_sanitizer.rb +5 -23
- data/lib/elastic_apm/transport/serializers/metadata_serializer.rb +3 -2
- data/lib/elastic_apm/transport/serializers/metricset_serializer.rb +2 -2
- data/lib/elastic_apm/transport/serializers/span_serializer.rb +12 -12
- data/lib/elastic_apm/transport/user_agent.rb +3 -2
- data/lib/elastic_apm/transport/worker.rb +1 -1
- data/lib/elastic_apm/util/deep_dup.rb +1 -1
- data/lib/elastic_apm/version.rb +1 -1
- metadata +12 -9
- data/lib/elastic_apm/sql.rb +0 -36
- data/lib/elastic_apm/sql_summarizer.rb +0 -53
data/docs/release-notes.asciidoc
CHANGED
data/docs/upgrading.asciidoc
CHANGED
@@ -16,30 +16,3 @@ We love all our products, but sometimes we must say goodbye to a release so that
|
|
16
16
|
forward on future development and innovation.
|
17
17
|
Our https://www.elastic.co/support/eol[End of life policy] defines how long a given release is considered supported,
|
18
18
|
as well as how long a release is considered still in active development or maintenance.
|
19
|
-
The table below is a simplified description of this policy.
|
20
|
-
|
21
|
-
[options="header"]
|
22
|
-
|====
|
23
|
-
|Agent version |EOL Date |Maintained until
|
24
|
-
|3.5.x |2021-07-17 | 3.6
|
25
|
-
|3.4.x |2021-07-10 | 3.5
|
26
|
-
|3.3.x |2021-06-04 | 3.4
|
27
|
-
|3.2.x |2021-05-19 | 3.3
|
28
|
-
|3.1.x |2021-04-21 | 3.2
|
29
|
-
|3.0.x |2021-04-08 | 3.1
|
30
|
-
|2.12.x |2021-04-01 |4.0
|
31
|
-
|2.11.x |2021-03-23 |2.12
|
32
|
-
|2.10.x |2021-03-03 |2.11
|
33
|
-
|2.9.x |2020-12-25 |2.10
|
34
|
-
|2.8.x |2020-11-20 |2.9
|
35
|
-
|2.7.x |2020-11-07 |2.8
|
36
|
-
|2.6.x |2020-09-19 |2.7
|
37
|
-
|2.5.x |2020-09-01 |2.6
|
38
|
-
|2.4.x |2020-08-27 |2.5
|
39
|
-
|2.3.x |2020-07-29 |2.4
|
40
|
-
|2.2.x |2020-07-22 |2.3
|
41
|
-
|2.1.x |2020-06-04 |2.2
|
42
|
-
|2.0.x |2020-05-14 |2.1
|
43
|
-
|1.1.x |2020-03-07 |3.0
|
44
|
-
|1.0.x |2019-12-29 |1.1
|
45
|
-
|====
|
data/lib/elastic_apm.rb
CHANGED
@@ -32,6 +32,7 @@ require 'elastic_apm/internal_error'
|
|
32
32
|
require 'elastic_apm/logging'
|
33
33
|
|
34
34
|
# Core
|
35
|
+
require 'elastic_apm/fields'
|
35
36
|
require 'elastic_apm/agent'
|
36
37
|
require 'elastic_apm/config'
|
37
38
|
require 'elastic_apm/context'
|
@@ -380,6 +381,16 @@ module ElasticAPM
|
|
380
381
|
agent&.set_user(user)
|
381
382
|
end
|
382
383
|
|
384
|
+
# Set destination fields on the current span
|
385
|
+
#
|
386
|
+
# @param address [String] Destination address
|
387
|
+
# @param address [String] Destination address
|
388
|
+
# @param address [Hash] Destination service
|
389
|
+
# @param address [Hash] Destination cloud
|
390
|
+
def set_destination(address: nil, port: nil, service: nil, cloud: nil)
|
391
|
+
agent&.set_destination(address: address, port: port, service: service, cloud: cloud)
|
392
|
+
end
|
393
|
+
|
383
394
|
# Provide a filter to transform payloads before sending them off
|
384
395
|
#
|
385
396
|
# @param key [Symbol] Unique filter key
|
@@ -387,7 +398,7 @@ module ElasticAPM
|
|
387
398
|
# @yield [Hash] A filter. Used if provided. Otherwise using `callback`
|
388
399
|
# @return [Bool] true
|
389
400
|
def add_filter(key, callback = nil, &block)
|
390
|
-
if callback.nil? && !
|
401
|
+
if callback.nil? && !block
|
391
402
|
raise ArgumentError, '#add_filter needs either `callback\' or a block'
|
392
403
|
end
|
393
404
|
|
data/lib/elastic_apm/agent.rb
CHANGED
@@ -127,7 +127,7 @@ module ElasticAPM
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def stop
|
130
|
-
|
130
|
+
info 'Stopping agent'
|
131
131
|
|
132
132
|
central_config.stop
|
133
133
|
metrics.stop
|
@@ -227,6 +227,10 @@ module ElasticAPM
|
|
227
227
|
instrumenter.set_user(user)
|
228
228
|
end
|
229
229
|
|
230
|
+
def set_destination(address: nil, port: nil, service: nil, cloud: nil)
|
231
|
+
current_span&.set_destination(address: nil, port: nil, service: nil, cloud: nil)
|
232
|
+
end
|
233
|
+
|
230
234
|
def build_context(rack_env:, for_type:)
|
231
235
|
@context_builder.build(rack_env: rack_env, for_type: for_type)
|
232
236
|
end
|
@@ -276,8 +280,8 @@ module ElasticAPM
|
|
276
280
|
def detect_forking!
|
277
281
|
return if @pid == Process.pid
|
278
282
|
|
279
|
-
config.logger.debug
|
280
|
-
restarting threads in process [PID:#{Process.pid}]"
|
283
|
+
config.logger.debug(
|
284
|
+
"Forked process detected, restarting threads in process [PID:#{Process.pid}]")
|
281
285
|
|
282
286
|
central_config.handle_forking!
|
283
287
|
transport.handle_forking!
|
@@ -66,9 +66,9 @@ module ElasticAPM
|
|
66
66
|
def fetch_and_apply_config
|
67
67
|
@promise =
|
68
68
|
Concurrent::Promise
|
69
|
-
.execute
|
70
|
-
.on_success(
|
71
|
-
.rescue(
|
69
|
+
.execute { fetch_config }
|
70
|
+
.on_success { |resp| handle_success(resp) }
|
71
|
+
.rescue { |err| handle_error(err) }
|
72
72
|
end
|
73
73
|
|
74
74
|
def fetch_config
|
@@ -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)
|
@@ -182,7 +183,7 @@ module ElasticAPM
|
|
182
183
|
|
183
184
|
@scheduled_task =
|
184
185
|
Concurrent::ScheduledTask
|
185
|
-
.execute(seconds
|
186
|
+
.execute(seconds) { fetch_and_apply_config }
|
186
187
|
end
|
187
188
|
end
|
188
189
|
end
|
data/lib/elastic_apm/config.rb
CHANGED
@@ -30,14 +30,8 @@ module ElasticAPM
|
|
30
30
|
class Config
|
31
31
|
extend Options
|
32
32
|
|
33
|
-
DEPRECATED_OPTIONS = %i[].freeze
|
34
|
-
|
35
|
-
# DEPRECATED: To align with other agents, change on next major bump to:
|
36
|
-
# "password, passwd, pwd, secret, *key, *token*, *session*, *credit*,
|
37
|
-
# *card*, authorization, set-cookie"
|
38
33
|
SANITIZE_FIELD_NAMES_DEFAULT =
|
39
|
-
%w[
|
40
|
-
*credit* *card* *authorization* *set-cookie*].freeze
|
34
|
+
%w[password passwd pwd secret *key *token* *session* *credit* *card* authorization set-cookie].freeze
|
41
35
|
|
42
36
|
# rubocop:disable Layout/LineLength, Layout/ExtraSpacing
|
43
37
|
option :config_file, type: :string, default: 'config/elastic_apm.yml'
|
@@ -101,7 +95,6 @@ module ElasticAPM
|
|
101
95
|
option :transaction_max_spans, type: :int, default: 500
|
102
96
|
option :transaction_sample_rate, type: :float, default: 1.0, converter: RoundFloat.new
|
103
97
|
option :use_elastic_traceparent_header, type: :bool, default: true
|
104
|
-
option :use_legacy_sql_parser, type: :bool, default: false
|
105
98
|
option :verify_server_cert, type: :bool, default: true
|
106
99
|
|
107
100
|
# rubocop:enable Layout/LineLength, Layout/ExtraSpacing
|
@@ -140,6 +133,7 @@ module ElasticAPM
|
|
140
133
|
def available_instrumentations
|
141
134
|
%w[
|
142
135
|
action_dispatch
|
136
|
+
azure_storage_table
|
143
137
|
delayed_job
|
144
138
|
dynamo_db
|
145
139
|
elasticsearch
|
@@ -168,11 +162,6 @@ module ElasticAPM
|
|
168
162
|
available_instrumentations - disable_instrumentations
|
169
163
|
end
|
170
164
|
|
171
|
-
def method_missing(name, *args)
|
172
|
-
return super unless DEPRECATED_OPTIONS.include?(name)
|
173
|
-
warn "The option `#{name}' has been removed."
|
174
|
-
end
|
175
|
-
|
176
165
|
def replace_options(new_options)
|
177
166
|
return if new_options.nil? || new_options.empty?
|
178
167
|
options_copy = @options.dup
|
@@ -201,15 +190,6 @@ module ElasticAPM
|
|
201
190
|
metrics_interval > 0
|
202
191
|
end
|
203
192
|
|
204
|
-
# DEPRECATED: Remove this in next major version
|
205
|
-
def sanitize_field_names=(value)
|
206
|
-
list = WildcardPatternList.new.call(value)
|
207
|
-
defaults = WildcardPatternList.new.call(SANITIZE_FIELD_NAMES_DEFAULT)
|
208
|
-
# use regex pattern for comparisons
|
209
|
-
get(:sanitize_field_names).value =
|
210
|
-
defaults.concat(list).uniq(&:pattern)
|
211
|
-
end
|
212
|
-
|
213
193
|
def span_frames_min_duration?
|
214
194
|
span_frames_min_duration != 0
|
215
195
|
end
|
@@ -248,72 +228,6 @@ module ElasticAPM
|
|
248
228
|
super.split.first + '>'
|
249
229
|
end
|
250
230
|
|
251
|
-
# Deprecations
|
252
|
-
|
253
|
-
def default_tags=(value)
|
254
|
-
warn '[DEPRECATED] The option default_tags has been renamed to ' \
|
255
|
-
'default_labels.'
|
256
|
-
self.default_labels = value
|
257
|
-
end
|
258
|
-
|
259
|
-
def ignore_url_patterns=(value)
|
260
|
-
unless value == self.class.schema[:ignore_url_patterns][:default]
|
261
|
-
warn '[DEPRECATED] The option ignore_url_patterns is being removed. ' \
|
262
|
-
'Consider using transaction_ignore_urls instead.'
|
263
|
-
end
|
264
|
-
|
265
|
-
set(:ignore_url_patterns, value)
|
266
|
-
end
|
267
|
-
|
268
|
-
def custom_key_filters=(value)
|
269
|
-
unless value == self.class.schema[:custom_key_filters][:default]
|
270
|
-
warn '[DEPRECATED] The option custom_key_filters is being removed. ' \
|
271
|
-
'See sanitize_field_names for an alternative.'
|
272
|
-
end
|
273
|
-
|
274
|
-
set(:custom_key_filters, value)
|
275
|
-
end
|
276
|
-
|
277
|
-
def disabled_instrumentations
|
278
|
-
disable_instrumentations
|
279
|
-
end
|
280
|
-
|
281
|
-
def active
|
282
|
-
enabled
|
283
|
-
end
|
284
|
-
alias active? active
|
285
|
-
|
286
|
-
def server_ca_cert
|
287
|
-
server_ca_cert_file
|
288
|
-
end
|
289
|
-
|
290
|
-
def disabled_instrumentations=(value)
|
291
|
-
warn '[DEPRECATED] The option disabled_instrumentations has been ' \
|
292
|
-
'renamed to disable_instrumentations to align with other agents.'
|
293
|
-
self.disable_instrumentations = value
|
294
|
-
end
|
295
|
-
|
296
|
-
def use_experimental_sql_parser=(_value)
|
297
|
-
warn '[DEPRECATED] The new SQL parser is now the default. To use the ' \
|
298
|
-
'old one, use use_legacy_sql_parser and please report why you ' \
|
299
|
-
'wish to do so.'
|
300
|
-
end
|
301
|
-
|
302
|
-
def active=(value)
|
303
|
-
warn '[DEPRECATED] The option active has been renamed to enabled ' \
|
304
|
-
'to align with other agents and with the remote config.'
|
305
|
-
self.enabled = value
|
306
|
-
end
|
307
|
-
|
308
|
-
def server_ca_cert=(value)
|
309
|
-
unless value == self.class.schema[:server_ca_cert_file][:default]
|
310
|
-
warn '[DEPRECATED] The option server_ca_cert has been ' \
|
311
|
-
'renamed to server_ca_cert_file to align with other agents.'
|
312
|
-
end
|
313
|
-
|
314
|
-
self.server_ca_cert_file = value
|
315
|
-
end
|
316
|
-
|
317
231
|
private
|
318
232
|
|
319
233
|
def load_config_file
|
@@ -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
|
data/lib/elastic_apm/grpc.rb
CHANGED
@@ -50,11 +50,9 @@ module ElasticAPM
|
|
50
50
|
|
51
51
|
split_peer = URI.split(peer)
|
52
52
|
destination = ElasticAPM::Span::Context::Destination.new(
|
53
|
-
type: TYPE,
|
54
|
-
name: SUBTYPE,
|
55
|
-
resource: peer,
|
56
53
|
address: split_peer[0],
|
57
|
-
port: split_peer[6]
|
54
|
+
port: split_peer[6],
|
55
|
+
service: { type: TYPE, name: SUBTYPE, resource: peer }
|
58
56
|
)
|
59
57
|
ElasticAPM::Span::Context.new(destination: destination)
|
60
58
|
end
|
@@ -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
|