instana 1.195.1 → 1.197.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +16 -2
  3. data/.rubocop.yml +6 -2
  4. data/Appraisals +13 -1
  5. data/Rakefile +1 -1
  6. data/docker-compose.yml +20 -0
  7. data/gemfiles/aws_30.gemfile +3 -0
  8. data/gemfiles/excon_021.gemfile +18 -0
  9. data/gemfiles/excon_079.gemfile +18 -0
  10. data/gemfiles/shoryuken_50.gemfile +19 -0
  11. data/instana.gemspec +3 -7
  12. data/lib/instana.rb +3 -0
  13. data/lib/instana/activator.rb +2 -0
  14. data/lib/instana/activators/aws_sdk_s3.rb +20 -0
  15. data/lib/instana/activators/aws_sdk_sns.rb +20 -0
  16. data/lib/instana/activators/aws_sdk_sqs.rb +20 -0
  17. data/lib/instana/activators/excon.rb +1 -1
  18. data/lib/instana/activators/shoryuken.rb +24 -0
  19. data/lib/instana/backend/agent.rb +60 -0
  20. data/lib/instana/backend/gc_snapshot.rb +41 -0
  21. data/lib/instana/backend/host_agent.rb +74 -0
  22. data/lib/instana/backend/host_agent_activation_observer.rb +97 -0
  23. data/lib/instana/backend/host_agent_lookup.rb +57 -0
  24. data/lib/instana/backend/host_agent_reporting_observer.rb +106 -0
  25. data/lib/instana/backend/process_info.rb +64 -0
  26. data/lib/instana/backend/request_client.rb +73 -0
  27. data/lib/instana/backend/serverless_agent.rb +118 -0
  28. data/lib/instana/base.rb +8 -27
  29. data/lib/instana/config.rb +8 -22
  30. data/lib/instana/instrumentation/aws_sdk_dynamodb.rb +21 -2
  31. data/lib/instana/instrumentation/aws_sdk_s3.rb +55 -0
  32. data/lib/instana/instrumentation/aws_sdk_sns.rb +29 -0
  33. data/lib/instana/instrumentation/aws_sdk_sqs.rb +98 -0
  34. data/lib/instana/instrumentation/excon.rb +19 -9
  35. data/lib/instana/instrumentation/instrumented_request.rb +68 -8
  36. data/lib/instana/instrumentation/net-http.rb +11 -7
  37. data/lib/instana/instrumentation/rack.rb +12 -7
  38. data/lib/instana/instrumentation/shoryuken.rb +44 -0
  39. data/lib/instana/logger_delegator.rb +31 -0
  40. data/lib/instana/{opentracing → open_tracing}/carrier.rb +0 -0
  41. data/lib/instana/open_tracing/instana_tracer.rb +99 -0
  42. data/lib/instana/secrets.rb +8 -4
  43. data/lib/instana/setup.rb +20 -11
  44. data/lib/instana/snapshot/deltable.rb +25 -0
  45. data/lib/instana/snapshot/docker_container.rb +151 -0
  46. data/lib/instana/snapshot/fargate_container.rb +88 -0
  47. data/lib/instana/snapshot/fargate_process.rb +67 -0
  48. data/lib/instana/snapshot/fargate_task.rb +72 -0
  49. data/lib/instana/snapshot/ruby_process.rb +48 -0
  50. data/lib/instana/tracer.rb +29 -147
  51. data/lib/instana/tracing/processor.rb +14 -22
  52. data/lib/instana/tracing/span.rb +34 -37
  53. data/lib/instana/tracing/span_context.rb +16 -10
  54. data/lib/instana/util.rb +8 -69
  55. data/lib/instana/version.rb +1 -1
  56. data/lib/opentracing.rb +26 -3
  57. data/test/backend/agent_test.rb +54 -0
  58. data/test/backend/gc_snapshot_test.rb +11 -0
  59. data/test/backend/host_agent_activation_observer_test.rb +72 -0
  60. data/test/backend/host_agent_lookup_test.rb +78 -0
  61. data/test/backend/host_agent_reporting_observer_test.rb +192 -0
  62. data/test/backend/host_agent_test.rb +47 -0
  63. data/test/backend/process_info_test.rb +63 -0
  64. data/test/backend/request_client_test.rb +39 -0
  65. data/test/backend/serverless_agent_test.rb +73 -0
  66. data/test/config_test.rb +10 -0
  67. data/test/instana_test.rb +11 -4
  68. data/test/instrumentation/aws_test.rb +130 -2
  69. data/test/instrumentation/excon_test.rb +16 -1
  70. data/test/instrumentation/net_http_test.rb +18 -0
  71. data/test/instrumentation/rack_instrumented_request_test.rb +9 -4
  72. data/test/instrumentation/rack_test.rb +2 -14
  73. data/test/instrumentation/shoryuken_test.rb +47 -0
  74. data/test/secrets_test.rb +41 -22
  75. data/test/snapshot/deltable_test.rb +17 -0
  76. data/test/snapshot/docker_container_test.rb +82 -0
  77. data/test/snapshot/fargate_container_test.rb +82 -0
  78. data/test/snapshot/fargate_process_test.rb +35 -0
  79. data/test/snapshot/fargate_task_test.rb +49 -0
  80. data/test/snapshot/ruby_process_test.rb +14 -0
  81. data/test/support/mock_timer.rb +20 -0
  82. data/test/test_helper.rb +16 -4
  83. data/test/tracing/custom_test.rb +1 -3
  84. data/test/tracing/id_management_test.rb +4 -0
  85. data/test/tracing/opentracing_test.rb +15 -2
  86. data/test/tracing/processor_test.rb +58 -0
  87. data/test/tracing/span_context_test.rb +21 -0
  88. data/test/tracing/span_test.rb +136 -0
  89. data/test/tracing/tracer_async_test.rb +29 -0
  90. data/test/tracing/tracer_test.rb +82 -16
  91. data/test/util_test.rb +10 -0
  92. metadata +86 -46
  93. data/Dockerfile +0 -16
  94. data/lib/instana/agent.rb +0 -508
  95. data/lib/instana/agent/helpers.rb +0 -87
  96. data/lib/instana/agent/hooks.rb +0 -44
  97. data/lib/instana/agent/tasks.rb +0 -51
  98. data/lib/instana/collector.rb +0 -119
  99. data/lib/instana/collectors/gc.rb +0 -60
  100. data/lib/instana/collectors/memory.rb +0 -37
  101. data/lib/instana/collectors/thread.rb +0 -33
  102. data/lib/instana/eum/eum-test.js.erb +0 -17
  103. data/lib/instana/eum/eum.js.erb +0 -17
  104. data/lib/instana/helpers.rb +0 -47
  105. data/lib/instana/opentracing/tracer.rb +0 -21
  106. data/lib/instana/thread_local.rb +0 -18
  107. data/lib/oj_check.rb +0 -19
  108. data/test/agent/agent_test.rb +0 -151
