unified_logger 0.1.5 → 0.1.6
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/unified_logger/job_logger.rb +40 -20
- data/lib/unified_logger/logger.rb +76 -11
- data/lib/unified_logger/request_logger.rb +4 -3
- data/lib/unified_logger/sidekiq.rb +40 -0
- data/lib/unified_logger/version.rb +1 -1
- data/lib/unified_logger.rb +3 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dac24933499290c1a3703ae8da09aaeaf46e8096e68043ce1ba4618f3b61435a
|
|
4
|
+
data.tar.gz: 3876aef726012b9a428a37a951ddd515126538686f91cc793bef629e9f13f5d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4bc1ef83dd6f6be2cce82a64226de3fcef60bff86728a136497eacd396b4991b0260c8740126b21e32336c2e4c42d1c821d9739141b4bf8d7783f7d9a287a9fa
|
|
7
|
+
data.tar.gz: a0e0a7d4b2b6b3907d1c73e6ee569703fa66ec56eda323efd3823563e4396151407bdda27997188b7bfcb912e54f451295d30b6c5874f594c9925669b8527771
|
|
@@ -1,41 +1,61 @@
|
|
|
1
1
|
module UnifiedLogger
|
|
2
2
|
class JobLogger
|
|
3
|
-
DEFAULT_MAX_RETRIES = 5
|
|
4
|
-
|
|
5
3
|
class << self
|
|
6
|
-
def log(
|
|
4
|
+
def log(class_name:, id: nil, queue: nil, params: nil,
|
|
5
|
+
enqueued_at: nil, retry_count: 0, max_retries: nil, **extra)
|
|
6
|
+
started = UnifiedLogger.current_time
|
|
7
7
|
yield
|
|
8
8
|
ensure
|
|
9
|
-
|
|
9
|
+
if UnifiedLogger.current_logger.is_a?(UnifiedLogger::Logger)
|
|
10
|
+
write_log(class_name: class_name, id: id, queue: queue, params: params,
|
|
11
|
+
enqueued_at: enqueued_at, retry_count: retry_count,
|
|
12
|
+
max_retries: max_retries, started: started, **extra)
|
|
13
|
+
end
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
private
|
|
13
17
|
|
|
14
|
-
def
|
|
18
|
+
def write_log(class_name:, id:, queue:, params:, enqueued_at:,
|
|
19
|
+
retry_count:, max_retries:, started:, **extra)
|
|
20
|
+
enqueued_time = parse_time(enqueued_at)
|
|
21
|
+
|
|
15
22
|
log = {
|
|
16
|
-
log_type:
|
|
17
|
-
timestamp:
|
|
18
|
-
class_name:
|
|
19
|
-
id:
|
|
20
|
-
queue:
|
|
21
|
-
params:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
log_type: :job,
|
|
24
|
+
timestamp: UnifiedLogger.formatted_time,
|
|
25
|
+
class_name: class_name,
|
|
26
|
+
id: id,
|
|
27
|
+
queue: queue,
|
|
28
|
+
params: params,
|
|
29
|
+
retry_count: retry_count,
|
|
30
|
+
enqueued_at: enqueued_at,
|
|
31
|
+
duration: started ? UnifiedLogger.current_time - started : 0,
|
|
32
|
+
queue_duration: enqueued_time && started ? started - enqueued_time : nil,
|
|
33
|
+
thread_id: Thread.current.object_id,
|
|
34
|
+
process_id: Process.pid
|
|
27
35
|
}
|
|
28
|
-
log
|
|
36
|
+
log.merge!(extra) if extra.any?
|
|
37
|
+
log.compact!
|
|
38
|
+
|
|
39
|
+
log[:logs] = Logger.fetch_and_reset_logs if Logger.logs.any?
|
|
40
|
+
log.merge!(Logger.fetch_and_reset_extra_log_fields) if Logger.extra_log_fields.any?
|
|
29
41
|
|
|
30
42
|
if $!
|
|
31
|
-
log[:exception] =
|
|
32
|
-
log[:status] =
|
|
43
|
+
log[:exception] = Logger.format_exception($!)
|
|
44
|
+
log[:status] = max_retries && retry_count < max_retries ? :warn : :error
|
|
33
45
|
else
|
|
34
46
|
log[:status] = :ok
|
|
35
47
|
end
|
|
36
48
|
|
|
37
49
|
UnifiedLogger.transform_job_log_callable&.call(log)
|
|
38
|
-
|
|
50
|
+
Logger.write_log(log)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def parse_time(value)
|
|
54
|
+
case value
|
|
55
|
+
when Numeric then Time.at(value).utc
|
|
56
|
+
when String then Time.parse(value)
|
|
57
|
+
when Time, ActiveSupport::TimeWithZone then value
|
|
58
|
+
end
|
|
39
59
|
end
|
|
40
60
|
end
|
|
41
61
|
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
module UnifiedLogger
|
|
2
2
|
class Logger < ::Logger
|
|
3
|
-
|
|
3
|
+
LOGS = Concurrent::ThreadLocalVar.new([])
|
|
4
|
+
EXTRA_LOG_FIELDS = Concurrent::ThreadLocalVar.new({})
|
|
5
|
+
NOTE = 1.5
|
|
4
6
|
SEVERITY_LEVELS = {
|
|
5
7
|
debug: ::Logger::DEBUG,
|
|
6
8
|
info: ::Logger::INFO,
|
|
9
|
+
note: NOTE,
|
|
7
10
|
warn: ::Logger::WARN,
|
|
8
11
|
error: ::Logger::ERROR,
|
|
9
12
|
fatal: ::Logger::FATAL,
|
|
@@ -17,6 +20,14 @@ module UnifiedLogger
|
|
|
17
20
|
self.formatter = proc {}
|
|
18
21
|
end
|
|
19
22
|
|
|
23
|
+
def level=(severity)
|
|
24
|
+
if severity == :note
|
|
25
|
+
@level = NOTE
|
|
26
|
+
else
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
20
31
|
def debug(message = nil, &block)
|
|
21
32
|
message = block.call if message.nil? && block
|
|
22
33
|
add(::Logger::DEBUG, message)
|
|
@@ -27,6 +38,11 @@ module UnifiedLogger
|
|
|
27
38
|
add(::Logger::INFO, message)
|
|
28
39
|
end
|
|
29
40
|
|
|
41
|
+
def note(message = nil, &block)
|
|
42
|
+
message = block.call if message.nil? && block
|
|
43
|
+
add(NOTE, message)
|
|
44
|
+
end
|
|
45
|
+
|
|
30
46
|
def warn(message = nil, &block)
|
|
31
47
|
message = block.call if message.nil? && block
|
|
32
48
|
add(::Logger::WARN, message)
|
|
@@ -57,18 +73,33 @@ module UnifiedLogger
|
|
|
57
73
|
end
|
|
58
74
|
|
|
59
75
|
class << self
|
|
60
|
-
def
|
|
61
|
-
|
|
76
|
+
def logs
|
|
77
|
+
LOGS.value
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def add(hash)
|
|
81
|
+
EXTRA_LOG_FIELDS.value = EXTRA_LOG_FIELDS.value.merge(hash)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def extra_log_fields
|
|
85
|
+
EXTRA_LOG_FIELDS.value
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def fetch_and_reset_extra_log_fields
|
|
89
|
+
fields = extra_log_fields
|
|
90
|
+
EXTRA_LOG_FIELDS.value = {}
|
|
91
|
+
fields
|
|
62
92
|
end
|
|
63
93
|
|
|
64
94
|
def reset_thread_logs
|
|
65
|
-
|
|
95
|
+
LOGS.value = []
|
|
96
|
+
EXTRA_LOG_FIELDS.value = {}
|
|
66
97
|
end
|
|
67
98
|
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
99
|
+
def fetch_and_reset_logs
|
|
100
|
+
current = logs
|
|
101
|
+
LOGS.value = []
|
|
102
|
+
current
|
|
72
103
|
end
|
|
73
104
|
|
|
74
105
|
def trim(data)
|
|
@@ -107,8 +138,42 @@ module UnifiedLogger
|
|
|
107
138
|
formatter.present? ? formatter.call(filtered_log) : filtered_log.to_json
|
|
108
139
|
end
|
|
109
140
|
|
|
141
|
+
def write_log(log)
|
|
142
|
+
logger = UnifiedLogger.current_logger
|
|
143
|
+
max = UnifiedLogger.config[:max_log_size]
|
|
144
|
+
if log.inspect.length <= max || !log.key?(:logs)
|
|
145
|
+
logger.write(format(log))
|
|
146
|
+
else
|
|
147
|
+
entries = log.delete(:logs)
|
|
148
|
+
logger.write(format(log))
|
|
149
|
+
write_overflow_logs(log[:id], log[:log_type], entries, max, logger)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
110
153
|
private
|
|
111
154
|
|
|
155
|
+
def write_overflow_logs(id, log_type, entries, max, logger)
|
|
156
|
+
index = 1
|
|
157
|
+
group = []
|
|
158
|
+
|
|
159
|
+
entries.each do |entry|
|
|
160
|
+
candidate = group + [entry]
|
|
161
|
+
overflow = { id: id, log_type: log_type, index: index, logs: candidate }
|
|
162
|
+
|
|
163
|
+
if overflow.inspect.length > max && group.any?
|
|
164
|
+
logger.write(format({ id: id, log_type: log_type, index: index, logs: group }))
|
|
165
|
+
index += 1
|
|
166
|
+
group = [entry]
|
|
167
|
+
else
|
|
168
|
+
group = candidate
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
return if group.empty?
|
|
173
|
+
|
|
174
|
+
logger.write(format({ id: id, log_type: log_type, index: index, logs: group }))
|
|
175
|
+
end
|
|
176
|
+
|
|
112
177
|
def filter(content)
|
|
113
178
|
return content unless content.respond_to?(:each)
|
|
114
179
|
|
|
@@ -132,16 +197,16 @@ module UnifiedLogger
|
|
|
132
197
|
return true unless severity >= level
|
|
133
198
|
|
|
134
199
|
severity_symbol = SEVERITY_MAP[severity] || :unknown
|
|
135
|
-
|
|
200
|
+
append_log(severity_symbol, message)
|
|
136
201
|
end
|
|
137
202
|
|
|
138
203
|
private
|
|
139
204
|
|
|
140
|
-
def
|
|
205
|
+
def append_log(severity, message)
|
|
141
206
|
message = sanitize_log_message(message) if message.is_a?(String)
|
|
142
207
|
log_hash = { timestamp: UnifiedLogger.formatted_time, severity: severity, message: message }
|
|
143
208
|
|
|
144
|
-
|
|
209
|
+
LOGS.value = LOGS.value + [log_hash]
|
|
145
210
|
end
|
|
146
211
|
|
|
147
212
|
def sanitize_log_message(text)
|
|
@@ -13,7 +13,7 @@ module UnifiedLogger
|
|
|
13
13
|
if UnifiedLogger.current_logger.is_a?(UnifiedLogger::Logger) && !silenced?(env["REQUEST_PATH"])
|
|
14
14
|
log = build_log(started, env, status, headers, response)
|
|
15
15
|
UnifiedLogger.transform_request_log_callable&.call(log, env)
|
|
16
|
-
UnifiedLogger
|
|
16
|
+
UnifiedLogger::Logger.write_log(log)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -36,7 +36,7 @@ module UnifiedLogger
|
|
|
36
36
|
timestamp: UnifiedLogger.formatted_time,
|
|
37
37
|
id: env["action_dispatch.request_id"],
|
|
38
38
|
ip: env["action_dispatch.remote_ip"].to_s,
|
|
39
|
-
controller: path_parameters[:controller],
|
|
39
|
+
controller: path_parameters[:controller]&.camelize&.concat("Controller"),
|
|
40
40
|
action: path_parameters[:action],
|
|
41
41
|
request: {
|
|
42
42
|
path: env["REQUEST_PATH"],
|
|
@@ -56,7 +56,8 @@ module UnifiedLogger
|
|
|
56
56
|
duration: started ? UnifiedLogger.current_time - started : 0
|
|
57
57
|
}
|
|
58
58
|
log[:exception] = UnifiedLogger::Logger.format_exception($!) if $!.present?
|
|
59
|
-
log[:
|
|
59
|
+
log[:logs] = UnifiedLogger::Logger.fetch_and_reset_logs if UnifiedLogger::Logger.logs.any?
|
|
60
|
+
log.merge!(UnifiedLogger::Logger.fetch_and_reset_extra_log_fields) if UnifiedLogger::Logger.extra_log_fields.any?
|
|
60
61
|
|
|
61
62
|
log
|
|
62
63
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "unified_logger"
|
|
2
|
+
|
|
3
|
+
module UnifiedLogger
|
|
4
|
+
class SidekiqServerMiddleware
|
|
5
|
+
def call(job_instance, job_hash, queue)
|
|
6
|
+
UnifiedLogger::JobLogger.log(**attrs_from(job_instance, job_hash, queue)) { yield } # rubocop:disable Style/ExplicitBlockArgument
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def attrs_from(job_instance, job_hash, queue)
|
|
12
|
+
aj = job_hash.key?("wrapped") ? job_hash.dig("args", 0) : nil
|
|
13
|
+
retries = job_hash["retry"]
|
|
14
|
+
|
|
15
|
+
{
|
|
16
|
+
class_name: aj&.[]("job_class") || job_hash["wrapped"] || job_instance.class.name,
|
|
17
|
+
id: aj&.[]("job_id") || job_hash["jid"],
|
|
18
|
+
queue: queue,
|
|
19
|
+
params: aj&.[]("arguments") || job_hash["args"],
|
|
20
|
+
retry_count: job_hash["retry_count"].to_i,
|
|
21
|
+
max_retries: resolve_max_retries(retries),
|
|
22
|
+
enqueued_at: aj&.[]("enqueued_at") || job_hash["enqueued_at"]
|
|
23
|
+
}.compact
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def resolve_max_retries(retries)
|
|
27
|
+
return retries if retries.is_a?(Integer)
|
|
28
|
+
|
|
29
|
+
retries == false ? 0 : 25
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if defined?(Sidekiq)
|
|
35
|
+
Sidekiq.configure_server do |config|
|
|
36
|
+
config.server_middleware do |chain|
|
|
37
|
+
chain.add UnifiedLogger::SidekiqServerMiddleware
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/unified_logger.rb
CHANGED
|
@@ -20,6 +20,7 @@ module UnifiedLogger
|
|
|
20
20
|
|
|
21
21
|
DEFAULTS = {
|
|
22
22
|
max_log_field_size: 2048,
|
|
23
|
+
max_log_size: 10_000,
|
|
23
24
|
filter_params: %i[passw secret token crypt salt certificate otp ssn set-cookie http_authorization http_cookie pin],
|
|
24
25
|
auto_insert_middleware: true,
|
|
25
26
|
silence_paths: []
|
|
@@ -55,7 +56,8 @@ module UnifiedLogger
|
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
delegate :trim, :format, :format_exception,
|
|
58
|
-
:
|
|
59
|
+
:logs, :fetch_and_reset_logs, :reset_thread_logs,
|
|
60
|
+
:add, :extra_log_fields, :fetch_and_reset_extra_log_fields,
|
|
59
61
|
to: :"UnifiedLogger::Logger"
|
|
60
62
|
end
|
|
61
63
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: unified_logger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marcovecchio
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-03-
|
|
10
|
+
date: 2026-03-30 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: activesupport
|
|
@@ -75,6 +75,7 @@ files:
|
|
|
75
75
|
- lib/unified_logger/logger.rb
|
|
76
76
|
- lib/unified_logger/railtie.rb
|
|
77
77
|
- lib/unified_logger/request_logger.rb
|
|
78
|
+
- lib/unified_logger/sidekiq.rb
|
|
78
79
|
- lib/unified_logger/version.rb
|
|
79
80
|
homepage: https://github.com/marcovecchio/unified_logger
|
|
80
81
|
licenses:
|