railswatch_gem 0.1.2 → 0.1.4
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/lib/railswatch_gem/instrumentation/cache_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/commands_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/errors_instrumenter.rb +16 -4
- data/lib/railswatch_gem/instrumentation/jobs_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/logs_instrumenter.rb +79 -54
- data/lib/railswatch_gem/instrumentation/mail_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/notifications_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/outgoing_requests_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/queries_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/requests_instrumenter.rb +1 -1
- data/lib/railswatch_gem/instrumentation/scheduled_tasks_instrumenter.rb +1 -1
- data/lib/railswatch_gem/version.rb +1 -1
- 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: b46c253056a39e43ac5a606710eba79ec8685088111637d802580d3fa9d66388
|
|
4
|
+
data.tar.gz: 79146492b64604e69b19909338a0bf42892b13410b7ee49f9470715c4e8f5615
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc4617eb9907496f98e26384db7477fd0a10ffab8dd29462614436e9f284d50fed7c538b7dad3c1ac08cc94be9be952275e2c8dff6129c8ee03267fac45efe32
|
|
7
|
+
data.tar.gz: e29e08b277c75b8512290d734eb0cd9f3e3b16b112060019b12b01592dc8067d070387636e45b99e38feaaea9b13064e5e81d053f0524eaf7ad39644e8cb61a7
|
|
@@ -23,7 +23,19 @@ module RailswatchGem
|
|
|
23
23
|
# 1. Infinite Loop Protection
|
|
24
24
|
return if error.class.name.start_with?("RailswatchGem::")
|
|
25
25
|
|
|
26
|
-
# 2.
|
|
26
|
+
# 2. Capture Backtrace Smartly
|
|
27
|
+
# If error.backtrace is nil (un-raised exception), use the current caller.
|
|
28
|
+
raw_trace = error.backtrace || caller
|
|
29
|
+
|
|
30
|
+
# Clean the trace to remove framework noise (gems, rails internals)
|
|
31
|
+
# This ensures we see the User's code, not the Gem's code.
|
|
32
|
+
clean_trace = if defined?(::Rails.backtrace_cleaner)
|
|
33
|
+
::Rails.backtrace_cleaner.clean(raw_trace)
|
|
34
|
+
else
|
|
35
|
+
raw_trace
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# 3. Context Correlation
|
|
27
39
|
request_id = context[:request_id] || Thread.current[:railswatch_request_id]
|
|
28
40
|
|
|
29
41
|
data = {
|
|
@@ -33,10 +45,10 @@ module RailswatchGem
|
|
|
33
45
|
# Exception Details
|
|
34
46
|
class: error.class.name,
|
|
35
47
|
message: error.message,
|
|
36
|
-
# Limit backtrace to save bandwidth
|
|
37
|
-
backtrace: (error.backtrace || []).first(25),
|
|
38
48
|
|
|
39
|
-
|
|
49
|
+
backtrace: clean_trace.first(25),
|
|
50
|
+
|
|
51
|
+
# Rails Context
|
|
40
52
|
handled: handled,
|
|
41
53
|
severity: severity,
|
|
42
54
|
source: source,
|
|
@@ -13,72 +13,97 @@ module RailswatchGem
|
|
|
13
13
|
def start
|
|
14
14
|
return unless defined?(::Rails) && ::Rails.logger
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
# The "Sidecar" Pattern:
|
|
17
|
+
# Create a dedicated logger for Railswatch and broadcast to it.
|
|
18
|
+
railswatch_logger = RemoteLogger.new(@client)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
if defined?(::ActiveSupport::BroadcastLogger) && ::Rails.logger.is_a?(::ActiveSupport::BroadcastLogger)
|
|
21
|
+
# Rails 7.1+: Native Broadcast
|
|
22
|
+
::Rails.logger.broadcast_to(railswatch_logger)
|
|
23
|
+
elsif defined?(::ActiveSupport::Logger) && ::ActiveSupport::Logger.respond_to?(:broadcast)
|
|
24
|
+
# Rails 6.0 - 7.0: ActiveSupport Broadcast
|
|
25
|
+
::Rails.logger.extend(::ActiveSupport::Logger.broadcast(railswatch_logger))
|
|
26
|
+
else
|
|
27
|
+
# Fallback: Manual Interceptor (This is what your spec hits)
|
|
28
|
+
attach_legacy_interceptor(::Rails.logger, railswatch_logger)
|
|
29
|
+
end
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
private
|
|
24
33
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
define_method(:_railswatch_client) { client }
|
|
28
|
-
private :_railswatch_client
|
|
34
|
+
def attach_legacy_interceptor(target_logger, remote_logger)
|
|
35
|
+
return if target_logger.respond_to?(:_railswatch_instrumented?)
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
interceptor = Module.new do
|
|
38
|
+
define_method(:add) do |severity, message = nil, progname = nil, &block|
|
|
39
|
+
# FIX: Check the main logger's level BEFORE forwarding.
|
|
40
|
+
# 'level' here refers to target_logger.level
|
|
41
|
+
if severity < level
|
|
42
|
+
return super(severity, message, progname, &block)
|
|
33
43
|
end
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if log_message.nil?
|
|
38
|
-
if block_given?
|
|
39
|
-
log_message = yield
|
|
40
|
-
else
|
|
41
|
-
log_message = progname
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# INFINITE LOOP PROTECTION
|
|
46
|
-
unless log_message.to_s.include?("[Railswatch]")
|
|
47
|
-
request_id = Thread.current[:railswatch_request_id]
|
|
48
|
-
|
|
49
|
-
_railswatch_client.record({
|
|
50
|
-
event_type: "log",
|
|
51
|
-
timestamp: Time.now.utc.iso8601(6),
|
|
52
|
-
severity: format_severity_level(severity),
|
|
53
|
-
message: log_message.to_s,
|
|
54
|
-
progname: progname,
|
|
55
|
-
request_id: request_id
|
|
56
|
-
})
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
super(severity, log_message, nil)
|
|
60
|
-
rescue => e
|
|
61
|
-
# Fail safe: don't crash the app if logging fails
|
|
62
|
-
$stderr.puts "RailswatchGem: LogsInstrumenter error: #{e.message}"
|
|
63
|
-
super
|
|
64
|
-
end
|
|
65
|
-
end
|
|
45
|
+
# Forward to our remote logger logic (safe, won't crash)
|
|
46
|
+
remote_logger.add(severity, message, progname, &block)
|
|
66
47
|
|
|
67
|
-
|
|
68
|
-
|
|
48
|
+
# Proceed with original logging
|
|
49
|
+
super(severity, message, progname, &block)
|
|
69
50
|
end
|
|
70
51
|
|
|
71
|
-
|
|
52
|
+
def _railswatch_instrumented?; true; end
|
|
53
|
+
end
|
|
72
54
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
55
|
+
target_logger.extend(interceptor)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# --- Inner Class: The Actual Logger Logic ---
|
|
59
|
+
class RemoteLogger < ::Logger
|
|
60
|
+
def initialize(client)
|
|
61
|
+
@client = client
|
|
62
|
+
super(nil) # No IO output
|
|
63
|
+
self.level = DEBUG # Capture everything sent to us (filtering happens upstream)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def add(severity, message = nil, progname = nil, &block)
|
|
67
|
+
# 1. Message Resolution
|
|
68
|
+
content = message || (block&.call) || progname
|
|
69
|
+
|
|
70
|
+
# 2. Guard Clauses
|
|
71
|
+
return true if content.nil?
|
|
72
|
+
|
|
73
|
+
str_message = content.to_s.strip
|
|
74
|
+
return true if str_message.empty?
|
|
75
|
+
return true if str_message.include?("[Railswatch]")
|
|
76
|
+
|
|
77
|
+
# 3. Record
|
|
78
|
+
record_log(severity, str_message, progname)
|
|
79
|
+
|
|
80
|
+
true
|
|
81
|
+
rescue => e
|
|
82
|
+
$stderr.puts "RailswatchGem: Logs error: #{e.message}"
|
|
83
|
+
true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def record_log(severity, message, progname)
|
|
89
|
+
@client.record({
|
|
90
|
+
event_type: "log",
|
|
91
|
+
timestamp: Time.now.utc.iso8601(6),
|
|
92
|
+
severity: format_severity_level(severity),
|
|
93
|
+
message: message,
|
|
94
|
+
progname: progname,
|
|
95
|
+
request_id: Thread.current[:railswatch_request_id]
|
|
96
|
+
})
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def format_severity_level(severity)
|
|
100
|
+
case severity
|
|
101
|
+
when 0, ::Logger::DEBUG then "DEBUG"
|
|
102
|
+
when 1, ::Logger::INFO then "INFO"
|
|
103
|
+
when 2, ::Logger::WARN then "WARN"
|
|
104
|
+
when 3, ::Logger::ERROR then "ERROR"
|
|
105
|
+
when 4, ::Logger::FATAL then "FATAL"
|
|
106
|
+
else "UNKNOWN"
|
|
82
107
|
end
|
|
83
108
|
end
|
|
84
109
|
end
|
|
@@ -38,7 +38,7 @@ module RailswatchGem
|
|
|
38
38
|
event_type: "query",
|
|
39
39
|
|
|
40
40
|
# Without this, the query logs might look 0ms off from the request logs.
|
|
41
|
-
timestamp: Time.at(event.
|
|
41
|
+
timestamp: Time.at(event.time).utc.iso8601(6),
|
|
42
42
|
|
|
43
43
|
# Query Details
|
|
44
44
|
name: name || "SQL",
|