@@ -6,11 +6,15 @@ require 'cgi'
6
6
 
7
7
  module Instana
8
8
  class Secrets
9
+ def initialize(logger: ::Instana.logger)
10
+ @logger = logger
11
+ end
12
+
9
13
  def remove_from_query(str, secret_values = Instana.agent.secret_values)
10
14
  return str unless secret_values
11
15
 
12
16
  url = URI(str)
13
- params = CGI.parse(url.query || '')
17
+ params = url.scheme ? CGI.parse(url.query || '') : CGI.parse(url.to_s)
14
18
 
15
19
  redacted = params.map do |k, v|
16
20
  needs_redaction = secret_values['list']
@@ -19,7 +23,7 @@ module Instana
19
23
  end
20
24
 
21
25
  url.query = URI.encode_www_form(redacted)
22
- CGI.unescape(url.to_s)
26
+ url.scheme ? CGI.unescape(url.to_s) : CGI.unescape(url.query)
23
27
  end
24
28
 
25
29
  private
@@ -37,8 +41,8 @@ module Instana
37
41
  when 'regex'
38
42
  ->(expected, actual) { !Regexp.new(expected).match(actual).nil? }
39
43
  else
40
- ::Instana.logger.warn("Matcher #{name} is not supported.")
41
- lambda { false }
44
+ @logger.warn("Matcher #{name} is not supported.")
45
+ ->(_e, _a) { false }
42
46
  end
