puma-log_stats-codeur 0.1.1 → 0.1.2
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/README.md +5 -2
- data/lib/puma/log_stats/version.rb +1 -1
- data/lib/puma/log_stats.rb +0 -2
- data/lib/puma/plugin/log_stats.rb +20 -119
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7088c577694fb2913018a740122202a4ef2a27eaae1beed620b0a12fcf459059
|
4
|
+
data.tar.gz: 1e98c214093d2b80b5a214b554e2d004ffba39aeb24d205c018fccea8d074321
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 885dbee8b5d1f80f666f004d733487ed6f6dc809cefa5505309bc9f4bd266fb6cfaa85b505ed6f63ecab669b0aefab4c7754929a0d0912f5c7c2a0727a866ad9
|
7
|
+
data.tar.gz: 51d5bc462ff4c14dab1769a01b4a19f34e380e3f533fa769a78da3079b55090ade9c8f5d54a547d4058579c4e839ea492100e3339119323fbf36e9287e07a342
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# PumaLogStats
|
2
2
|
|
3
|
-
Puma plugin to log server stats
|
3
|
+
Puma plugin to log server stats to puma.log. It logs changes only and can raise Sentry issues when a threshold is reached.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -26,7 +26,10 @@ This plugin is loaded using Puma's plugin API. To enable, add a `plugin :log_sta
|
|
26
26
|
# config/puma.rb
|
27
27
|
|
28
28
|
plugin :log_stats
|
29
|
-
LogStats.
|
29
|
+
# LogStats.interval = 10
|
30
|
+
# LogStats.notify_change_with = :sentry # can be a Proc
|
31
|
+
# LogStats.warning_threshold = 0.7
|
32
|
+
# LogStats.critical_threshold = 0.85
|
30
33
|
```
|
31
34
|
|
32
35
|
## Development
|
data/lib/puma/log_stats.rb
CHANGED
@@ -8,11 +8,8 @@ module LogStats
|
|
8
8
|
attr_accessor :interval
|
9
9
|
LogStats.interval = 10
|
10
10
|
|
11
|
-
attr_accessor :
|
12
|
-
LogStats.
|
13
|
-
|
14
|
-
attr_accessor :alarm_notification_interval
|
15
|
-
LogStats.alarm_notification_interval = 60
|
11
|
+
attr_accessor :notify_change_with
|
12
|
+
LogStats.notify_change_with = :sentry
|
16
13
|
|
17
14
|
attr_accessor :warning_threshold
|
18
15
|
LogStats.warning_threshold = 0.7
|
@@ -34,8 +31,10 @@ module LogStats
|
|
34
31
|
@load_level = :normal
|
35
32
|
while @running
|
36
33
|
sleep LogStats.interval
|
34
|
+
@previous_status_message = @status_message
|
37
35
|
@stats = Puma.stats_hash
|
38
|
-
|
36
|
+
@status_message = status_message
|
37
|
+
log(@status_message) if @previous_status_message != @status_message
|
39
38
|
check_alarms
|
40
39
|
end
|
41
40
|
end
|
@@ -50,27 +49,31 @@ module LogStats
|
|
50
49
|
def threshold_reached(level, threshold)
|
51
50
|
return false if threads_load < threshold
|
52
51
|
|
53
|
-
|
54
|
-
@load_level = level if @load_level != level
|
52
|
+
change_level(level, "Puma threads load is greater than #{threshold * 100}% (#{max_threads - pool_capacity}/#{max_threads})")
|
55
53
|
true
|
56
54
|
end
|
57
55
|
|
58
56
|
def normal_load
|
59
|
-
|
57
|
+
change_level(:normal, "Puma threads load is back to normal values")
|
58
|
+
end
|
60
59
|
|
61
|
-
|
62
|
-
@load_level
|
60
|
+
def change_level(level, message)
|
61
|
+
return if @load_level == level
|
62
|
+
|
63
|
+
log("#{level.to_s.upcase}: #{message}")
|
64
|
+
notify(level, message)
|
65
|
+
@load_level = level
|
63
66
|
end
|
64
67
|
|
65
|
-
def
|
66
|
-
if
|
67
|
-
|
68
|
-
|
69
|
-
|
68
|
+
def notify(level, message)
|
69
|
+
if LogStats.notify_change_with == :sentry
|
70
|
+
Sentry.capture_message(message, level: level == :critical ? :error : level) if defined?(Sentry) && level != :normal
|
71
|
+
elsif LogStats.notify_change_with.respond_to?(:call)
|
72
|
+
LogStats.notify_change_with.call(level: level, message: message, threads_load: threads_load)
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
73
|
-
def
|
76
|
+
def status_message
|
74
77
|
if clustered?
|
75
78
|
"cluster: #{booted_workers}/#{workers} workers: #{running}/#{max_threads} threads, #{pool_capacity} available, #{backlog} backlog"
|
76
79
|
else
|
@@ -134,105 +137,3 @@ end
|
|
134
137
|
Puma::Plugin.create do
|
135
138
|
include LogStats
|
136
139
|
end
|
137
|
-
|
138
|
-
# require "puma"
|
139
|
-
# require "puma/plugin"
|
140
|
-
# require "json"
|
141
|
-
|
142
|
-
# # Puma plugin to log server stats whenever the number of
|
143
|
-
# # concurrent requests exceeds a configured threshold.
|
144
|
-
# module LogStats
|
145
|
-
# STAT_METHODS = %i[backlog running pool_capacity max_threads requests_count].freeze
|
146
|
-
|
147
|
-
# class << self
|
148
|
-
# # Minimum concurrent requests per process that will trigger logging server
|
149
|
-
# # stats, or nil to disable logging.
|
150
|
-
# # Default is the max number of threads in the server's thread pool.
|
151
|
-
# # If this attribute is a Proc, it will be re-evaluated each interval.
|
152
|
-
# attr_accessor :threshold
|
153
|
-
# LogStats.threshold = :max
|
154
|
-
|
155
|
-
# # Interval between logging attempts in seconds.
|
156
|
-
# attr_accessor :interval
|
157
|
-
# LogStats.interval = 1
|
158
|
-
|
159
|
-
# # Proc to filter backtraces.
|
160
|
-
# attr_accessor :backtrace_filter
|
161
|
-
# LogStats.backtrace_filter = ->(bt) { bt }
|
162
|
-
# end
|
163
|
-
|
164
|
-
# Puma::Plugin.create do
|
165
|
-
# attr_reader :launcher
|
166
|
-
|
167
|
-
# def start(launcher)
|
168
|
-
# @launcher = launcher
|
169
|
-
# launcher.events.register(:state) do |state|
|
170
|
-
# @state = state
|
171
|
-
# stats_logger_thread if state == :running
|
172
|
-
# end
|
173
|
-
|
174
|
-
# in_background { start }
|
175
|
-
# end
|
176
|
-
|
177
|
-
# private
|
178
|
-
|
179
|
-
# def stats_logger_thread
|
180
|
-
# Thread.new do
|
181
|
-
# if Thread.current.respond_to?(:name=)
|
182
|
-
# Thread.current.name = "puma stats logger"
|
183
|
-
# end
|
184
|
-
# start while @state == :running
|
185
|
-
# end
|
186
|
-
# end
|
187
|
-
|
188
|
-
# def start
|
189
|
-
# sleep LogStats.interval
|
190
|
-
# return unless server
|
191
|
-
|
192
|
-
# if should_log?
|
193
|
-
# stats = server_stats
|
194
|
-
# stats[:threads] = thread_backtraces
|
195
|
-
# stats[:gc] = GC.stat
|
196
|
-
# log stats.to_json
|
197
|
-
# end
|
198
|
-
# rescue => e
|
199
|
-
# log "LogStats failed: #{e}\n #{e.backtrace.join("\n ")}"
|
200
|
-
# end
|
201
|
-
|
202
|
-
# def log(str)
|
203
|
-
# launcher.log_writer.log str
|
204
|
-
# end
|
205
|
-
|
206
|
-
# # Save reference to Server object from the thread-local key.
|
207
|
-
# def server
|
208
|
-
# @server ||= Thread.list.map { |t| t[Puma::Server::ThreadLocalKey] }.compact.first
|
209
|
-
# end
|
210
|
-
|
211
|
-
# def server_stats
|
212
|
-
# STAT_METHODS.select(&server.method(:respond_to?))
|
213
|
-
# .map { |name| [name, server.send(name) || 0] }.to_h
|
214
|
-
# end
|
215
|
-
|
216
|
-
# # True if current server load meets configured threshold.
|
217
|
-
# def should_log?
|
218
|
-
# threshold = LogStats.threshold
|
219
|
-
# threshold = threshold.call if threshold.is_a?(Proc)
|
220
|
-
# threshold = server.max_threads if threshold == :max
|
221
|
-
# threshold && (server.max_threads - server.pool_capacity) >= threshold
|
222
|
-
# end
|
223
|
-
|
224
|
-
# def thread_backtraces
|
225
|
-
# worker_threads.map do |t|
|
226
|
-
# name = t.respond_to?(:name) ? t.name : thread.object_id.to_s(36)
|
227
|
-
# [name, LogStats.backtrace_filter.call(t.backtrace)]
|
228
|
-
# end.sort.to_h
|
229
|
-
# end
|
230
|
-
|
231
|
-
# # List all non-idle worker threads in the thread pool.
|
232
|
-
# def worker_threads
|
233
|
-
# server.instance_variable_get(:@thread_pool)
|
234
|
-
# .instance_variable_get(:@workers)
|
235
|
-
# .reject { |t| t.backtrace.first.match?(/thread_pool\.rb.*sleep/) }
|
236
|
-
# end
|
237
|
-
# end
|
238
|
-
# end
|