elastic-apm 2.9.1 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ci/.jenkins_codecov.yml +5 -0
- data/.ci/.jenkins_exclude.yml +9 -19
- data/.ci/.jenkins_framework.yml +1 -4
- data/.ci/.jenkins_master_framework.yml +3 -0
- data/.ci/Jenkinsfile +43 -118
- data/.ci/downstreamTests.groovy +59 -30
- data/.ci/jobs/apm-agent-ruby-downstream.yml +31 -0
- data/.ci/jobs/apm-agent-ruby-mbp.yml +34 -0
- data/.ci/jobs/defaults.yml +1 -36
- data/.pre-commit-config.yaml +22 -0
- data/.rspec +0 -1
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +12 -0
- data/docs/api.asciidoc +2 -2
- data/docs/configuration.asciidoc +37 -1
- data/docs/metrics.asciidoc +77 -6
- data/lib/elastic_apm.rb +2 -2
- data/lib/elastic_apm/agent.rb +11 -2
- data/lib/elastic_apm/central_config.rb +141 -0
- data/lib/elastic_apm/central_config/cache_control.rb +34 -0
- data/lib/elastic_apm/config.rb +152 -338
- data/lib/elastic_apm/config/bytes.rb +25 -0
- data/lib/elastic_apm/config/duration.rb +6 -8
- data/lib/elastic_apm/config/options.rb +134 -0
- data/lib/elastic_apm/config/regexp_list.rb +13 -0
- data/lib/elastic_apm/metadata.rb +2 -1
- data/lib/elastic_apm/metrics.rb +2 -1
- data/lib/elastic_apm/metrics/vm.rb +57 -0
- data/lib/elastic_apm/normalizers/action_view.rb +1 -1
- data/lib/elastic_apm/railtie.rb +10 -5
- data/lib/elastic_apm/spies/mongo.rb +13 -2
- data/lib/elastic_apm/stacktrace_builder.rb +2 -2
- data/lib/elastic_apm/transport/connection.rb +2 -0
- data/lib/elastic_apm/transport/serializers/metadata_serializer.rb +6 -1
- data/lib/elastic_apm/version.rb +1 -1
- metadata +11 -3
- data/lib/elastic_apm/config/size.rb +0 -28
@@ -4,3 +4,37 @@
|
|
4
4
|
display-name: APM Agent Ruby
|
5
5
|
description: APM Agent Ruby
|
6
6
|
script-path: .ci/Jenkinsfile
|
7
|
+
scm:
|
8
|
+
- github:
|
9
|
+
branch-discovery: no-pr
|
10
|
+
discover-pr-forks-strategy: merge-current
|
11
|
+
discover-pr-forks-trust: permission
|
12
|
+
discover-pr-origin: merge-current
|
13
|
+
discover-tags: true
|
14
|
+
repo: apm-agent-ruby
|
15
|
+
repo-owner: elastic
|
16
|
+
credentials-id: 2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken
|
17
|
+
ssh-checkout:
|
18
|
+
credentials: f6c7695a-671e-4f4f-a331-acdce44ff9ba
|
19
|
+
build-strategies:
|
20
|
+
- tags:
|
21
|
+
ignore-tags-older-than: -1
|
22
|
+
ignore-tags-newer-than: -1
|
23
|
+
- regular-branches: true
|
24
|
+
- change-request:
|
25
|
+
ignore-target-only-changes: false
|
26
|
+
clean:
|
27
|
+
after: true
|
28
|
+
before: true
|
29
|
+
prune: true
|
30
|
+
shallow-clone: true
|
31
|
+
depth: 3
|
32
|
+
do-not-fetch-tags: true
|
33
|
+
submodule:
|
34
|
+
disable: false
|
35
|
+
recursive: true
|
36
|
+
parent-credentials: true
|
37
|
+
timeout: 100
|
38
|
+
timeout: '15'
|
39
|
+
use-author: true
|
40
|
+
wipe-workspace: 'True'
|
data/.ci/jobs/defaults.yml
CHANGED
@@ -12,46 +12,11 @@
|
|
12
12
|
project-type: multibranch
|
13
13
|
logrotate:
|
14
14
|
daysToKeep: 30
|
15
|
-
numToKeep:
|
15
|
+
numToKeep: 300
|
16
16
|
number-to-keep: '100'
|
17
17
|
days-to-keep: '30'
|
18
18
|
concurrent: true
|
19
19
|
node: linux
|
20
|
-
script-path: .ci/Jenkinsfile
|
21
|
-
scm:
|
22
|
-
- github:
|
23
|
-
branch-discovery: all
|
24
|
-
discover-pr-forks-strategy: merge-current
|
25
|
-
discover-pr-forks-trust: permission
|
26
|
-
discover-pr-origin: merge-current
|
27
|
-
discover-tags: true
|
28
|
-
repo: apm-agent-ruby
|
29
|
-
repo-owner: elastic
|
30
|
-
credentials-id: 2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken
|
31
|
-
ssh-checkout:
|
32
|
-
credentials: f6c7695a-671e-4f4f-a331-acdce44ff9ba
|
33
|
-
build-strategies:
|
34
|
-
- tags:
|
35
|
-
ignore-tags-older-than: -1
|
36
|
-
ignore-tags-newer-than: -1
|
37
|
-
- regular-branches: true
|
38
|
-
- change-request:
|
39
|
-
ignore-target-only-changes: false
|
40
|
-
clean:
|
41
|
-
after: true
|
42
|
-
before: true
|
43
|
-
prune: true
|
44
|
-
shallow-clone: true
|
45
|
-
depth: 3
|
46
|
-
do-not-fetch-tags: true
|
47
|
-
submodule:
|
48
|
-
disable: false
|
49
|
-
recursive: true
|
50
|
-
parent-credentials: true
|
51
|
-
timeout: 100
|
52
|
-
timeout: '15'
|
53
|
-
use-author: true
|
54
|
-
wipe-workspace: 'True'
|
55
20
|
periodic-folder-trigger: 1d
|
56
21
|
prune-dead-branches: true
|
57
22
|
publishers:
|
@@ -0,0 +1,22 @@
|
|
1
|
+
repos:
|
2
|
+
- repo: git://github.com/pre-commit/pre-commit-hooks
|
3
|
+
rev: v2.2.3
|
4
|
+
hooks:
|
5
|
+
- id: check-case-conflict
|
6
|
+
- id: check-executables-have-shebangs
|
7
|
+
- id: check-json
|
8
|
+
- id: check-merge-conflict
|
9
|
+
- id: check-yaml
|
10
|
+
- id: check-xml
|
11
|
+
- id: end-of-file-fixer
|
12
|
+
|
13
|
+
- repo: git@github.com:elastic/apm-pipeline-library
|
14
|
+
rev: current
|
15
|
+
hooks:
|
16
|
+
- id: check-bash-syntax
|
17
|
+
- id: check-abstract-classes-and-trait
|
18
|
+
- id: check-jsonslurper-class
|
19
|
+
- id: check-jenkins-pipelines
|
20
|
+
- id: check-unicode-non-breaking-spaces
|
21
|
+
- id: remove-unicode-non-breaking-spaces
|
22
|
+
- id: check-jjbb
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -66,9 +66,6 @@ Style/DoubleNegation:
|
|
66
66
|
Style/EmptyMethod:
|
67
67
|
Enabled: false
|
68
68
|
|
69
|
-
Rails/Delegate:
|
70
|
-
Enabled: false
|
71
|
-
|
72
69
|
Style/NumericPredicate:
|
73
70
|
Enabled: false
|
74
71
|
|
@@ -83,3 +80,6 @@ Naming/MemoizedInstanceVariableName:
|
|
83
80
|
|
84
81
|
Style/SpecialGlobalVars:
|
85
82
|
Enabled: false
|
83
|
+
|
84
|
+
Style/MissingRespondToMissing:
|
85
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
|
5
5
|
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## 2.10.0
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
- Add Ruby specific metrics ([#437](https://github.com/elastic/apm-agent-ruby/pull/437))
|
12
|
+
- Support for APM Agent Configuration via Kibana ([#464](https://github.com/elastic/apm-agent-ruby/pull/464))
|
13
|
+
- Change span name format and add command to context's db.statement for `MongoSpy` ([#488](https://github.com/elastic/apm-agent-ruby/pull/490))
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
|
17
|
+
- `ElasticAPM.report` and `ElasticAPM.report_message` return the string ID of the generated `Error` objects ([#507](https://github.com/elastic/apm-agent-ruby/pull/507))
|
18
|
+
|
7
19
|
## 2.9.1 (2019-06-28)
|
8
20
|
|
9
21
|
### Fixed
|
data/docs/api.asciidoc
CHANGED
@@ -212,7 +212,7 @@ Arguments:
|
|
212
212
|
* `handled`: Whether the error was _handled_ eg. wasn't rescued and was represented
|
213
213
|
to the user. Default: `true`.
|
214
214
|
|
215
|
-
Returns `[ElasticAPM::Error]
|
215
|
+
Returns `[String]` ID of the generated `[ElasticAPM::Error]` object.
|
216
216
|
|
217
217
|
[float]
|
218
218
|
[[api-agent-report-message]]
|
@@ -231,7 +231,7 @@ Arguments:
|
|
231
231
|
|
232
232
|
* `message`: A custom error string. **Required**.
|
233
233
|
|
234
|
-
Returns `[ElasticAPM::Error]
|
234
|
+
Returns `[String]` ID of the generated `[ElasticAPM::Error]` object.
|
235
235
|
|
236
236
|
[float]
|
237
237
|
[[api-context]]
|
data/docs/configuration.asciidoc
CHANGED
@@ -62,7 +62,7 @@ Some options can be set with `ENV` variables and all of them may be set in
|
|
62
62
|
your source code.
|
63
63
|
|
64
64
|
When setting values for lists using `ENV` variables, strings are split by comma
|
65
|
-
eg `
|
65
|
+
eg `ELASTIC_APM_CUSTOM_KEY_FILTERS="a,b" # => [/a/, /b/]`.
|
66
66
|
|
67
67
|
[float]
|
68
68
|
[[config-config-file]]
|
@@ -213,6 +213,21 @@ Whether or not to attach the request headers to transactions and errors.
|
|
213
213
|
|
214
214
|
Whether or not to attach `ENV` from Rack to transactions and errors.
|
215
215
|
|
216
|
+
[float]
|
217
|
+
[[config-central-config]]
|
218
|
+
==== `central_config`
|
219
|
+
|============
|
220
|
+
| Environment | `Config` key | Default
|
221
|
+
| `ELASTIC_APM_CENTRAL_CONFIG` | `central_config` | `true`
|
222
|
+
|============
|
223
|
+
|
224
|
+
Enable {kibana-ref}/agent-configuration.html[APM Agent Configuration via Kibana].
|
225
|
+
If set to `true`, the client will poll the APM Server regularly for new agent configuration.
|
226
|
+
|
227
|
+
Usually APM Server determines how often to poll, but if not the default interval is 5 minutes.
|
228
|
+
|
229
|
+
NOTE: This feature requires APM Server v7.3 or later and that the APM Server is configured with `kibana.enabled: true`.
|
230
|
+
|
216
231
|
[float]
|
217
232
|
[[config-custom-key-filters]]
|
218
233
|
==== `custom_key_filters`
|
@@ -244,6 +259,10 @@ Add default tags to add to every transaction.
|
|
244
259
|
|
245
260
|
WARNING: Be aware that tags are indexed in Elasticsearch. Using too many unique keys will result in *https://www.elastic.co/blog/found-crash-elasticsearch#mapping-explosion[Mapping explosion]*.
|
246
261
|
|
262
|
+
NOTE: `global_labels` are supported as of APM server version 7.2. `default_tags` will eventually be
|
263
|
+
deprecated so please transition to using `global_labels` instead. In the meantime, any `default_tags`
|
264
|
+
that are set will override `global_labels`.
|
265
|
+
|
247
266
|
[float]
|
248
267
|
[[config-disable-send]]
|
249
268
|
==== `disable_send`
|
@@ -337,6 +356,23 @@ Version number of the used framework.
|
|
337
356
|
For Ruby on Rails and Sinatra, this defaults to the used version of the framework,
|
338
357
|
otherwise, the default is `nil`.
|
339
358
|
|
359
|
+
[float]
|
360
|
+
[[config-global-labels]]
|
361
|
+
==== `global_labels`
|
362
|
+
|
363
|
+
[options="header"]
|
364
|
+
|============
|
365
|
+
| Environment | `Config` key | Default | Example
|
366
|
+
| `ELASTIC_APM_GLOBAL_LABELS` | `global_labels` | `nil` | `dept=engineering,rack=number8`
|
367
|
+
|============
|
368
|
+
|
369
|
+
Labels added to all events, with the format key=value[,key=value[,...]].
|
370
|
+
|
371
|
+
NOTE: This option requires APM Server 7.2 or greater, and will have no effect when using older
|
372
|
+
server versions. `default_tags` will eventually be deprecated but in the meantime, their value
|
373
|
+
will override any `global_labels`. Please transition to using `global_labels` instead of
|
374
|
+
`default_tags` in light of this deprecation.
|
375
|
+
|
340
376
|
[float]
|
341
377
|
[[config-hostname]]
|
342
378
|
==== `hostname`
|
data/docs/metrics.asciidoc
CHANGED
@@ -12,11 +12,15 @@ You can adjust the interval by setting <<config-metrics-interval,`metrics_interv
|
|
12
12
|
|
13
13
|
The metrics will be stored in the `apm-*` index and have the `processor.event` property set to `metric`.
|
14
14
|
|
15
|
+
[float]
|
16
|
+
[[metrics-system]]
|
17
|
+
=== System metrics
|
18
|
+
|
15
19
|
**Note:** Metrics from the Ruby agent are Linux only for now.
|
16
20
|
|
17
21
|
[float]
|
18
22
|
[[metric-system.cpu.total.norm.pct]]
|
19
|
-
|
23
|
+
==== `system.cpu.total.norm.pct`
|
20
24
|
|
21
25
|
* *Type:* Float
|
22
26
|
* *Format:* Percent
|
@@ -26,7 +30,7 @@ normalised by the number of cores.
|
|
26
30
|
|
27
31
|
[float]
|
28
32
|
[[metric-system.memory.total]]
|
29
|
-
|
33
|
+
==== `system.memory.total`
|
30
34
|
|
31
35
|
* *Type:* Long
|
32
36
|
* *Format:* Bytes
|
@@ -35,7 +39,7 @@ The total memory of the system in bytes.
|
|
35
39
|
|
36
40
|
[float]
|
37
41
|
[[metric-system.memory.actual.free]]
|
38
|
-
|
42
|
+
==== `system.memory.actual.free`
|
39
43
|
|
40
44
|
* *Type:* Long
|
41
45
|
* *Format:* Bytes
|
@@ -44,7 +48,7 @@ Free memory of the system in bytes.
|
|
44
48
|
|
45
49
|
[float]
|
46
50
|
[[metric-system.process.cpu.total.norm.pct]]
|
47
|
-
|
51
|
+
==== `system.process.cpu.total.norm.pct`
|
48
52
|
|
49
53
|
* *Type:* Float
|
50
54
|
* *Format:* Percent
|
@@ -54,7 +58,7 @@ This value is normalized by the number of CPU cores and it ranges from 0 to 100%
|
|
54
58
|
|
55
59
|
[float]
|
56
60
|
[[metric-system.process.memory.size]]
|
57
|
-
|
61
|
+
==== `system.process.memory.size`
|
58
62
|
|
59
63
|
* *Type:* Long
|
60
64
|
* *Format:* Bytes
|
@@ -63,10 +67,77 @@ The total virtual memory the process has.
|
|
63
67
|
|
64
68
|
[float]
|
65
69
|
[[metric-system.process.memory.rss.bytes]]
|
66
|
-
|
70
|
+
==== `system.process.memory.rss.bytes`
|
67
71
|
|
68
72
|
* *Type:* Long
|
69
73
|
* *Format:* Bytes
|
70
74
|
|
71
75
|
The Resident Set Size,
|
72
76
|
the amount of memory the process occupies in main memory (RAM).
|
77
|
+
|
78
|
+
[float]
|
79
|
+
[[metrics-ruby]]
|
80
|
+
=== Ruby Metrics
|
81
|
+
|
82
|
+
[float]
|
83
|
+
[[metric-ruby.gc.counts]]
|
84
|
+
==== `ruby.gc.count`
|
85
|
+
|
86
|
+
* *Type:* Integer
|
87
|
+
* *Format:* Count
|
88
|
+
|
89
|
+
The number of Garbage Collection runs since the process started.
|
90
|
+
|
91
|
+
[float]
|
92
|
+
[[metric-ruby.threads]]
|
93
|
+
==== `ruby.threads`
|
94
|
+
|
95
|
+
* *Type:* Integer
|
96
|
+
* *Format:* Count
|
97
|
+
|
98
|
+
The number of threads belonging to the current process.
|
99
|
+
|
100
|
+
[float]
|
101
|
+
[[metric-ruby.heap.slots.live]]
|
102
|
+
==== `ruby.heap.slots.live`
|
103
|
+
|
104
|
+
* *Type:* Integer
|
105
|
+
* *Format:* Slots
|
106
|
+
|
107
|
+
Current amount of heap slots that are live.
|
108
|
+
|
109
|
+
**NB:** Not currently supported on JRuby.
|
110
|
+
|
111
|
+
[float]
|
112
|
+
[[metric-ruby.heap.slots.free]]
|
113
|
+
==== `ruby.heap.slots.free`
|
114
|
+
|
115
|
+
* *Type:* Integer
|
116
|
+
* *Format:* Slots
|
117
|
+
|
118
|
+
Current amount of heap slots that are free.
|
119
|
+
|
120
|
+
**NB:** Not currently supported on JRuby.
|
121
|
+
|
122
|
+
[float]
|
123
|
+
[[metrics-ruby.heap.allocations.total]]
|
124
|
+
==== `ruby.heap.allocations.total`
|
125
|
+
|
126
|
+
* *Type:* Integer
|
127
|
+
* *Format:* Objects
|
128
|
+
|
129
|
+
Current amount of allocated objects on the heap.
|
130
|
+
|
131
|
+
**NB:** Not currently supported on JRuby.
|
132
|
+
|
133
|
+
[float]
|
134
|
+
[[metrics-ruby.gc.time]]
|
135
|
+
==== `ruby.gc.time`
|
136
|
+
|
137
|
+
* *Type:* Float
|
138
|
+
* *Format:* Seconds
|
139
|
+
|
140
|
+
The total time spent in garbage collection.
|
141
|
+
|
142
|
+
**NB:** You need to enable Ruby's GC Profiler for this to get reported.
|
143
|
+
You can do this at any time when your application boots by calling `GC::Profiler.enable`.
|
data/lib/elastic_apm.rb
CHANGED
@@ -305,7 +305,7 @@ module ElasticAPM # rubocop:disable Metrics/ModuleLength
|
|
305
305
|
# @param exception [Exception] The exception
|
306
306
|
# @param context [Context] An optional [Context]
|
307
307
|
# @param handled [Boolean] Whether the exception was rescued
|
308
|
-
# @return [
|
308
|
+
# @return [String] ID of the generated [Error]
|
309
309
|
def report(exception, context: nil, handled: true)
|
310
310
|
agent&.report(exception, context: context, handled: handled)
|
311
311
|
end
|
@@ -314,7 +314,7 @@ module ElasticAPM # rubocop:disable Metrics/ModuleLength
|
|
314
314
|
#
|
315
315
|
# @param message [String] The message
|
316
316
|
# @param context [Context] An optional [Context]
|
317
|
-
# @return [
|
317
|
+
# @return [String] ID of the generated [Error]
|
318
318
|
def report_message(message, context: nil, **attrs)
|
319
319
|
agent&.report_message(
|
320
320
|
message,
|
data/lib/elastic_apm/agent.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'elastic_apm/error'
|
4
|
+
|
3
5
|
require 'elastic_apm/context_builder'
|
4
6
|
require 'elastic_apm/error_builder'
|
5
7
|
require 'elastic_apm/stacktrace_builder'
|
6
|
-
|
8
|
+
|
9
|
+
require 'elastic_apm/central_config'
|
7
10
|
require 'elastic_apm/transport/base'
|
8
|
-
require 'elastic_apm/spies'
|
9
11
|
require 'elastic_apm/metrics'
|
10
12
|
|
13
|
+
require 'elastic_apm/spies'
|
14
|
+
|
11
15
|
module ElasticAPM
|
12
16
|
# rubocop:disable Metrics/ClassLength
|
13
17
|
# @api private
|
@@ -57,6 +61,7 @@ module ElasticAPM
|
|
57
61
|
!!@instance
|
58
62
|
end
|
59
63
|
|
64
|
+
# rubocop:disable Metrics/MethodLength
|
60
65
|
def initialize(config)
|
61
66
|
@config = config
|
62
67
|
|
@@ -64,6 +69,7 @@ module ElasticAPM
|
|
64
69
|
@context_builder = ContextBuilder.new(config)
|
65
70
|
@error_builder = ErrorBuilder.new(self)
|
66
71
|
|
72
|
+
@central_config = CentralConfig.new(config)
|
67
73
|
@transport = Transport::Base.new(config)
|
68
74
|
@instrumenter = Instrumenter.new(
|
69
75
|
config,
|
@@ -71,6 +77,7 @@ module ElasticAPM
|
|
71
77
|
) { |event| enqueue event }
|
72
78
|
@metrics = Metrics.new(config) { |event| enqueue event }
|
73
79
|
end
|
80
|
+
# rubocop:enable Metrics/MethodLength
|
74
81
|
|
75
82
|
attr_reader :config, :transport, :instrumenter,
|
76
83
|
:stacktrace_builder, :context_builder, :error_builder, :metrics
|
@@ -189,6 +196,7 @@ module ElasticAPM
|
|
189
196
|
handled: handled
|
190
197
|
)
|
191
198
|
enqueue error
|
199
|
+
error.id
|
192
200
|
end
|
193
201
|
|
194
202
|
def report_message(message, context: nil, backtrace: nil, **attrs)
|
@@ -199,6 +207,7 @@ module ElasticAPM
|
|
199
207
|
**attrs
|
200
208
|
)
|
201
209
|
enqueue error
|
210
|
+
error.id
|
202
211
|
end
|
203
212
|
|
204
213
|
# filters
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'elastic_apm/central_config/cache_control'
|
4
|
+
|
5
|
+
module ElasticAPM
|
6
|
+
# @api private
|
7
|
+
class CentralConfig
|
8
|
+
include Logging
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
class ResponseError < InternalError
|
12
|
+
def initialize(response)
|
13
|
+
@response = response
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :response
|
17
|
+
end
|
18
|
+
class ClientError < ResponseError; end
|
19
|
+
class ServerError < ResponseError; end
|
20
|
+
|
21
|
+
DEFAULT_MAX_AGE = 300
|
22
|
+
|
23
|
+
def initialize(config)
|
24
|
+
@config = config
|
25
|
+
@modified_options = {}
|
26
|
+
@service_info = {
|
27
|
+
'service.name': config.service_name,
|
28
|
+
'service.environment': config.environment
|
29
|
+
}.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :config
|
33
|
+
attr_reader :scheduled_task, :promise # for specs
|
34
|
+
|
35
|
+
def start
|
36
|
+
return unless config.central_config?
|
37
|
+
|
38
|
+
fetch_and_apply_config
|
39
|
+
end
|
40
|
+
|
41
|
+
def fetch_and_apply_config
|
42
|
+
@promise =
|
43
|
+
Concurrent::Promise
|
44
|
+
.execute(&method(:fetch_config))
|
45
|
+
.on_success(&method(:handle_success))
|
46
|
+
.rescue(&method(:handle_error))
|
47
|
+
end
|
48
|
+
|
49
|
+
def stop
|
50
|
+
@scheduled_task&.cancel
|
51
|
+
end
|
52
|
+
|
53
|
+
# rubocop:disable Metrics/MethodLength
|
54
|
+
def fetch_config
|
55
|
+
resp = perform_request
|
56
|
+
|
57
|
+
case resp.status
|
58
|
+
when 200..299
|
59
|
+
resp
|
60
|
+
when 300..399
|
61
|
+
resp
|
62
|
+
when 400..499
|
63
|
+
raise ClientError, resp
|
64
|
+
when 500..599
|
65
|
+
raise ServerError, resp
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# rubocop:enable Metrics/MethodLength
|
69
|
+
|
70
|
+
def assign(update)
|
71
|
+
# For each updated option, store the original value,
|
72
|
+
# unless already stored
|
73
|
+
update.each_key do |key|
|
74
|
+
@modified_options[key] ||= config.get(key.to_sym)&.value
|
75
|
+
end
|
76
|
+
|
77
|
+
# If the new update doesn't set a previously modified option,
|
78
|
+
# revert it to the original
|
79
|
+
@modified_options.each_key do |key|
|
80
|
+
next if update.key?(key)
|
81
|
+
update[key] = @modified_options.delete(key)
|
82
|
+
end
|
83
|
+
|
84
|
+
config.assign(update)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# rubocop:disable Metrics/MethodLength
|
90
|
+
def handle_success(resp)
|
91
|
+
if resp.status == 304
|
92
|
+
info 'Received 304 Not Modified'
|
93
|
+
else
|
94
|
+
update = JSON.parse(resp.body.to_s)
|
95
|
+
assign(update)
|
96
|
+
|
97
|
+
info 'Updated config from Kibana'
|
98
|
+
end
|
99
|
+
|
100
|
+
schedule_next_fetch(resp)
|
101
|
+
|
102
|
+
true
|
103
|
+
rescue Exception => e
|
104
|
+
error 'Failed to apply remote config, %s', e.inspect
|
105
|
+
debug { e.backtrace.join('\n') }
|
106
|
+
end
|
107
|
+
# rubocop:enable Metrics/MethodLength
|
108
|
+
|
109
|
+
def handle_error(error)
|
110
|
+
error(
|
111
|
+
'Failed fetching config: %s, trying again in %d seconds',
|
112
|
+
error.response.body, DEFAULT_MAX_AGE
|
113
|
+
)
|
114
|
+
|
115
|
+
assign({})
|
116
|
+
|
117
|
+
schedule_next_fetch(error.response)
|
118
|
+
end
|
119
|
+
|
120
|
+
def perform_request
|
121
|
+
Http.post(
|
122
|
+
config.server_url + '/agent/v1/config/',
|
123
|
+
body: @service_info,
|
124
|
+
headers: { etag: 1, content_type: 'application/json' }
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
def schedule_next_fetch(resp)
|
129
|
+
seconds =
|
130
|
+
if (cache_header = resp.headers['Cache-Control'])
|
131
|
+
CacheControl.new(cache_header).max_age
|
132
|
+
else
|
133
|
+
DEFAULT_MAX_AGE
|
134
|
+
end
|
135
|
+
|
136
|
+
@scheduled_task =
|
137
|
+
Concurrent::ScheduledTask
|
138
|
+
.execute(seconds, &method(:fetch_and_apply_config))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|