43
47
  end
44
48
  end
data/lib/instana/setup.rb CHANGED
@@ -1,30 +1,39 @@
1
1
  # (c) Copyright IBM Corp. 2021
2
2
  # (c) Copyright Instana Inc. 2016
3
3
 
4
- require 'oj_check'
4
+ require 'instana/logger_delegator'
5
5
 
6
6
  require "instana/base"
7
7
  require "instana/config"
8
- require "instana/agent"
9
- require "instana/collector"
10
8
  require "instana/secrets"
11
9
  require "instana/tracer"
12
10
  require "instana/tracing/processor"
13
11
 
14
12
  require 'instana/activator'
15
13
 
14
+ require 'instana/backend/request_client'
15
+ require 'instana/backend/gc_snapshot'
16
+ require 'instana/backend/process_info'
17
+
18
+ require 'instana/snapshot/deltable'
19
+ require 'instana/snapshot/ruby_process'
20
+ require 'instana/snapshot/fargate_process'
21
+ require 'instana/snapshot/fargate_task'
22
+ require 'instana/snapshot/fargate_container'
23
+ require 'instana/snapshot/docker_container'
24
+
25
+ require 'instana/backend/host_agent_lookup'
26
+ require 'instana/backend/host_agent_activation_observer'
27
+ require 'instana/backend/host_agent_reporting_observer'
28
+
29
+ require 'instana/backend/host_agent'
30
+ require 'instana/backend/serverless_agent'
31
+ require 'instana/backend/agent'
32
+
16
33
  ::Instana.setup
17
34
  ::Instana.agent.setup
18
35
  ::Instana::Activator.start
19
36
 
20
- # Register the metric collectors
21
- unless RUBY_PLATFORM == 'java'.freeze
22
- require 'instana/collectors/gc'
23
- end
24
-
25
- require 'instana/collectors/memory'
26
- require 'instana/collectors/thread'
27
-
28
37
  # Require supported OpenTracing interfaces
29
38
  require "opentracing"
30
39
 
