prometheus_exporter 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88f0f450fbf76e51d739c1f9abc7cea62e2651dd366c5e9bd38df9464ebf797e
4
- data.tar.gz: a89f2e00749002ba9323a6741cc682fb9bd2df051dd96cd68c9c9fd6e51d73d6
3
+ metadata.gz: d78846839afaebda3169dbf21569a55a692884872508f751544d791f75f3c993
4
+ data.tar.gz: aa70c3578a9fa9b7a15bcc032981d21d49344e0c313c874346ee96e962894c9f
5
5
  SHA512:
6
- metadata.gz: 32922666245bacfd8d608a4a08c255ef8103f70c7ba31974ed3c2685cc261b05df25d17e2c0bc38c50d67a576388d98ae9150b204a0385d3d516f298b77aa6e4
7
- data.tar.gz: 360d70c6f3c03e31158a43f26fccee61ec25717a2b4f021ff46902b447f864533e543083d5dc675bdab0f47df93288f3f7f60157145fbea5a1e1062d6981e4fa
6
+ metadata.gz: cc029080ef384bd5f9adff56491ee1a1ba9bb601ee81009c4685fca76a22ab2e20440f4bc1e5f67bcba7f0ec9f703ffbb0ac0f9b08c86c91bdee6a47c7bcdeb4
7
+ data.tar.gz: f5fc713effa23e04599272a4dcfe51091927e3b281ed6e930306d4f200ff591dea70f0c9762b1e372300168cee1dcec82427ed407c4633c8300230fd8d551030
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ 0.4.8 - 10-04-2019
2
+
3
+ - Feature: added helpers for instrumenting unicorn using raindrops
4
+
1
5
  0.4.7 - 08-04-2019
2
6
 
3
7
  - Fix: collector was not escaping " \ and \n correctly. This could lead
