puma_metrics_engine 1.1.0 → 1.2.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ab335fa7843d45934fd97c5442b9bfd3a87006066b6f14ef99123a9316ab165
|
|
4
|
+
data.tar.gz: 7bd9134d5a436aecebd2a3f2a4073a5b51c46f3fb3d4a8b2391464e108326503
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c9f71532254eed460c8169a894c41e0ac03c7a089c37a133fc097d7632a0ab2bd2e282bbe84b7cd3ea667ea1adfa9f5a9cb3afc4aaaeb8d470107e5f403ab016
|
|
7
|
+
data.tar.gz: b704e4c376bdbdad8324b004c71ed20d176dbdda1febaaa63c6c411da33beee40cdb98460671dd8c558feb085a491602f2babc220d3ede42f2d77e90594b00d7
|
data/README.md
CHANGED
|
@@ -25,6 +25,12 @@ end
|
|
|
25
25
|
|
|
26
26
|
Access metrics at `/matrix` endpoint.
|
|
27
27
|
|
|
28
|
+
For debugging production issues, use `/debug` endpoint to check:
|
|
29
|
+
- Middleware registration status
|
|
30
|
+
- Redis connectivity
|
|
31
|
+
- Header presence
|
|
32
|
+
- Current data in Redis
|
|
33
|
+
|
|
28
34
|
## Response Format
|
|
29
35
|
|
|
30
36
|
```json
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PumaMetricsEngine
|
|
4
|
+
class DebugController < ActionController::Base
|
|
5
|
+
skip_before_action :verify_authenticity_token
|
|
6
|
+
|
|
7
|
+
def show
|
|
8
|
+
render json: {
|
|
9
|
+
timestamp: Time.current,
|
|
10
|
+
middleware: middleware_status,
|
|
11
|
+
redis: redis_status,
|
|
12
|
+
headers: sample_headers,
|
|
13
|
+
data: redis_data_summary,
|
|
14
|
+
environment: environment_info
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def middleware_status
|
|
21
|
+
middleware_stack = Rails.application.middleware.to_a.map(&:klass).map(&:name)
|
|
22
|
+
is_registered = middleware_stack.include?("PumaMetricsEngine::QueueTimeTracker")
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
registered: is_registered,
|
|
26
|
+
middleware_stack: middleware_stack,
|
|
27
|
+
note: is_registered ? "Middleware is registered" : "Middleware NOT found in stack"
|
|
28
|
+
}
|
|
29
|
+
rescue StandardError => e
|
|
30
|
+
{ error: e.message }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def redis_status
|
|
34
|
+
client = redis
|
|
35
|
+
client.ping
|
|
36
|
+
{
|
|
37
|
+
connected: true,
|
|
38
|
+
url: ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" },
|
|
39
|
+
keys: {
|
|
40
|
+
queue_times: client.exists?(MatrixController::QUEUE_TIMES_KEY),
|
|
41
|
+
request_timestamps: client.exists?(MatrixController::REQUESTS_KEY)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
rescue StandardError => e
|
|
45
|
+
{
|
|
46
|
+
connected: false,
|
|
47
|
+
error: e.message,
|
|
48
|
+
url: ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" }
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def redis_data_summary
|
|
53
|
+
client = redis
|
|
54
|
+
{
|
|
55
|
+
queue_times_count: client.zcard(MatrixController::QUEUE_TIMES_KEY),
|
|
56
|
+
request_timestamps_count: client.zcard(MatrixController::REQUESTS_KEY),
|
|
57
|
+
recent_queue_times: client.zrange(MatrixController::QUEUE_TIMES_KEY, -10, -1),
|
|
58
|
+
recent_timestamps: client.zrange(MatrixController::REQUESTS_KEY, -10, -1)
|
|
59
|
+
}
|
|
60
|
+
rescue StandardError => e
|
|
61
|
+
{ error: e.message }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def sample_headers
|
|
65
|
+
# Show what headers we're looking for
|
|
66
|
+
{
|
|
67
|
+
x_request_start: request.headers["X-Request-Start"],
|
|
68
|
+
http_x_request_start: request.headers["HTTP_X_REQUEST_START"],
|
|
69
|
+
all_x_headers: request.headers.select { |k, _| k.to_s.upcase.include?("X-REQUEST") },
|
|
70
|
+
note: "Check if X-Request-Start header is being sent by your load balancer"
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def environment_info
|
|
75
|
+
{
|
|
76
|
+
rails_env: Rails.env,
|
|
77
|
+
redis_url_set: ENV.key?("REDIS_URL"),
|
|
78
|
+
puma_defined: defined?(Puma)
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def redis
|
|
83
|
+
@redis ||= Redis.new(url: ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" })
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
data/config/routes.rb
CHANGED
|
@@ -14,6 +14,13 @@ module PumaMetricsEngine
|
|
|
14
14
|
request_start_time = extract_request_start_time(env)
|
|
15
15
|
process_start_time = Time.now.to_f
|
|
16
16
|
|
|
17
|
+
# Log header presence for debugging
|
|
18
|
+
if defined?(Rails)
|
|
19
|
+
header_value = env["HTTP_X_REQUEST_START"] || env["X-Request-Start"]
|
|
20
|
+
Rails.logger.debug("[QueueTimeTracker] X-Request-Start header: #{header_value.inspect}") if header_value
|
|
21
|
+
Rails.logger.debug("[QueueTimeTracker] No X-Request-Start header found") unless header_value
|
|
22
|
+
end
|
|
23
|
+
|
|
17
24
|
status, headers, response = @app.call(env)
|
|
18
25
|
|
|
19
26
|
# Calculate queue time if we have request start time
|
|
@@ -27,8 +34,10 @@ module PumaMetricsEngine
|
|
|
27
34
|
timestamp = process_start_time
|
|
28
35
|
# Store in Redis asynchronously to avoid blocking the request
|
|
29
36
|
store_metrics_async(timestamp, queue_time_ms)
|
|
37
|
+
Rails.logger.debug("[QueueTimeTracker] Stored queue time: #{queue_time_ms}ms") if defined?(Rails)
|
|
30
38
|
else
|
|
31
39
|
# Still track request timestamp even if queue time is invalid
|
|
40
|
+
Rails.logger.warn("[QueueTimeTracker] Invalid queue time: #{queue_time_ms}ms (rejected)") if defined?(Rails)
|
|
32
41
|
store_request_timestamp_async(process_start_time)
|
|
33
42
|
end
|
|
34
43
|
else
|
|
@@ -37,7 +46,8 @@ module PumaMetricsEngine
|
|
|
37
46
|
end
|
|
38
47
|
rescue StandardError => e
|
|
39
48
|
# Don't let tracking errors break the request
|
|
40
|
-
Rails.logger.error("QueueTimeTracker
|
|
49
|
+
Rails.logger.error("[QueueTimeTracker] Error: #{e.message}") if defined?(Rails)
|
|
50
|
+
Rails.logger.error("[QueueTimeTracker] Backtrace: #{e.backtrace.first(5).join("\n")}") if defined?(Rails)
|
|
41
51
|
end
|
|
42
52
|
|
|
43
53
|
[status, headers, response]
|
|
@@ -89,7 +99,8 @@ module PumaMetricsEngine
|
|
|
89
99
|
# Cleanup old data (older than TTL)
|
|
90
100
|
cleanup_old_data(redis_client)
|
|
91
101
|
rescue StandardError => e
|
|
92
|
-
Rails.logger.error("Failed to store
|
|
102
|
+
Rails.logger.error("[QueueTimeTracker] Failed to store metrics: #{e.message}") if defined?(Rails)
|
|
103
|
+
Rails.logger.error("[QueueTimeTracker] Redis error backtrace: #{e.backtrace.first(3).join("\n")}") if defined?(Rails)
|
|
93
104
|
end
|
|
94
105
|
end
|
|
95
106
|
end
|
|
@@ -101,7 +112,7 @@ module PumaMetricsEngine
|
|
|
101
112
|
redis_client.zadd(REQUESTS_KEY, timestamp, timestamp)
|
|
102
113
|
cleanup_old_data(redis_client)
|
|
103
114
|
rescue StandardError => e
|
|
104
|
-
Rails.logger.error("Failed to store request timestamp: #{e.message}") if defined?(Rails)
|
|
115
|
+
Rails.logger.error("[QueueTimeTracker] Failed to store request timestamp: #{e.message}") if defined?(Rails)
|
|
105
116
|
end
|
|
106
117
|
end
|
|
107
118
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: puma_metrics_engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Neeto
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-11-
|
|
11
|
+
date: 2025-11-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -146,6 +146,7 @@ extra_rdoc_files: []
|
|
|
146
146
|
files:
|
|
147
147
|
- LICENSE.txt
|
|
148
148
|
- README.md
|
|
149
|
+
- app/controllers/puma_metrics_engine/debug_controller.rb
|
|
149
150
|
- app/controllers/puma_metrics_engine/matrix_controller.rb
|
|
150
151
|
- config/routes.rb
|
|
151
152
|
- lib/puma_metrics_engine.rb
|