elastic-apm 3.8.0 → 3.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.asciidoc +72 -0
  3. data/Gemfile +2 -3
  4. data/docs/configuration.asciidoc +1 -0
  5. data/docs/debugging.asciidoc +14 -0
  6. data/docs/supported-technologies.asciidoc +2 -1
  7. data/lib/elastic_apm/config.rb +32 -5
  8. data/lib/elastic_apm/config/options.rb +2 -1
  9. data/lib/elastic_apm/config/round_float.rb +31 -0
  10. data/lib/elastic_apm/config/wildcard_pattern_list.rb +13 -1
  11. data/lib/elastic_apm/context_builder.rb +1 -1
  12. data/lib/elastic_apm/instrumenter.rb +10 -3
  13. data/lib/elastic_apm/metadata.rb +3 -1
  14. data/lib/elastic_apm/metadata/cloud_info.rb +128 -0
  15. data/lib/elastic_apm/metadata/system_info.rb +5 -3
  16. data/lib/elastic_apm/metadata/system_info/container_info.rb +28 -4
  17. data/lib/elastic_apm/middleware.rb +8 -2
  18. data/lib/elastic_apm/span.rb +7 -3
  19. data/lib/elastic_apm/spies/delayed_job.rb +4 -2
  20. data/lib/elastic_apm/spies/dynamo_db.rb +58 -0
  21. data/lib/elastic_apm/spies/elasticsearch.rb +11 -1
  22. data/lib/elastic_apm/trace_context.rb +1 -1
  23. data/lib/elastic_apm/trace_context/traceparent.rb +2 -4
  24. data/lib/elastic_apm/trace_context/tracestate.rb +112 -9
  25. data/lib/elastic_apm/transaction.rb +26 -5
  26. data/lib/elastic_apm/transport/connection.rb +1 -0
  27. data/lib/elastic_apm/transport/filters/hash_sanitizer.rb +9 -16
  28. data/lib/elastic_apm/transport/filters/secrets_filter.rb +8 -6
  29. data/lib/elastic_apm/transport/serializers.rb +8 -6
  30. data/lib/elastic_apm/transport/serializers/metadata_serializer.rb +43 -3
  31. data/lib/elastic_apm/transport/serializers/span_serializer.rb +2 -1
  32. data/lib/elastic_apm/transport/serializers/transaction_serializer.rb +1 -0
  33. data/lib/elastic_apm/transport/user_agent.rb +3 -3
  34. data/lib/elastic_apm/transport/worker.rb +5 -0
  35. data/lib/elastic_apm/util.rb +2 -0
  36. data/lib/elastic_apm/util/precision_validator.rb +46 -0
  37. data/lib/elastic_apm/version.rb +1 -1
  38. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32d176ac5c22246df60ecc92f1baad37011a872af4e64f842b5a43c699a6ced3
4
- data.tar.gz: bf0505e728d8f1bd0bb941574a844a8990d14e13a94a7c9f2a6c2d0f9eb5d35b
3
+ metadata.gz: 54d7b5d46523e74fc797ec2030a355b6137e92a40ecb8242a9a79d551d6b2f89
4
+ data.tar.gz: ba614dd32ce665845f09d9c840fff0f6e8a34637a703f849a7b22edbeb350d25
5
5
  SHA512:
6
- metadata.gz: d57b6bdbc7e78bea95e197d33f3eef4db7a35b23f9e450c636c3c1e3a5dd75ee8ee195709944ac51d6af7a3ab2451fd19d6139f0dedf9e86a4827732d5097f2a
7
- data.tar.gz: 924b9bbf782a0fa4e376137e9a44d10cc01be71455ca7614ab1374c70f0926d174eb1078b985cd60c1693e2e0ec1cdd8446502bd40007359262dcc31241250aa
6
+ metadata.gz: fd0d35a56be409fd3ee55352d68a9ef7cfd13add082edb41ca971bde54895c70babd30025e6a87134123a999be2732b476a8868b3db617b9f315940124f8e2ad
7
+ data.tar.gz: 75e7e737b4f927dbbbb6b828ae5c628b3e37334409a43b1e94cc09cb9b403dcbb7030e766e49cadba9683536032119514f022570abb97c066fce6a59959dbf6f
@@ -35,6 +35,78 @@ endif::[]
35
35
  [[release-notes-3.x]]