data/README.md CHANGED
@@ -16,6 +16,7 @@ To learn more see [Instrumenting Rails with Prometheus](https://samsaffron.com/a
16
16
  * [Delayed Job plugin](#delayed-job-plugin)
17
17
  * [Hutch metrics](#hutch-message-processing-tracer)
18
18
  * [Puma metrics](#puma-metrics)
19
+ * [Unicorn metrics](#unicorn-metrics)
19
20
  * [Custom type collectors](#custom-type-collectors)
20
21
  * [Multi process mode with custom collector](#multi-process-mode-with-custom-collector)
21
22
  * [GraphQL support](#graphql-support)
@@ -158,6 +159,7 @@ gem 'prometheus_exporter'
158
159
  ```
159
160
 
160
161
  In an initializer:
162
+
161
163
  ```ruby
162
164
  unless Rails.env == "test"
163
165
  require 'prometheus_exporter/middleware'
@@ -275,6 +277,21 @@ after_worker_boot do
275
277
  end
276
278
  ```
277
279
 
280
+ ### Unicorn process metrics
281
+
282
+ In order to gather metrics from unicorn processes, we use `rainbows`, which exposes `Rainbows::Linux.tcp_listener_stats` to gather information about active workers and queued requests. To start monitoring your unicorn processes, you'll need to know both the path to unicorn PID file and the listen address (`pid_file` and `listen` in your unicorn config file)
283
+
284
+ Then, run `prometheus_exporter` with `--unicorn-master` and `--unicorn-listen-address` options:
285
+
286
+ ```bash
287
+ prometheus_exporter --unicorn-master /var/run/unicorn.pid --unicorn-listen-address 127.0.0.1:3000
288
+
289
+ # alternatively, if you're using unix sockets:
290
+ prometheus_exporter --unicorn-master /var/run/unicorn.pid --unicorn-listen-address /var/run/unicorn.sock
291
+ ```
292
+
293
+ Note: You must install the `raindrops` gem in your `Gemfile` or locally.
294
+
278
295
  ### Custom type collectors
279
296
 
280
297
  In some cases you may have custom metrics you want to ship the collector in a batch. In this case you may still be interested in the base collector behavior, but would like to add your own special messages.
@@ -313,7 +330,6 @@ PrometheusExporter::Client.default.send_json(type: "person", age: 40)
313
330
 
314
331
  To load the custom collector run:
315
332
 
316
-
317
333
  ```
318
334
  $ bundle exec prometheus_exporter -a person_collector.rb
319
335
  ```
@@ -37,6 +37,13 @@ def run
37
37
  options[:verbose] = true
38
38
  end
39
39
 
40
+ opt.on('--unicorn-listen-address ADDRESS', String, '(optional) Address where unicorn listens on (unix or TCP address)') do |o|
41
+ options[:unicorn_listen_address] = o
42
+ end
43
+
44
+ opt.on('--unicorn-master PID_FILE', String, '(optional) PID file of unicorn master process to monitor unicorn') do |o|
45
+ options[:unicorn_pid_file] = o
46
+ end
40
47
  end.parse!
41
48
 
42
49
  if custom_collector_filename
@@ -0,0 +1,68 @@
1
+ begin
2
+ require 'raindrops'
3
+ rescue LoadError
4
+ # No raindrops available, dont do anything
5
+ end
6
+
7
+ module PrometheusExporter::Instrumentation
8
+ # collects stats from unicorn
9
+ class Unicorn
10
+ def self.start(pid_file:, listener_address:, client:, frequency: 30)
11
+ unicorn_collector = new(pid_file: pid_file, listener_address: listener_address)
12
+ client ||= PrometheusExporter::Client.default
13
+ Thread.new do
14
+ loop do
15
+ metric = unicorn_collector.collect
16
+ client.send_json metric
17
+ rescue StandardError => e
18
+ STDERR.puts("Prometheus Exporter Failed To Collect Unicorn Stats #{e}")
19
+ ensure
20
+ sleep frequency
21
+ end
22
+ end
23
+ end
24
+
25
+ def initialize(pid_file:, listener_address:)
26
+ @pid_file = pid_file
27
+ @listener_address = listener_address
28
+ @tcp = listener_address =~ /\A.+:\d+\z/
29
+ end
30
+
31
+ def collect
32
+ metric = {}
33
+ metric[:type] = 'unicorn'
34
+ collect_unicorn_stats(metric)
35
+ metric
36
+ end
37
+
38
+ def collect_unicorn_stats(metric)
39
+ stats = listener_address_stats
40
+
41
+ metric[:active_workers_total] = stats.active
42
+ metric[:request_backlog_total] = stats.queued
43
+ metric[:workers_total] = worker_process_count
44
+ end
45
+
46
+ private
47
+
48
+ def worker_process_count
49
+ return nil unless File.exist?(@pid_file)
50
+ pid = File.read(@pid_file)
51
+
52
+ return nil unless pid && pid.to_i > 0
53
+
54
+ # find all processes whose parent is the unicorn master
55
+ # but we're actually only interested in the number of processes (= lines of output)
56
+ result = `ps --no-header -o pid --ppid #{pid}`
57
+ result.lines.count
58
+ end
59
+
60
+ def listener_address_stats
61
+ if @tcp
62
+ Raindrops::Linux.tcp_listener_stats(@listener_address)[@listener_address]
63
+ else
64
+ Raindrops::Linux.unix_listener_stats(@listener_address)[@listener_address]
65
+ end
66
+ end
67
+ end
68
+ end
@@ -4,3 +4,4 @@ require_relative "instrumentation/sidekiq"
4
4
  require_relative "instrumentation/delayed_job"
5
5
  require_relative "instrumentation/puma"
6
6
  require_relative "instrumentation/hutch"
7
+ require_relative "instrumentation/unicorn"
@@ -16,6 +16,7 @@ module PrometheusExporter::Server
16
16
  register_collector(DelayedJobCollector.new)
17
17
  register_collector(PumaCollector.new)
18
18
  register_collector(HutchCollector.new)
19
+ register_collector(UnicornCollector.new)
19
20
  end
20
21
 
21
22
  def register_collector(collector)
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
+ require 'prometheus_exporter/client'
3
+ require_relative '../instrumentation/unicorn'
2
4
 
3
5
  module PrometheusExporter::Server
4
6
  class RunnerException < StandardError; end;
@@ -20,6 +22,15 @@ module PrometheusExporter::Server
20
22
  raise WrongInheritance, 'Collector class must be inherited from PrometheusExporter::Server::CollectorBase'
21
23
  end
22
24
 
25
+ if unicorn_listen_address && unicorn_pid_file
26
+ local_client = PrometheusExporter::LocalClient.new(collector: collector)
27
+ PrometheusExporter::Instrumentation::Unicorn.start(
28
+ pid_file: unicorn_pid_file,
29
+ listener_address: unicorn_listen_address,
30
+ client: local_client
31
+ )
32
+ end
33
+
23
34
  server = server_class.new port: port, collector: collector, timeout: timeout, verbose: verbose
24
35
  server.start
25
36
  end
@@ -81,6 +92,8 @@ module PrometheusExporter::Server
81
92
  @server_class || PrometheusExporter::Server::WebServer
82
93
  end
83
94
 
95
+ attr_accessor :unicorn_listen_address, :unicorn_pid_file
96
+
84
97
  def collector
85
98
  @_collector ||= collector_class.new
86
99
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # custom type collector for prometheus_exporter for handling the metrics sent from
4
+ # PrometheusExporter::Instrumentation::Unicorn
5
+ class PrometheusExporter::Server::UnicornCollector < PrometheusExporter::Server::TypeCollector
6
+ UNICORN_GAUGES = {
7
+ workers_total: 'Number of unicorn workers.',
8
+ active_workers_total: 'Number of active unicorn workers',
9
+ request_backlog_total: 'Number of requests waiting to be processed by a unicorn worker.'
10
+ }.freeze
11
+
12
+ def initialize
13
+ @unicorn_metrics = []
14
+ end
15
+
16
+ def type
17
+ 'unicorn'
18
+ end
19
+
20
+ def metrics
21
+ return [] if @unicorn_metrics.length.zero?
22
+
23
+ metrics = {}
24
+
25
+ @unicorn_metrics.map do |m|
26
+ UNICORN_GAUGES.map do |k, help|
27
+ k = k.to_s
28
+ if (v = m[k])
29
+ g = metrics[k] ||= PrometheusExporter::Metric::Gauge.new("unicorn_#{k}", help)
30
+ g.observe(v)
31
+ end
32
+ end
33
+ end
34
+
35
+ metrics.values
36
+ end
37
+
38
+ def collect(obj)
39
+ @unicorn_metrics << obj
40
+ end
41
+ end
@@ -10,3 +10,4 @@ require_relative "server/web_server"
10
10
  require_relative "server/runner"
11
11
  require_relative "server/puma_collector"
12
12
  require_relative "server/hutch_collector"
13
+ require_relative "server/unicorn_collector"
@@ -1,3 +1,3 @@
1
1
  module PrometheusExporter
2
- VERSION = "0.4.7"
2
+ VERSION = "0.4.8"
3
3
  end
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.4.7
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-08 00:00:00.000000000 Z
11
+ date: 2019-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -167,6 +167,7 @@ files:
167
167
  - lib/prometheus_exporter/instrumentation/process.rb
168
168
  - lib/prometheus_exporter/instrumentation/puma.rb
169
169
  - lib/prometheus_exporter/instrumentation/sidekiq.rb
170
+ - lib/prometheus_exporter/instrumentation/unicorn.rb
170
171
  - lib/prometheus_exporter/metric.rb
171
172
  - lib/prometheus_exporter/metric/base.rb
172
173
  - lib/prometheus_exporter/metric/counter.rb
@@ -184,6 +185,7 @@ files:
184
185
  - lib/prometheus_exporter/server/runner.rb
185
186
  - lib/prometheus_exporter/server/sidekiq_collector.rb
186
187
  - lib/prometheus_exporter/server/type_collector.rb
188
+ - lib/prometheus_exporter/server/unicorn_collector.rb
187
189
  - lib/prometheus_exporter/server/web_collector.rb
188
190
  - lib/prometheus_exporter/server/web_server.rb
189
191
  - lib/prometheus_exporter/version.rb