prometheus_exporter 0.3.1 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/CHANGELOG +8 -0
- data/README.md +37 -0
- data/lib/prometheus_exporter/client.rb +9 -2
- data/lib/prometheus_exporter/instrumentation/delayed_job.rb +7 -3
- data/lib/prometheus_exporter/server/delayed_job_collector.rb +26 -4
- data/lib/prometheus_exporter/server/sidekiq_collector.rb +7 -3
- data/lib/prometheus_exporter/server/web_collector.rb +5 -4
- data/lib/prometheus_exporter/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 884ad6656dc8d2b784711db6e057cf9743cc93a4bb7d9bc978b06e90441978a1
|
4
|
+
data.tar.gz: 34fbcbba98564562c49ea99dcffa95403224d6c85f372686426bed005d5a64e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 243a116fd665dea9bb6b9ed2d350a07a3819b512be4320993caa4b3a1038987c9232b325ff605f9495b75c33626dab2a0ba56d7fd6b0f3119d23156086391c72
|
7
|
+
data.tar.gz: 26630637bbcbfcd92d5c3ec3ccef0ffe9e88b1d8822e2df7c1e76aef9c0ae2bae730e4f6125dd9d169679cb8336f03e6129f0eeb7f2f6ad7e0aa6d3ec886c8aa
|
data/.travis.yml
CHANGED
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -157,6 +157,17 @@ Sidekiq.configure_server do |config|
|
|
157
157
|
end
|
158
158
|
```
|
159
159
|
|
160
|
+
To monitor Sidekiq process info
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
Sidekiq.configure_server do |config|
|
164
|
+
config.on :startup do
|
165
|
+
require 'prometheus_exporter/instrumentation'
|
166
|
+
PrometheusExporter::Instrumentation::Process.start type: 'sidekiq'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
160
171
|
It also comes with a DelayedJob plugin.
|
161
172
|
|
162
173
|
```ruby
|
@@ -322,6 +333,12 @@ thing1 122
|
|
322
333
|
thing2 12
|
323
334
|
```
|
324
335
|
|
336
|
+
### GraphQL support
|
337
|
+
|
338
|
+
GraphQL execution metrics are [supported](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/queries/tracing.md#prometheus) and can be collected via the GraphQL
|
339
|
+
collector, included in [graphql-ruby](https://github.com/rmosolgo/graphql-ruby)
|
340
|
+
|
341
|
+
|
325
342
|
### Metrics default prefix / labels
|
326
343
|
|
327
344
|
_This only works in single process mode_
|
@@ -350,6 +367,26 @@ ruby_web_requests{hostname="app-server-01",route="test/route"} 1
|
|
350
367
|
ruby_web_requests{hostname="app-server-01"} 1
|
351
368
|
```
|
352
369
|
|
370
|
+
### Client default labels
|
371
|
+
|
372
|
+
You can specify a default label for the instrumentation metrics sent by an specific client, for example:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
# Specify on intializing PrometheusExporter::Client
|
376
|
+
PrometheusExporter::Client.new(custom_labels: { hostname: 'app-server-01', app_name: 'app-01' })
|
377
|
+
|
378
|
+
# Specify on an instance of PrometheusExporter::Client
|
379
|
+
client = PrometheusExporter::Client.new
|
380
|
+
client.custom_labels = { hostname: 'app-server-01', app_name: 'app-01' }
|
381
|
+
```
|
382
|
+
|
383
|
+
Will result in:
|
384
|
+
|
385
|
+
```
|
386
|
+
http_requests_total{controller="home","action"="index",service="app-server-01",app_name="app-01"} 2
|
387
|
+
http_requests_total{service="app-server-01",app_name="app-01"} 1
|
388
|
+
```
|
389
|
+
|
353
390
|
## Transport concerns
|
354
391
|
|
355
392
|
Prometheus Exporter handles transport using a simple HTTP protocol. In multi process mode we avoid needing a large number of HTTP request by using chunked encoding to send metrics. This means that a single HTTP channel can deliver 100s or even 1000s of metrics over a single HTTP session to the `/send-metrics` endpoint. All calls to `send` and `send_json` on the PrometheusExporter::Client class are **non-blocking** and batched.
|
@@ -35,7 +35,7 @@ class PrometheusExporter::Client
|
|
35
35
|
MAX_SOCKET_AGE = 25
|
36
36
|
MAX_QUEUE_SIZE = 10_000
|
37
37
|
|
38
|
-
def initialize(host: 'localhost', port: PrometheusExporter::DEFAULT_PORT, max_queue_size: nil, thread_sleep: 0.5, json_serializer: nil)
|
38
|
+
def initialize(host: 'localhost', port: PrometheusExporter::DEFAULT_PORT, max_queue_size: nil, thread_sleep: 0.5, json_serializer: nil, custom_labels: nil)
|
39
39
|
@metrics = []
|
40
40
|
|
41
41
|
@queue = Queue.new
|
@@ -57,6 +57,12 @@ class PrometheusExporter::Client
|
|
57
57
|
@thread_sleep = thread_sleep
|
58
58
|
|
59
59
|
@json_serializer = json_serializer == :oj ? PrometheusExporter::OjCompat : JSON
|
60
|
+
|
61
|
+
@custom_labels = custom_labels
|
62
|
+
end
|
63
|
+
|
64
|
+
def custom_labels=(custom_labels)
|
65
|
+
@custom_labels = custom_labels
|
60
66
|
end
|
61
67
|
|
62
68
|
def register(type, name, help)
|
@@ -66,7 +72,8 @@ class PrometheusExporter::Client
|
|
66
72
|
end
|
67
73
|
|
68
74
|
def send_json(obj)
|
69
|
-
|
75
|
+
payload = @custom_labels.nil? ? obj : obj.merge(custom_labels: @custom_labels)
|
76
|
+
send(@json_serializer.dump(payload))
|
70
77
|
end
|
71
78
|
|
72
79
|
def send(str)
|
@@ -10,7 +10,8 @@ module PrometheusExporter::Instrumentation
|
|
10
10
|
plugin = Class.new(Delayed::Plugin) do
|
11
11
|
callbacks do |lifecycle|
|
12
12
|
lifecycle.around(:invoke_job) do |job, *args, &block|
|
13
|
-
|
13
|
+
max_attempts = Delayed::Worker.max_attempts
|
14
|
+
instrumenter.call(job, max_attempts, *args, &block)
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -23,9 +24,10 @@ module PrometheusExporter::Instrumentation
|
|
23
24
|
@client = client || PrometheusExporter::Client.default
|
24
25
|
end
|
25
26
|
|
26
|
-
def call(job, *args, &block)
|
27
|
+
def call(job, max_attempts, *args, &block)
|
27
28
|
success = false
|
28
29
|
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
30
|
+
attempts = job.attempts + 1 # Increment because we're adding the current attempt
|
29
31
|
result = block.call(job, *args)
|
30
32
|
success = true
|
31
33
|
result
|
@@ -36,7 +38,9 @@ module PrometheusExporter::Instrumentation
|
|
36
38
|
type: "delayed_job",
|
37
39
|
name: job.handler.to_s.match(JOB_CLASS_REGEXP).to_a[1].to_s,
|
38
40
|
success: success,
|
39
|
-
duration: duration
|
41
|
+
duration: duration,
|
42
|
+
attempts: attempts,
|
43
|
+
max_attempts: max_attempts
|
40
44
|
)
|
41
45
|
end
|
42
46
|
end
|
@@ -6,15 +6,25 @@ module PrometheusExporter::Server
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def collect(obj)
|
9
|
+
default_labels = { job_name: obj['name'] }
|
10
|
+
custom_labels = obj['custom_labels']
|
11
|
+
labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
|
12
|
+
|
9
13
|
ensure_delayed_job_metrics
|
10
|
-
@delayed_job_duration_seconds.observe(obj["duration"],
|
11
|
-
@delayed_jobs_total.observe(1,
|
12
|
-
@delayed_failed_jobs_total.observe(1,
|
14
|
+
@delayed_job_duration_seconds.observe(obj["duration"], labels)
|
15
|
+
@delayed_jobs_total.observe(1, labels)
|
16
|
+
@delayed_failed_jobs_total.observe(1, labels) if !obj["success"]
|
17
|
+
@delayed_jobs_max_attempts_reached_total.observe(1) if obj["attempts"] >= obj["max_attempts"]
|
18
|
+
@delayed_job_duration_seconds_summary.observe(obj["duration"])
|
19
|
+
@delayed_job_duration_seconds_summary.observe(obj["duration"], status: "success") if obj["success"]
|
20
|
+
@delayed_job_duration_seconds_summary.observe(obj["duration"], status: "failed") if !obj["success"]
|
21
|
+
@delayed_job_attempts_summary.observe(obj["attempts"]) if obj["success"]
|
13
22
|
end
|
14
23
|
|
15
24
|
def metrics
|
16
25
|
if @delayed_jobs_total
|
17
|
-
[@delayed_job_duration_seconds, @delayed_jobs_total, @delayed_failed_jobs_total
|
26
|
+
[@delayed_job_duration_seconds, @delayed_jobs_total, @delayed_failed_jobs_total,
|
27
|
+
@delayed_jobs_max_attempts_reached_total, @delayed_job_duration_seconds_summary, @delayed_job_attempts_summary]
|
18
28
|
else
|
19
29
|
[]
|
20
30
|
end
|
@@ -36,6 +46,18 @@ module PrometheusExporter::Server
|
|
36
46
|
@delayed_failed_jobs_total =
|
37
47
|
PrometheusExporter::Metric::Counter.new(
|
38
48
|
"delayed_failed_jobs_total", "Total number failed delayed jobs executed.")
|
49
|
+
|
50
|
+
@delayed_jobs_max_attempts_reached_total =
|
51
|
+
PrometheusExporter::Metric::Counter.new(
|
52
|
+
"delayed_jobs_max_attempts_reached_total", "Total number of delayed jobs that reached max attempts.")
|
53
|
+
|
54
|
+
@delayed_job_duration_seconds_summary =
|
55
|
+
PrometheusExporter::Metric::Summary.new("delayed_job_duration_seconds_summary",
|
56
|
+
"Summary of the time it takes jobs to execute.")
|
57
|
+
|
58
|
+
@delayed_job_attempts_summary =
|
59
|
+
PrometheusExporter::Metric::Summary.new("delayed_job_attempts_summary",
|
60
|
+
"Summary of the amount of attempts it takes delayed jobs to succeed.")
|
39
61
|
end
|
40
62
|
end
|
41
63
|
end
|
@@ -6,10 +6,14 @@ module PrometheusExporter::Server
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def collect(obj)
|
9
|
+
default_labels = { job_name: obj['name'] }
|
10
|
+
custom_labels = obj['custom_labels']
|
11
|
+
labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
|
12
|
+
|
9
13
|
ensure_sidekiq_metrics
|
10
|
-
@sidekiq_job_duration_seconds.observe(obj["duration"],
|
11
|
-
@sidekiq_jobs_total.observe(1,
|
12
|
-
@sidekiq_failed_jobs_total.observe(1,
|
14
|
+
@sidekiq_job_duration_seconds.observe(obj["duration"], labels)
|
15
|
+
@sidekiq_jobs_total.observe(1, labels)
|
16
|
+
@sidekiq_failed_jobs_total.observe(1, labels) if !obj["success"]
|
13
17
|
end
|
14
18
|
|
15
19
|
def metrics
|
@@ -51,11 +51,12 @@ module PrometheusExporter::Server
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def observe(obj)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
action: obj["action"] || "other"
|
54
|
+
default_labels = {
|
55
|
+
controller: obj['controller'] || 'other',
|
56
|
+
action: obj['action'] || 'other'
|
58
57
|
}
|
58
|
+
custom_labels = obj['custom_labels']
|
59
|
+
labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
|
59
60
|
|
60
61
|
@http_requests_total.observe(1, labels.merge(status: obj["status"]))
|
61
62
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prometheus_exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|