@@ -0,0 +1,25 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Snapshot
6
+ # @since 1.197.0
7
+ module Deltable
8
+ def delta(key, *rest, compute:, obj:, path: [key, *rest])
9
+ val = obj[key]
10
+ return val if val == nil
11
+
12
+ if rest.empty?
13
+ @__delta ||= Hash.new(0)
14
+ cache_key = path.join('.')
15
+ old = @__delta[cache_key]
16
+ @__delta[cache_key] = val
17
+
18
+ return compute.call(old, val)
19
+ end
20
+
21
+ delta(*rest, compute: compute, obj: val, path: path)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,151 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Snapshot
6
+ # Describes a Docker container visible to the current process
7
+ # @since 1.197.0
8
+ class DockerContainer
9
+ include Deltable
10
+ ID = 'com.instana.plugin.docker'.freeze
11
+
12
+ def initialize(container, metadata_uri: ENV['ECS_CONTAINER_METADATA_URI'])
13
+ @container = container
14
+ @metadata_uri = URI(metadata_uri)
15
+ @client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
16
+ end
17
+
18
+ def entity_id
19
+ "#{@container['Labels']['com.amazonaws.ecs.task-arn']}::#{@container['Name']}"
20
+ end
21
+
22
+ def data
23
+ metrics = lookup('/task/stats').fetch(@container['DockerId'], {})
24
+
25
+ container_metrics(metrics)
26
+ .merge(container_metadata)
27
+ end
28
+
29
+ def snapshot
30
+ {
31
+ name: ID,
32
+ entityId: entity_id,
33
+ data: data
34
+ }
35
+ end
36
+
37
+ private
38
+
39
+ def container_metadata
40
+ {
41
+ Id: @container['DockerId'],
42
+ Created: @container['CreatedAt'],
43
+ Started: @container['StartedAt'],
44
+ Image: @container['Image'],
45
+ Labels: @container['Labels'],
46
+ Ports: @container['Ports'],
47
+ NetworkMode: @container['Networks'].first['NetworkMode']
48
+ }
49
+ end
50
+
51
+ def container_metrics(metrics)
52
+ return {} if metrics.empty?
53
+
54
+ {
55
+ memory: memory_stats(metrics),
56
+ blkio: blkio_stats(metrics),
57
+ cpu: cpu_stats(metrics),
58
+ network: network_stats(metrics)
59
+ }.compact
60
+ end
61
+
62
+ def memory_stats(metrics)
63
+ identity = ->(_old, new) { new }
64
+
65
+ {
66
+ active_anon: delta('memory_stats', 'stats', 'active_anon', compute: identity, obj: metrics),
67
+ active_file: delta('memory_stats', 'stats', 'active_file', compute: identity, obj: metrics),
68
+ inactive_anon: delta('memory_stats', 'stats', 'inactive_anon', compute: identity, obj: metrics),
69
+ inactive_file: delta('memory_stats', 'stats', 'inactive_file', compute: identity, obj: metrics),
70
+ total_cache: delta('memory_stats', 'stats', 'total_cache', compute: identity, obj: metrics),
71
+ total_rss: delta('memory_stats', 'stats', 'total_rss', compute: identity, obj: metrics),
72
+ usage: delta('memory_stats', 'usage', compute: identity, obj: metrics),
73
+ max_usage: delta('memory_stats', 'max_usage', compute: identity, obj: metrics),
74
+ limit: delta('memory_stats', 'limit', compute: identity, obj: metrics)
75
+ }
76
+ end
77
+
78
+ def blkio_stats(metrics)
79
+ delta = ->(old, new) { new - old }
80
+ bytes = {
81
+ 'block_bytes' => metrics['blkio_stats']['io_service_bytes_recursive'].map { |r| [r['op'], r['value']] }.to_h
82
+ }
83
+
84
+ {
85
+ blk_read: delta('block_bytes', 'Read', compute: delta, obj: bytes),
86
+ blk_write: delta('block_bytes', 'Write', compute: delta, obj: bytes)
87
+ }
88
+ end
89
+
90
+ def cpu_stats(metrics)
91
+ delta = ->(old, new) { new - old }
92
+ identity = ->(_old, new) { new }
93
+
94
+ cpu_system_delta = delta('cpu_stats', 'system_cpu_usage', compute: delta, obj: metrics).to_f
95
+ online_cpus = delta('cpu_stats', 'online_cpus', compute: identity, obj: metrics) || 1
96
+
97
+ {
98
+ total_usage: (delta('cpu_stats', 'cpu_usage', 'total_usage', compute: delta, obj: metrics) / cpu_system_delta) * online_cpus,
99
+ user_usage: (delta('cpu_stats', 'cpu_usage', 'usage_in_usermode', compute: delta, obj: metrics) / cpu_system_delta) * online_cpus,
100
+ system_usage: (delta('cpu_stats', 'cpu_usage', 'usage_in_kernelmode', compute: delta, obj: metrics) / cpu_system_delta) * online_cpus,
101
+ throttling_count: delta('cpu_stats', 'throttling_data', 'periods', compute: delta, obj: metrics),
102
+ throttling_time: delta('cpu_stats', 'throttling_data', 'throttled_time', compute: delta, obj: metrics)
103
+ }
104
+ end
105
+
106
+ def network_stats(metrics)
107
+ delta = ->(old, new) { new - old }
108
+ return nil unless metrics['networks']
109
+
110
+ interfaces = metrics['networks'].keys
111
+ payload = {
112
+ rx: {
113
+ bytes: 0,
114
+ dropped: 0,
115
+ errors: 0,
116
+ packet: 0
117
+ },
118
+ tx: {
119
+ bytes: 0,
120
+ dropped: 0,
121
+ errors: 0,
122
+ packet: 0
123
+ }
124
+ }
125
+
126
+ interfaces.each do |interface|
127
+ payload[:rx][:bytes] += delta('networks', interface, 'rx_bytes', compute: delta, obj: metrics)
128
+ payload[:rx][:dropped] += delta('networks', interface, 'rx_dropped', compute: delta, obj: metrics)
129
+ payload[:rx][:errors] += delta('networks', interface, 'rx_errors', compute: delta, obj: metrics)
130
+ payload[:rx][:packet] += delta('networks', interface, 'rx_packets', compute: delta, obj: metrics)
131
+
132
+ payload[:tx][:bytes] += delta('networks', interface, 'tx_bytes', compute: delta, obj: metrics)
133
+ payload[:tx][:dropped] += delta('networks', interface, 'tx_packets', compute: delta, obj: metrics)
134
+ payload[:tx][:errors] += delta('networks', interface, 'tx_errors', compute: delta, obj: metrics)
135
+ payload[:tx][:packet] += delta('networks', interface, 'tx_dropped', compute: delta, obj: metrics)
136
+ end
137
+
138
+ payload
139
+ end
140
+
141
+ def lookup(resource)
142
+ path = @metadata_uri.path + resource
143
+ response = @client.send_request('GET', path)
144
+
145
+ raise "Unable to get `#{path}`. Got `#{response.code}`." unless response.ok?
146
+
147
+ response.json
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,88 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Snapshot
6
+ # Describes a Fargate container visible to the current process
7
+ # @since 1.197.0
8
+ class FargateContainer
9
+ ID = 'com.instana.plugin.aws.ecs.container'.freeze
10
+
11
+ def initialize(container, metadata_uri: ENV['ECS_CONTAINER_METADATA_URI'])
12
+ @container = container
13
+ @metadata_uri = URI(metadata_uri)
14
+ @client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
15
+ end
16
+
17
+ def entity_id
18
+ "#{@container['Labels']['com.amazonaws.ecs.task-arn']}::#{@container['Name']}"
19
+ end
20
+
21
+ def data
22
+ payload = {
23
+ dockerId: @container['DockerId'],
24
+ dockerName: @container['DockerName'],
25
+ containerName: @container['Name'],
26
+ image: @container['Image'],
27
+ imageId: @container['ImageID'],
28
+ taskArn: @container['Labels']['com.amazonaws.ecs.task-arn'],
29
+ taskDefinition: @container['Labels']['com.amazonaws.ecs.task-definition-data.family'],
30
+ taskDefinitionVersion: @container['Labels']['com.amazonaws.ecs.task-definition-data.version'],
31
+ clusterArn: @container['Labels']['com.amazonaws.ecs.cluster'],
32
+ desiredStatus: @container['DesiredStatus'],
33
+ knownStatus: @container['KnownStatus'],
34
+ ports: @container['Ports'],
35
+ limits: {
36
+ cpu: @container['Limits']['CPU'],
37
+ memory: @container['Limits']['Memory']
38
+ },
39
+ createdAt: @container['CreatedAt'],
40
+ startedAt: @container['StartedAt']
41
+ }
42
+
43
+ if current_container?
44
+ payload[:instrumented] = true
45
+ payload[:runtime] = 'ruby'
46
+ end
47
+
48
+ payload
49
+ end
50
+
51
+ def snapshot
52
+ {
53
+ name: ID,
54
+ entityId: entity_id,
55
+ data: data
56
+ }
57
+ end
58
+
59
+ def source
60
+ return unless current_container?
61
+
62
+ {
63
+ hl: true,
64
+ cp: 'aws',
65
+ e: entity_id
66
+ }
67
+ end
68
+
69
+ private
70
+
71
+ def current_container?
72
+ return @current_container if @current_container
73
+
74
+ current_conatiner_response = current_conatiner
75
+ @current_container = @container['DockerName'] == current_conatiner_response['DockerName']
76
+ end
77
+
78
+ def current_conatiner
79
+ path = @metadata_uri.path
80
+ response = @client.send_request('GET', path)
81
+
82
+ raise "Unable to get `#{path}`. Got `#{response.code}`." unless response.ok?
83
+
84
+ response.json
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,67 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Snapshot
6
+ # Describes the current process in terms of its existence inside of a Fargate container
7
+ # @since 1.197.0
8
+ class FargateProcess
9
+ ID = 'com.instana.plugin.process'.freeze
10
+
11
+ def initialize(metadata_uri: ENV['ECS_CONTAINER_METADATA_URI'])
12
+ @metadata_uri = URI(metadata_uri)
13
+ @client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
14
+ @start_time = Time.now
15
+ end
16
+
17
+ def entity_id
18
+ Process.pid.to_s
19
+ end
20
+
21
+ def data
22
+ proc_table = Sys::ProcTable.ps(pid: Process.pid)
23
+ process = Backend::ProcessInfo.new(proc_table)
24
+
25
+ {
26
+ pid: process.pid.to_i,
27
+ env: ENV.to_h,
28
+ exec: process.name,
29
+ args: process.arguments,
30
+ user: process.uid,
31
+ group: process.gid,
32
+ start: @start_time.to_i * 1000,
33
+ containerType: 'docker',
34
+ container: container_id,
35
+ "com.instana.plugin.host.name": task_id
36
+ }
37
+ end
38
+
39
+ def snapshot
40
+ {
41
+ name: ID,
42
+ entityId: entity_id,
43
+ data: data
44
+ }
45
+ end
46
+
47
+ private
48
+
49
+ def lookup(resource = nil)
50
+ path = resource ? @metadata_uri.path + resource : @metadata_uri.path
51
+ response = @client.send_request('GET', path)
52
+
53
+ raise "Unable to get `#{path}`. Got `#{response.code}`." unless response.ok?
54
+
55
+ response.json
56
+ end
57
+
58
+ def container_id
59
+ @container_id ||= lookup['DockerId']
60
+ end
61
+
62
+ def task_id
63
+ @task_id ||= lookup('/task')['TaskARN']
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,72 @@
1
+ # (c) Copyright IBM Corp. 2021
2
+ # (c) Copyright Instana Inc. 2021
3
+
4
+ module Instana
5
+ module Snapshot
6
+ # Describes the current process in terms of its existence inside of a Fargate task
7
+ # @since 1.197.0
8
+ class FargateTask
9
+ ID = 'com.instana.plugin.aws.ecs.task'.freeze
10
+
11
+ def initialize(metadata_uri: ENV['ECS_CONTAINER_METADATA_URI'])
12
+ @metadata_uri = URI(metadata_uri)
13
+ @client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
14
+ end
15
+
16
+ def entity_id
17
+ task_metadata['TaskARN']
18
+ end
19
+ alias host_name entity_id
20
+
21
+ def data
22
+ {
23
+ taskArn: task_metadata['TaskARN'],
24
+ clusterArn: task_metadata['Cluster'],
25
+ taskDefinition: task_metadata['Family'],
26
+ taskDefinitionVersion: task_metadata['Revision'],
27
+ availabilityZone: task_metadata['AvailabilityZone'],
28
+ desiredStatus: task_metadata['DesiredStatus'],
29
+ knownStatus: task_metadata['KnownStatus'],
30
+ pullStartedAt: task_metadata['PullStartedAt'],
31
+ pullStoppedAt: task_metadata['PullStoppedAt'],
32
+ instanaZone: instana_zone,
33
+ tags: instana_tags
34
+ }.compact
35
+ end
36
+
37
+ def snapshot
38
+ {
39
+ name: ID,
40
+ entityId: entity_id,
41
+ data: data
42
+ }
43
+ end
44
+
45
+ private
46
+
47
+ def task_metadata
48
+ lookup('/task')
49
+ end
50
+
51
+ def instana_zone
52
+ ENV['INSTANA_ZONE']
53
+ end
54
+
55
+ def instana_tags
56
+ ENV.fetch('INSTANA_TAGS', '')
57
+ .split(/,/)
58
+ .map { |t| t.include?('=') ? t.split('=', 2) : [t, nil] }
59
+ .to_h
60
+ end
61
+
62
+ def lookup(resource)
63
+ path = @metadata_uri.path + resource
64
+ response = @client.send_request('GET', path)
65
+
66
+ raise "Unable to get `#{path}`. Got `#{response.code}`." unless response.ok?
67
+
68
+ response.json
69
+ end
70
+ end
71
+ end
72
+ end