prometheus_exporter 0.4.3 → 0.4.4

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: e93d3054e02dcc5bc4dc87df3be0b87ce3715850d4d116465f31ee525bb9c9f6
4
- data.tar.gz: 681a91ab3490d12b095b5bde5a9eb303202e5c6b688cf57afe38752e49b2d9d4
3
+ metadata.gz: b60596255e84ca5aedae095d4ae7dda21f1c324e49a495e73e5f8e8a6adb3472
4
+ data.tar.gz: 990f03708492b5a2b5d13cf6a9bf67e091bdf62c819b1a559a0a240e6d9660bc
5
5
  SHA512:
6
- metadata.gz: b4b875a1d7799aab1ec0c6ec69570a070a730774cd58cd7a61e54d19bf4f327ddf0f47e6fa10e33084b86fbdcbd407a0e0e715bb190f9bf412b59ce17b9963dd
7
- data.tar.gz: 1face6bafbf0da750d2b88f3d5ed010cb136fad3da776928f7a327db20cc81fd972208f7cbfeb298dd72492489a8838c76429cbe448b87d478dfff79292c2f00
6
+ metadata.gz: d914be65e9857dcf5173e03a8fd230d0a2004aea8cf454fd1671229c856730ee72a9793624eddcf01ee561768d228e9e2e06eddd1a72629726d1dc994f34614b
7
+ data.tar.gz: 6a05a048eaa75641b749761ed823be1aa694e83d3c2f0d35e860e9237dd0f82569dc31c4c3d0e24293b10d1dcd5d36f16d893348c620f21efae9c16596b29b3c
data/README.md CHANGED
@@ -56,10 +56,20 @@ Simplest way of consuming Prometheus exporter is in a single process mode.
56
56
  ```ruby
57
57
  require 'prometheus_exporter/server'
58
58
 
59
+ # client allows instrumentation to send info to server
60
+ require 'prometheus_exporter/client'
61
+ require 'prometheus_exporter/instrumentation'
62
+
59
63
  # port is the port that will provide the /metrics route
60
64
  server = PrometheusExporter::Server::WebServer.new port: 12345
61
65
  server.start
62
66
 
67
+ # wire up a default local client
68
+ PrometheusExporter::Client.default = PrometheusExporter::LocalClient.new(collector: server.collector)
69
+
70
+ # this ensures basic process instrumentation metrics are added such as RSS and Ruby metrics
71
+ PrometheusExporter::Instrumentation::Process.start
72
+
63
73
  gauge = PrometheusExporter::Metric::Gauge.new("rss", "used RSS for process")
64
74
  counter = PrometheusExporter::Metric::Counter.new("web_requests", "number of web requests")
65
75
  summary = PrometheusExporter::Metric::Summary.new("page_load_time", "time it took to load page")
@@ -3,197 +3,213 @@
3
3
  require 'socket'
4
4
  require 'thread'
5
5
 
6
- class PrometheusExporter::Client
6
+ module PrometheusExporter
7
+
8
+ class Client
9
+ class RemoteMetric
10
+ def initialize(name:, help:, type:, client:)
11
+ @name = name
12
+ @help = help
13
+ @client = client
14
+ @type = type
15
+ end
7
16
 
8
- class RemoteMetric
9
- def initialize(name:, help:, type:, client:)
10
- @name = name
11
- @help = help
12
- @client = client
13
- @type = type
14
- end
17
+ def standard_values(value, keys, prometheus_exporter_action = nil)
18
+ values = {
19
+ type: @type,
20
+ help: @help,
21
+ name: @name,
22
+ keys: keys,
23
+ value: value
24
+ }
25
+ values[:prometheus_exporter_action] = prometheus_exporter_action if prometheus_exporter_action
26
+ values
27
+ end
15
28
 
16
- def standard_values(value, keys, prometheus_exporter_action = nil)
17
- values = {
18
- type: @type,
19
- help: @help,
20
- name: @name,
21
- keys: keys,
22
- value: value
23
- }
24
- values[:prometheus_exporter_action] = prometheus_exporter_action if prometheus_exporter_action
25
- values
26
- end
29
+ def observe(value = 1, keys = nil)
30
+ @client.send_json(standard_values(value, keys))
31
+ end
32
+
33
+ def increment(keys = nil, value = 1)
34
+ @client.send_json(standard_values(value, keys, :increment))
35
+ end
36
+
37
+ def decrement(keys = nil, value = 1)
38
+ @client.send_json(standard_values(value, keys, :decrement))
39
+ end
27
40
 
28
- def observe(value = 1, keys = nil)
29
- @client.send_json(standard_values(value, keys))
30
41
  end
31
42
 
32
- def increment(keys = nil, value = 1)
33
- @client.send_json(standard_values(value, keys, :increment))
43
+ def self.default
44
+ @default ||= new
34
45
  end
35
46
 
36
- def decrement(keys = nil, value = 1)
37
- @client.send_json(standard_values(value, keys, :decrement))
47
+ def self.default=(client)
48
+ @default = client
38
49
  end
39
50
 
40
- end
51
+ MAX_SOCKET_AGE = 25
52
+ MAX_QUEUE_SIZE = 10_000
41
53
 
42
- def self.default
43
- @default ||= new
44
- end
54
+ def initialize(host: 'localhost', port: PrometheusExporter::DEFAULT_PORT, max_queue_size: nil, thread_sleep: 0.5, json_serializer: nil, custom_labels: nil)
55
+ @metrics = []
45
56
 
46
- def self.default=(client)
47
- @default = client
48
- end
57
+ @queue = Queue.new
58
+ @socket = nil
59
+ @socket_started = nil
49
60
 
50
- MAX_SOCKET_AGE = 25
51
- MAX_QUEUE_SIZE = 10_000
61
+ max_queue_size ||= MAX_QUEUE_SIZE
62
+ max_queue_size = max_queue_size.to_i
52
63
 
53
- def initialize(host: 'localhost', port: PrometheusExporter::DEFAULT_PORT, max_queue_size: nil, thread_sleep: 0.5, json_serializer: nil, custom_labels: nil)
54
- @metrics = []
64
+ if max_queue_size.to_i <= 0
65
+ raise ArgumentError, "max_queue_size must be larger than 0"
66
+ end
55
67
 
56
- @queue = Queue.new
57
- @socket = nil
58
- @socket_started = nil
68
+ @max_queue_size = max_queue_size
69
+ @host = host
70
+ @port = port
71
+ @worker_thread = nil
72
+ @mutex = Mutex.new
73
+ @thread_sleep = thread_sleep
59
74
 
60
- max_queue_size ||= MAX_QUEUE_SIZE
61
- max_queue_size = max_queue_size.to_i
75
+ @json_serializer = json_serializer == :oj ? PrometheusExporter::OjCompat : JSON
62
76
 
63
- if max_queue_size.to_i <= 0
64
- raise ArgumentError, "max_queue_size must be larger than 0"
77
+ @custom_labels = custom_labels
65
78
  end
66
79
 
67
- @max_queue_size = max_queue_size
68
- @host = host
69
- @port = port
70
- @worker_thread = nil
71
- @mutex = Mutex.new
72
- @thread_sleep = thread_sleep
73
-
74
- @json_serializer = json_serializer == :oj ? PrometheusExporter::OjCompat : JSON
75
-
76
- @custom_labels = custom_labels
77
- end
78
-
79
- def custom_labels=(custom_labels)
80
- @custom_labels = custom_labels
81
- end
82
-
83
- def register(type, name, help)
84
- metric = RemoteMetric.new(type: type, name: name, help: help, client: self)
85
- @metrics << metric
86
- metric
87
- end
80
+ def custom_labels=(custom_labels)
81
+ @custom_labels = custom_labels
82
+ end
88
83
 
89
- def send_json(obj)
90
- payload = @custom_labels.nil? ? obj : obj.merge(custom_labels: @custom_labels)
91
- send(@json_serializer.dump(payload))
92
- end
84
+ def register(type, name, help)
85
+ metric = RemoteMetric.new(type: type, name: name, help: help, client: self)
86
+ @metrics << metric
87
+ metric
88
+ end
93
89
 
94
- def send(str)
95
- @queue << str
96
- if @queue.length > @max_queue_size
97
- STDERR.puts "Prometheus Exporter client is dropping message cause queue is full"
98
- @queue.pop
90
+ def send_json(obj)
91
+ payload = @custom_labels.nil? ? obj : obj.merge(custom_labels: @custom_labels)
92
+ send(@json_serializer.dump(payload))
99
93
  end
100
94
 
101
- ensure_worker_thread!
102
- end
95
+ def send(str)
96
+ @queue << str
97
+ if @queue.length > @max_queue_size
98
+ STDERR.puts "Prometheus Exporter client is dropping message cause queue is full"
99
+ @queue.pop
100
+ end
103
101
 
104
- def process_queue
105
- while @queue.length > 0
106
- ensure_socket!
102
+ ensure_worker_thread!
103
+ end
107
104
 
108
- begin
109
- message = @queue.pop
110
- @socket.write(message.bytesize.to_s(16).upcase)
111
- @socket.write("\r\n")
112
- @socket.write(message)
113
- @socket.write("\r\n")
114
- rescue => e
115
- STDERR.puts "Prometheus Exporter is dropping a message: #{e}"
116
- @socket = nil
117
- raise
105
+ def process_queue
106
+ while @queue.length > 0
107
+ ensure_socket!
108
+
109
+ begin
110
+ message = @queue.pop
111
+ @socket.write(message.bytesize.to_s(16).upcase)
112
+ @socket.write("\r\n")
113
+ @socket.write(message)
114
+ @socket.write("\r\n")
115
+ rescue => e
116
+ STDERR.puts "Prometheus Exporter is dropping a message: #{e}"
117
+ @socket = nil
118
+ raise
119
+ end
118
120
  end
119
121
  end
120
- end
121
122
 
122
- def stop
123
- @mutex.synchronize do
124
- @worker_thread&.kill
125
- while @worker_thread.alive?
126
- sleep 0.001
123
+ def stop
124
+ @mutex.synchronize do
125
+ @worker_thread&.kill
126
+ while @worker_thread.alive?
127
+ sleep 0.001
128
+ end
129
+ @worker_thread = nil
127
130
  end
128
- @worker_thread = nil
129
- end
130
131
 
131
- close_socket!
132
- end
132
+ close_socket!
133
+ end
133
134
 
134
- private
135
+ private
135
136
 
136
- def worker_loop
137
- close_socket_if_old!
138
- process_queue
139
- rescue => e
140
- STDERR.puts "Prometheus Exporter, failed to send message #{e}"
141
- end
137
+ def worker_loop
138
+ close_socket_if_old!
139
+ process_queue
140
+ rescue => e
141
+ STDERR.puts "Prometheus Exporter, failed to send message #{e}"
142
+ end
142
143
 
143
- def ensure_worker_thread!
144
- unless @worker_thread&.alive?
145
- @mutex.synchronize do
146
- return if @worker_thread&.alive?
144
+ def ensure_worker_thread!
145
+ unless @worker_thread&.alive?
146
+ @mutex.synchronize do
147
+ return if @worker_thread&.alive?
147
148
 
148
- @worker_thread = Thread.new do
149
- while true
150
- worker_loop
151
- sleep @thread_sleep
149
+ @worker_thread = Thread.new do
150
+ while true
151
+ worker_loop
152
+ sleep @thread_sleep
153
+ end
152
154
  end
153
155
  end
154
156
  end
155
157
  end
156
- end
157
158
 
158
- def close_socket!
159
- begin
160
- if @socket
161
- @socket.write("0\r\n")
159
+ def close_socket!
160
+ begin
161
+ if @socket
162
+ @socket.write("0\r\n")
163
+ @socket.write("\r\n")
164
+ @socket.flush
165
+ @socket.close
166
+ end
167
+ rescue Errno::EPIPE
168
+ end
169
+
170
+ @socket = nil
171
+ @socket_started = nil
172
+ end
173
+
174
+ def close_socket_if_old!
175
+ if @socket && ((@socket_started + MAX_SOCKET_AGE) < Time.now.to_f)
176
+ close_socket!
177
+ end
178
+ end
179
+
180
+ def ensure_socket!
181
+ close_socket_if_old!
182
+ if !@socket
183
+ @socket = TCPSocket.new @host, @port
184
+ @socket.write("POST /send-metrics HTTP/1.1\r\n")
185
+ @socket.write("Transfer-Encoding: chunked\r\n")
186
+ @socket.write("Host: #{@host}\r\n")
187
+ @socket.write("Connection: Close\r\n")
188
+ @socket.write("Content-Type: application/octet-stream\r\n")
162
189
  @socket.write("\r\n")
163
- @socket.flush
164
- @socket.close
190
+ @socket_started = Time.now.to_f
165
191
  end
166
- rescue Errno::EPIPE
192
+
193
+ nil
194
+ rescue
195
+ @socket = nil
196
+ @socket_started = nil
197
+ raise
167
198
  end
168
199
 
169
- @socket = nil
170
- @socket_started = nil
171
200
  end
172
201
 
173
- def close_socket_if_old!
174
- if @socket && ((@socket_started + MAX_SOCKET_AGE) < Time.now.to_f)
175
- close_socket!
202
+ class LocalClient < Client
203
+ attr_reader :collector
204
+
205
+ def initialize(collector:, json_serializer: nil, custom_labels: nil)
206
+ @collector = collector
207
+ super(json_serializer: json_serializer, custom_labels: custom_labels)
176
208
  end
177
- end
178
209
 
179
- def ensure_socket!
180
- close_socket_if_old!
181
- if !@socket
182
- @socket = TCPSocket.new @host, @port
183
- @socket.write("POST /send-metrics HTTP/1.1\r\n")
184
- @socket.write("Transfer-Encoding: chunked\r\n")
185
- @socket.write("Host: #{@host}\r\n")
186
- @socket.write("Connection: Close\r\n")
187
- @socket.write("Content-Type: application/octet-stream\r\n")
188
- @socket.write("\r\n")
189
- @socket_started = Time.now.to_f
190
- end
191
-
192
- nil
193
- rescue
194
- @socket = nil
195
- @socket_started = nil
196
- raise
210
+ def send(json)
211
+ @collector.process(json)
212
+ end
197
213
  end
198
214
 
199
215
  end
@@ -1,10 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # collects stats from currently running process
2
4
  module PrometheusExporter::Instrumentation
3
5
  class Process
4
6
  def self.start(client: nil, type: "ruby", frequency: 30)
5
7
  process_collector = new(type)
6
8
  client ||= PrometheusExporter::Client.default
7
- Thread.new do
9
+
10
+ stop if @thread
11
+
12
+ @thread = Thread.new do
8
13
  while true
9
14
  begin
10
15
  metric = process_collector.collect
@@ -18,6 +23,13 @@ module PrometheusExporter::Instrumentation
18
23
  end
19
24
  end
20
25
 
26
+ def self.stop
27
+ if t = @thread
28
+ t.kill
29
+ @thread = nil
30
+ end
31
+ end
32
+
21
33
  def initialize(type)
22
34
  @type = type
23
35
  end
@@ -2,6 +2,5 @@ require_relative "instrumentation/process"
2
2
  require_relative "instrumentation/method_profiler"
3
3
  require_relative "instrumentation/sidekiq"
4
4
  require_relative "instrumentation/delayed_job"
5
- require_relative "instrumentation/global"
6
5
  require_relative "instrumentation/puma"
7
6
  require_relative "instrumentation/hutch"
@@ -3,22 +3,6 @@
3
3
  module PrometheusExporter::Server
4
4
 
5
5
  class Collector < CollectorBase
6
- MAX_PROCESS_METRIC_AGE = 60
7
- PROCESS_GAUGES = {
8
- heap_free_slots: "Free ruby heap slots.",
9
- heap_live_slots: "Used ruby heap slots.",
10
- v8_heap_size: "Total JavaScript V8 heap size (bytes).",
11
- v8_used_heap_size: "Total used JavaScript V8 heap size (bytes).",
12
- v8_physical_size: "Physical size consumed by V8 heaps.",
13
- v8_heap_count: "Number of V8 contexts running.",
14
- rss: "Total RSS used by process.",
15
- }
16
-
17
- PROCESS_COUNTERS = {
18
- major_gc_ops_total: "Major GC operations by process.",
19
- minor_gc_ops_total: "Minor GC operations by process.",
20
- allocated_objects_total: "Total number of allocated objects by process.",
21
- }
22
6
 
23
7
  def initialize(json_serializer: nil)
24
8
  @process_metrics = []
@@ -39,7 +23,10 @@ module PrometheusExporter::Server
39
23
  end
40
24
 
41
25
  def process(str)
42
- obj = @json_serializer.parse(str)
26
+ process_hash(@json_serializer.parse(str))
27
+ end
28
+
29
+ def process_hash(obj)
43
30
  @mutex.synchronize do
44
31
  if collector = @collectors[obj["type"]]
45
32
  collector.collect(obj)
@@ -1,3 +1,3 @@
1
1
  module PrometheusExporter
2
- VERSION = "0.4.3"
2
+ VERSION = "0.4.4"
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.3
4
+ version: 0.4.4
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-02-11 00:00:00.000000000 Z
11
+ date: 2019-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -162,7 +162,6 @@ files:
162
162
  - lib/prometheus_exporter/client.rb
163
163
  - lib/prometheus_exporter/instrumentation.rb
164
164
  - lib/prometheus_exporter/instrumentation/delayed_job.rb
165
- - lib/prometheus_exporter/instrumentation/global.rb
166
165
  - lib/prometheus_exporter/instrumentation/hutch.rb
167
166
  - lib/prometheus_exporter/instrumentation/method_profiler.rb
168
167
  - lib/prometheus_exporter/instrumentation/process.rb
File without changes