36
36
  === Ruby Agent version 3.x
37
37
 
38
+ [[release-notes-3.11.1]]
39
+ ==== 3.11.1 (2020-11-05)
40
+
41
+ [float]
42
+ ===== Fixed
43
+
44
+ - Fix reporting from Kubernetes based deploys to APM Server 7.9.x {pull}885[#885]
45
+
46
+ [[release-notes-3.11.0]]
47
+ ==== 3.11.0 (2020-10-27)
48
+
49
+ [float]
50
+ ===== Added
51
+
52
+ - Add and read sampling info from Tracestate headers {pull}858[#858]
53
+ - Add information about cloud hosting environment if available {pull}871[#871]
54
+
55
+ [float]
56
+ ===== Changed
57
+
58
+ - Align the default value of `sanitize_field_names` with other agents {pull}867[#867]
59
+ - Ensure max 4 digits of precision for `sample_rate` as per agent spec {pull}880[#880]
60
+
61
+ [float]
62
+ ===== Fixed
63
+
64
+ - Fix Delayed::Job class names when used through ActiveJob {pull}869[#869]
65
+ - Fix Delayed::Job when run without the agent running {pull}874[#874]
66
+ - Fix Kubernetes related metadata {pull}882[#882]
67
+
68
+ [[release-notes-3.10.1]]
69
+ ==== 3.10.1 (2020-08-26)
70
+
71
+ [float]
72
+ ===== Fixed
73
+
74
+ - Remove secrets from cookies in errors {pull}863[#863]
75
+ - Silence deprecation warning when setting `ignore_url_patterns` to default {pull}865[#865]
76
+
77
+ [[release-notes-3.10.0]]
78
+ ==== 3.10.0 (2020-08-26)
79
+
80
+ [float]
81
+ ===== Added
82
+
83
+ - Config option `transaction_ignore_urls` to replace `ignore_url_patterns` {pull}844[#844]
84
+ - Prepend `(?-i)` to patterns to make them case-sensitive {pull}846[#846]
85
+
86
+ [float]
87
+ ===== Fixed
88
+
89
+ - Reverted {pull}839[#839]
90
+ - Improved Kubernetes pod ID detection {pull}859[#859]
91
+
92
+ [[release-notes-3.9.0]]
93
+ ==== 3.9.0 (2020-08-04)
94
+
95
+ [float]
96
+ ===== Fixed
97
+ - Scrub request body of illegal UTF-8 characters {pull}832[#832]
98
+
99
+ [float]
100
+ ===== Added
101
+
102
+ - Support for DynamoDB {pull}827[#827]
103
+
104
+ [float]
105
+ ===== Fixed
106
+
107
+ - Fix Rails Engine views' paths being reported as absolute {pull}839[#839]
108
+ - Fix an issue when using Elasticsearch spy without a running agent {pull}830[#830]
109
+
38
110
  [[release-notes-3.8.0]]
39
111
  ==== 3.8.0 (2020-06-18)
40
112
 
data/Gemfile CHANGED
@@ -22,18 +22,16 @@ source 'https://rubygems.org'
22
22
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
23
23
 
24
24
  # Tools
25
- gem 'bootsnap', require: false
26
25
  gem 'cucumber', require: false
27
26
  gem 'pry'
28
27
  gem 'rack-test'
29
28
  gem 'rspec', '~> 3'
30
29
  gem 'rspec-its'
31
- gem 'rubocop', require: nil
32
- gem 'rubocop-performance', require: nil
33
30
  gem 'timecop'
34
31
  gem 'webmock'
35
32
 
36
33
  # Integrations
34
+ gem 'aws-sdk-dynamodb', require: nil
37
35
  gem 'aws-sdk-sqs', require: nil
38
36
  gem 'elasticsearch', require: nil
39
37
  gem 'fakeredis', require: nil
@@ -41,6 +39,7 @@ gem 'faraday', require: nil
41
39
  gem 'graphql', require: nil
42
40
  gem 'google-protobuf', '< 3.12' if !defined?(JRUBY_VERSION) && RUBY_VERSION < '2.5'
43
41
  gem 'grpc' if !defined?(JRUBY_VERSION)
42
+ gem 'json'
44
43
  gem 'json-schema', require: nil
45
44
  gem 'mongo', require: nil
46
45
  gem 'opentracing', require: nil
@@ -853,6 +853,7 @@ To reduce overhead and storage requirements, you can set the sample rate to a va
853
853
  between `0.0` and `1.0`.
854
854
  We still record overall time and the result for unsampled transactions, but no
855
855
  context information, tags, or spans.
856
+ Note that the sample rate will be rounded to 4 digits of precision.
856
857
 
857
858
  [float]
858
859
  [[config-use-experimental-sql-parser]]
@@ -28,3 +28,17 @@ Things to consider:
28
28
  - Experiencing high load? The agent can spawn multiple instances of its Workers that pick off the queue by changing the option `pool_size` (default is `1`).
29
29
  - If you have high load you may also consider setting `transaction_sample_rate` to something smaller than `1.0`. This determines whether to include _spans_ for every _transaction_. If you have enough traffic, skipping some (probably) identical spans won't have a noticeable effect on your data.
30
30
 
31
+ [float]
32
+ [[disable-agent]]
33
+ === Disable the Agent
34
+
35
+ In the unlikely event the agent causes disruptions to a production application,
36
+ you can disable the agent while you troubleshoot.
37
+
38
+ If you have access to <<dynamic-configuration,dynamic configuration>>,
39
+ you can disable the recording of events by setting <<config-recording,`recording`>> to `false`.
40
+ When changed at runtime from a supported source, there's no need to restart your application.
41
+
42
+ If that doesn't work, or you don't have access to dynamic configuration, you can disable the agent by setting
43
+ <<config-enabled,`enabled`>> to `false`.
44
+ You'll need to restart your application for the changes to apply.
@@ -60,6 +60,7 @@ See <<getting-started-grape>>.
60
60
  We automatically instrument database actions using:
61
61
 
62
62
  - ActiveRecord (v4.2+)
63
+ - DynamoDB (v1.0+)
63
64
  - Elasticsearch (v0.9+)
64
65
  - Mongo (v2.1+)
65
66
  - Redis (v3.1+)
@@ -151,4 +152,4 @@ To instrument a server, add the `ElasticAPM::GRPC::ServerInterceptor`.
151
152
  [source,ruby]
152
153
  ----
153
154
  GRPC::RpcServer.new(interceptors: [ElasticAPM::GRPC::ServerInterceptor.new])
154
- ----
155
+ ----
@@ -17,9 +17,10 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
- require 'elastic_apm/config/options'
21
- require 'elastic_apm/config/duration'
22
20
  require 'elastic_apm/config/bytes'
21
+ require 'elastic_apm/config/duration'
22
+ require 'elastic_apm/config/options'
23
+ require 'elastic_apm/config/round_float'
23
24
  require 'elastic_apm/config/regexp_list'
24
25
  require 'elastic_apm/config/wildcard_pattern_list'
25
26
 
@@ -30,6 +31,11 @@ module ElasticAPM
30
31
 
31
32
  DEPRECATED_OPTIONS = %i[].freeze
32
33
 
34
+ # DEPRECATED: To align with other agents, change on next major bump to:
35
+ # "password, passwd, pwd, secret, *key, *token*, *session*, *credit*, *card*, authorization, set-cookie"
36
+ SANITIZE_FIELD_NAMES_DEFAULT =
37
+ %w[*password* *passwd* *pwd* *secret* *key* *token* *session* *credit* *card* *authorization* *set-cookie*]
38
+
33
39
  # rubocop:disable Metrics/LineLength, Layout/ExtraSpacing
34
40
  option :config_file, type: :string, default: 'config/elastic_apm.yml'
35
41
  option :server_url, type: :url, default: 'http://localhost:8200'
@@ -45,6 +51,7 @@ module ElasticAPM
45
51
  option :capture_elasticsearch_queries, type: :bool, default: false
46
52
  option :capture_env, type: :bool, default: true
47
53
  option :central_config, type: :bool, default: true
54
+ option :cloud_provider, type: :string, default: 'auto'
48
55
  option :current_user_email_method, type: :string, default: 'email'
49
56
  option :current_user_id_method, type: :string, default: 'id'
50
57
  option :current_user_username_method, type: :string, default: 'username'
@@ -76,7 +83,8 @@ module ElasticAPM
76
83
  option :proxy_port, type: :int
77
84
  option :proxy_username, type: :string
78
85
  option :recording, type: :bool, default: true
79
- option :sanitize_field_names, type: :list, default: [], converter: WildcardPatternList.new
86
+ option :sanitize_field_names, type: :list,
87
+ default: SANITIZE_FIELD_NAMES_DEFAULT, converter: WildcardPatternList.new
80
88
  option :server_ca_cert, type: :string
81
89
  option :service_name, type: :string
82
90
  option :service_node_name, type: :string
@@ -87,8 +95,9 @@ module ElasticAPM
87
95
  option :source_lines_span_library_frames, type: :int, default: 0
88
96
  option :span_frames_min_duration, type: :float, default: '5ms', converter: Duration.new(default_unit: 'ms')
89
97
  option :stack_trace_limit, type: :int, default: 999_999
98
+ option :transaction_ignore_urls, type: :list, default: [], converter: WildcardPatternList.new
90
99
  option :transaction_max_spans, type: :int, default: 500
91
- option :transaction_sample_rate, type: :float, default: 1.0
100
+ option :transaction_sample_rate, type: :float, default: 1.0, converter: RoundFloat.new
92
101
  option :use_elastic_traceparent_header, type: :bool, default: true
93
102
  option :use_legacy_sql_parser, type: :bool, default: false
94
103
  option :verify_server_cert, type: :bool, default: true
@@ -131,6 +140,7 @@ module ElasticAPM
131
140
  %w[
132
141
  action_dispatch
133
142
  delayed_job
143
+ dynamo_db
134
144
  elasticsearch
135
145
  faraday
136
146
  http
@@ -187,6 +197,14 @@ module ElasticAPM
187
197
  metrics_interval > 0
188
198
  end
189
199
 
200
+ # DEPRECATED: Remove this in next major version
201
+ def sanitize_field_names=(value)
202
+ list = WildcardPatternList.new.call(value)
203
+ defaults = WildcardPatternList.new.call(SANITIZE_FIELD_NAMES_DEFAULT)
204
+ get(:sanitize_field_names).value =
205
+ defaults.concat(list).uniq(&:pattern) # use regex pattern for comparisons
206
+ end
207
+
190
208
  def span_frames_min_duration?
191
209
  span_frames_min_duration != 0
192
210
  end
@@ -233,6 +251,15 @@ module ElasticAPM
233
251
  self.default_labels = value
234
252
  end
235
253
 
254
+ def ignore_url_patterns=(value)
255
+ unless value == self.class.schema[:ignore_url_patterns][:default]
256
+ warn '[DEPRECATED] The option ignore_url_patterns is being removed. ' \
257
+ 'Consider using transaction_ignore_urls instead.'
258
+ end
259
+
260
+ set(:ignore_url_patterns, value)
261
+ end
262
+
236
263
  def custom_key_filters=(value)
237
264
  unless value == self.class.schema[:custom_key_filters][:default]
238
265
  warn '[DEPRECATED] The option custom_key_filters is being removed. ' \
@@ -317,7 +344,7 @@ module ElasticAPM
317
344
  self.logger ||= ::Rails.logger
318
345
 
319
346
  self.__root_path = ::Rails.root.to_s
320
- self.__view_paths = app.config.paths['app/views'].existent
347
+ self.__view_paths = app.config.paths['app/views'].existent + [::Rails.root.to_s]
321
348
  end
322
349
 
323
350
  def rails_app_name(app)
@@ -38,7 +38,8 @@ module ElasticAPM
38
38
  set(value || default)
39
39
  end
40
40
 
41
- attr_reader :key, :value, :default, :type
41
+ attr_reader :key, :default, :type, :converter
42
+ attr_accessor :value
42
43
 
43
44
  def set(value)
44
45
  @value = normalize(value)
@@ -0,0 +1,31 @@
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 'elastic_apm/util/precision_validator'
21
+
22
+ module ElasticAPM
23
+ class Config
24
+ # @api private
25
+ class RoundFloat
26
+ def call(value)
27
+ Util::PrecisionValidator.validate(value, precision: 4, minimum: 0.0001)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -27,6 +27,8 @@ module ElasticAPM
27
27
  @pattern = convert(str)
28
28
  end
29
29
 
30
+ attr_reader :pattern
31
+
30
32
  def match?(other)
31
33
  !!@pattern.match(other)
32
34
  end
@@ -36,12 +38,22 @@ module ElasticAPM
36
38
  private
37
39
 
38
40
  def convert(str)
41
+ case_sensitive = false
42
+
43
+ if str.start_with?('(?-i)')
44
+ str = str.gsub(/^\(\?-\i\)/, '')
45
+ case_sensitive = true
46
+ end
47
+
39
48
  parts =
40
49
  str.chars.each_with_object([]) do |char, arr|
41
50
  arr << (char == '*' ? '.*' : Regexp.escape(char))
42
51
  end
43
52
 
44
- Regexp.new('\A' + parts.join + '\Z', Regexp::IGNORECASE)
53
+ Regexp.new(
54
+ '\A' + parts.join + '\Z',
55
+ case_sensitive ? nil : Regexp::IGNORECASE
56
+ )
45
57
  end
46
58
  end
47
59
 
@@ -76,7 +76,7 @@ module ElasticAPM
76
76
  else
77
77
  body = req.body.read
78
78
  req.body.rewind
79
- body.byteslice(0, MAX_BODY_LENGTH).force_encoding('utf-8')
79
+ body.byteslice(0, MAX_BODY_LENGTH).force_encoding('utf-8').scrub
80
80
  end
81
81
  end
82
82
 
@@ -119,7 +119,13 @@ module ElasticAPM
119
119
  "Already inside #{transaction.inspect}"
120
120
  end
121
121
 
122
- sampled = trace_context ? trace_context.recorded? : random_sample?(config)
122
+ if trace_context
123
+ sampled = trace_context.recorded?
124
+ sample_rate = trace_context.tracestate.sample_rate
125
+ else
126
+ sampled = random_sample?(config)
127
+ sample_rate = config.transaction_sample_rate
128
+ end
123
129
 
124
130
  transaction =
125
131
  Transaction.new(
@@ -128,6 +134,7 @@ module ElasticAPM
128
134
  context: context,
129
135
  trace_context: trace_context,
130
136
  sampled: sampled,
137
+ sample_rate: sample_rate,
131
138
  config: config
132
139
  )
133
140
 
@@ -259,7 +266,7 @@ module ElasticAPM
259
266
  end
260
267
 
261
268
  def update_transaction_metrics(transaction)
262
- return unless transaction.collect_metrics
269
+ return unless transaction.collect_metrics?
263
270
 
264
271
  tags = {
265
272
  'transaction.name': transaction.name,
@@ -298,7 +305,7 @@ module ElasticAPM
298
305
  end
299
306
 
300
307
  def update_span_metrics(span)
301
- return unless span.transaction.breakdown_metrics
308
+ return unless span.transaction.collect_metrics?
302
309
 
303
310
  tags = {
304
311
  'span.type': span.type,
@@ -25,12 +25,14 @@ module ElasticAPM
25
25
  @process = ProcessInfo.new(config)
26
26
  @system = SystemInfo.new(config)
27
27
  @labels = config.global_labels
28
+ @cloud = CloudInfo.new(config).fetch!
28
29
  end
29
30
 
30
- attr_reader :service, :process, :system, :labels
31
+ attr_reader :service, :process, :system, :cloud, :labels
31
32
  end
32
33
  end
33
34
 
34
35
  require 'elastic_apm/metadata/service_info'
35
36
  require 'elastic_apm/metadata/system_info'
36
37
  require 'elastic_apm/metadata/process_info'
38
+ require 'elastic_apm/metadata/cloud_info'
@@ -0,0 +1,128 @@
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 "http"
21
+
22
+ module ElasticAPM
23
+ class Metadata
24
+ # @api private
25
+ class CloudInfo
26
+ include Logging
27
+
28
+ AWS_URI = "http://169.254.169.254/latest/dynamic/instance-identity/document"
29
+ GCP_URI = "http://metadata.google.internal/computeMetadata/v1/?recursive=true"
30
+ AZURE_URI = "http://169.254.169.254/metadata/instance/compute?api-version=2019-08-15"
31
+
32
+ def initialize(config)
33
+ @config = config
34
+ @client = HTTP.timeout(0.1)
35
+ end
36
+
37
+ attr_reader :config
38
+
39
+ attr_accessor(
40
+ :account_id,
41
+ :account_name,
42
+ :instance_id,
43
+ :instance_name,
44
+ :machine_type,
45
+ :project_id,
46
+ :project_name,
47
+ :availability_zone,
48
+ :provider,
49
+ :region
50
+ )
51
+
52
+ def fetch!
53
+ case config.cloud_provider
54
+ when "aws"
55
+ fetch_aws
56
+ when "gcp"
57
+ fetch_gcp
58
+ when "azure"
59
+ fetch_azure
60
+ when "auto"
61
+ fetch_aws || fetch_gcp || fetch_azure
62
+ when "none"
63
+ nil
64
+ else
65
+ error("Unknown setting for cloud_provider '#{config.cloud_provider}'")
66
+ end
67
+
68
+ self
69
+ end
70
+
71
+ private
72
+
73
+ def fetch_aws
74
+ resp = @client.get(AWS_URI)
75
+
76
+ return unless resp.status === 200
77
+ return unless (metadata = JSON.parse(resp.body))
78
+
79
+ self.provider = "aws"
80
+ self.account_id = metadata["accountId"]
81
+ self.instance_id = metadata["instanceId"]
82
+ self.availability_zone = metadata["availabilityZone"]
83
+ self.machine_type = metadata["instanceType"]
84
+ self.region = metadata["region"]
85
+ rescue HTTP::TimeoutError, HTTP::ConnectionError
86
+ nil
87
+ end
88
+
89
+ def fetch_gcp
90
+ resp = @client.headers("Metadata-Flavor" => "Google").get(GCP_URI)
91
+
92
+ return unless resp.status === 200
93
+ return unless (metadata = JSON.parse(resp.body))
94
+
95
+ zone = metadata["instance"]["zone"]&.split("/")&.at(-1)
96
+
97
+ self.provider = "gcp"
98
+ self.instance_id = metadata["instance"]["id"]
99
+ self.instance_name = metadata["instance"]["name"]
100
+ self.project_id = metadata["project"]["numericProjectId"]
101
+ self.project_name = metadata["project"]["projectId"]
102
+ self.availability_zone = zone
103
+ self.region = zone.split("-")[0..-2].join("-")
104
+ self.machine_type = metadata["instance"]["machineType"]
105
+ rescue HTTP::TimeoutError, HTTP::ConnectionError
106
+ nil
107
+ end
108
+
109
+ def fetch_azure
110
+ resp = @client.headers("Metadata" => "true").get(AZURE_URI)
111
+
112
+ return unless resp.status === 200
113
+ return unless (metadata = JSON.parse(resp.body))
114
+
115
+ self.provider = 'azure'
116
+ self.account_id = metadata["subscriptionId"]
117
+ self.instance_id = metadata["vmId"]
118
+ self.instance_name = metadata["name"]
119
+ self.project_name = metadata["resourceGroupName"]
120
+ self.availability_zone = metadata["zone"]
121
+ self.machine_type = metadata["vmSize"]
122
+ self.region = metadata["location"]
123
+ rescue HTTP::TimeoutError, HTTP::ConnectionError
124
+ nil
125
+ end
126
+ end
127
+ end
128
+ end