unified_logger 0.1.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 +7 -0
- data/lib/unified_logger/job_logger.rb +45 -0
- data/lib/unified_logger/logger.rb +143 -0
- data/lib/unified_logger/railtie.rb +7 -0
- data/lib/unified_logger/request_logger.rb +108 -0
- data/lib/unified_logger/version.rb +3 -0
- data/lib/unified_logger.rb +81 -0
- metadata +102 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2b1182b4653c380d8b35b55733c0ba47fa4c5eff722178765dfe6b2f1fddaf8c
|
|
4
|
+
data.tar.gz: 7b94cd76f7288dffa0004f69a57e633ffa2342cfb67969031e8822f02a96aab6
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 3a6090da5a5deb10ad56cf57c475342517dc854658bd23934b4a4c7bf247060cb0851a96af50698b8dd1ca268c8f2a147a4e7478df05931fd3cf0c7e2a3093f6
|
|
7
|
+
data.tar.gz: 23df148c3859f4e42f1646ddc94d774de39ed9908e74660035ebbe618f8b81d709d9fc5dbe96a0454d71ae4058c2df0ec2a65799d6d3e68caee49883d5d88b8e
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "English"
|
|
2
|
+
|
|
3
|
+
module UnifiedLogger
|
|
4
|
+
class JobLogger
|
|
5
|
+
DEFAULT_MAX_RETRIES = 5
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def log(job)
|
|
9
|
+
yield
|
|
10
|
+
ensure
|
|
11
|
+
log_execution(job) if UnifiedLogger.current_logger.is_a?(UnifiedLogger::Logger)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def log_execution(job)
|
|
17
|
+
log = {
|
|
18
|
+
log_type: :job,
|
|
19
|
+
class_name: job.class.name,
|
|
20
|
+
id: job.job_id,
|
|
21
|
+
queue: job.queue_name,
|
|
22
|
+
params: job.arguments,
|
|
23
|
+
executions_count: job.executions,
|
|
24
|
+
exception_executions: job.exception_executions,
|
|
25
|
+
enqueued_at: job.enqueued_at,
|
|
26
|
+
locale: job.locale,
|
|
27
|
+
duration: job.enqueued_at.present? ? UnifiedLogger.current_time - job.enqueued_at.in_time_zone : "unknown"
|
|
28
|
+
}
|
|
29
|
+
log[:custom] = UnifiedLogger::Logger.fetch_and_reset_custom_logs if UnifiedLogger::Logger.custom_logs.any?
|
|
30
|
+
|
|
31
|
+
if $ERROR_INFO
|
|
32
|
+
log[:exception] = UnifiedLogger::Logger.format_exception($ERROR_INFO)
|
|
33
|
+
log[:status] = job.executions >= DEFAULT_MAX_RETRIES ? :error : :warn
|
|
34
|
+
else
|
|
35
|
+
log[:status] = :ok
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
custom = {}
|
|
39
|
+
UnifiedLogger.transform_job_log_callable&.call(custom)
|
|
40
|
+
log.merge!(custom)
|
|
41
|
+
UnifiedLogger.current_logger.write(UnifiedLogger::Logger.format(log))
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module UnifiedLogger
|
|
2
|
+
class Logger < ::Logger
|
|
3
|
+
CUSTOM_LOGS = Concurrent::ThreadLocalVar.new([])
|
|
4
|
+
SEVERITY_LEVELS = {
|
|
5
|
+
debug: ::Logger::DEBUG,
|
|
6
|
+
info: ::Logger::INFO,
|
|
7
|
+
warn: ::Logger::WARN,
|
|
8
|
+
error: ::Logger::ERROR,
|
|
9
|
+
fatal: ::Logger::FATAL,
|
|
10
|
+
unknown: ::Logger::UNKNOWN
|
|
11
|
+
}.freeze
|
|
12
|
+
SEVERITY_MAP = SEVERITY_LEVELS.invert.freeze
|
|
13
|
+
|
|
14
|
+
def initialize(logging_device = $stdout, *)
|
|
15
|
+
super
|
|
16
|
+
@logging_device = logging_device
|
|
17
|
+
self.formatter = proc {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def debug(message = nil, params = {})
|
|
21
|
+
add(::Logger::DEBUG, message, params)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def info(message = nil, params = {})
|
|
25
|
+
add(::Logger::INFO, message, params)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def warn(message = nil, params = {})
|
|
29
|
+
add(::Logger::WARN, message, params)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def error(message = nil, params = {})
|
|
33
|
+
add(::Logger::ERROR, message, params)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def fatal(message = nil, params = {})
|
|
37
|
+
add(::Logger::FATAL, message, params)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def unknown(message = nil, params = {})
|
|
41
|
+
add(::Logger::UNKNOWN, message, params)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add(severity, message = nil, params = {})
|
|
45
|
+
return true if message.blank?
|
|
46
|
+
return true unless severity >= level
|
|
47
|
+
|
|
48
|
+
severity_symbol = SEVERITY_MAP[severity] || :unknown
|
|
49
|
+
self.class.append_custom_log(severity_symbol, message, params)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def <<(message)
|
|
53
|
+
add(::Logger::UNKNOWN, message.to_s.chomp, {})
|
|
54
|
+
self
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def write(message)
|
|
58
|
+
@logging_device.write("#{message}\n") if @logging_device.respond_to?(:write)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class << self
|
|
62
|
+
def custom_logs
|
|
63
|
+
CUSTOM_LOGS.value
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def reset_thread_logs
|
|
67
|
+
CUSTOM_LOGS.value = []
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def fetch_and_reset_custom_logs
|
|
71
|
+
logs = custom_logs
|
|
72
|
+
reset_thread_logs
|
|
73
|
+
logs
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def trim(data)
|
|
77
|
+
data = filter(data)
|
|
78
|
+
size = data.inspect.length
|
|
79
|
+
max = UnifiedLogger.config[:max_log_field_size]
|
|
80
|
+
return data if size < max
|
|
81
|
+
|
|
82
|
+
begin
|
|
83
|
+
json = JSON.generate(data, quirks_mode: true)
|
|
84
|
+
rescue JSON::GeneratorError, Encoding::UndefinedConversionError
|
|
85
|
+
json = data.respond_to?("to_s") ? data.to_s : "unparseable object (instance of #{data.class.name})"
|
|
86
|
+
end
|
|
87
|
+
"#{json[0..max]}... (#{size - max} extra characters omitted)"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def format_exception(exception)
|
|
91
|
+
if exception.is_a?(String)
|
|
92
|
+
{ message: exception }
|
|
93
|
+
elsif exception.is_a?(Exception)
|
|
94
|
+
btc = ActiveSupport::BacktraceCleaner.new
|
|
95
|
+
prefix = UnifiedLogger.backtrace_root + File::SEPARATOR
|
|
96
|
+
btc.add_filter { |line| line.sub(/\A#{Regexp.escape(prefix)}/, "") }
|
|
97
|
+
btc.add_silencer { |line| /request_logger.rb/.match?(line) }
|
|
98
|
+
{ class_name: exception.class.name, message: exception.message, backtrace: btc.clean(exception.backtrace || []) }
|
|
99
|
+
elsif exception.respond_to?(:to_s)
|
|
100
|
+
exception.to_s
|
|
101
|
+
else
|
|
102
|
+
exception.class.name
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def filter(content)
|
|
107
|
+
return content unless content.respond_to?(:each)
|
|
108
|
+
|
|
109
|
+
filter_class = if defined?(ActiveSupport::ParameterFilter)
|
|
110
|
+
ActiveSupport::ParameterFilter
|
|
111
|
+
else
|
|
112
|
+
ActionDispatch::Http::ParameterFilter
|
|
113
|
+
end
|
|
114
|
+
filter_class.new(UnifiedLogger.config[:filter_params]).filter(content)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def format(log)
|
|
118
|
+
filtered_log = filter(log)
|
|
119
|
+
formatter = UnifiedLogger.log_transformer
|
|
120
|
+
formatter.present? ? formatter.call(filtered_log) : filtered_log.to_json
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def append_custom_log(severity, message, params)
|
|
124
|
+
clean_message = clean_log_message(message)
|
|
125
|
+
log_hash = { timestamp: UnifiedLogger.current_time, severity: severity,
|
|
126
|
+
message: clean_message, params: params }.compact_blank
|
|
127
|
+
|
|
128
|
+
CUSTOM_LOGS.value = CUSTOM_LOGS.value + [log_hash]
|
|
129
|
+
true
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def clean_log_message(text)
|
|
133
|
+
return text unless text.is_a?(String)
|
|
134
|
+
|
|
135
|
+
text = text.gsub(/\e\[[0-9;]*m/, "")
|
|
136
|
+
text = text.gsub(%r{[^a-zA-Z0-9\s.,;:!?'"()\[\]{}\-_@#$%&*+=<>|~`/]}, "")
|
|
137
|
+
text = text.gsub('"', "'")
|
|
138
|
+
text = text.gsub(/\s+/, " ")
|
|
139
|
+
text.strip
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
module UnifiedLogger
|
|
2
|
+
class Railtie < Rails::Railtie
|
|
3
|
+
initializer "unified_logger.middleware", after: :load_config_initializers do |app|
|
|
4
|
+
app.middleware.insert_after ActionDispatch::DebugExceptions, UnifiedLogger::RequestLogger if UnifiedLogger.config[:auto_insert_middleware]
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require "English"
|
|
2
|
+
|
|
3
|
+
module UnifiedLogger
|
|
4
|
+
class RequestLogger
|
|
5
|
+
def initialize(app)
|
|
6
|
+
@app = app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
return @app.call(env) unless UnifiedLogger.current_logger.is_a?(UnifiedLogger::Logger)
|
|
11
|
+
|
|
12
|
+
started = UnifiedLogger.current_time
|
|
13
|
+
status, headers, response = @app.call(env)
|
|
14
|
+
ensure
|
|
15
|
+
if UnifiedLogger.current_logger.is_a?(UnifiedLogger::Logger) && !silenced?(env["REQUEST_PATH"])
|
|
16
|
+
log = build_log(started, env, status, headers, response)
|
|
17
|
+
custom = {}
|
|
18
|
+
UnifiedLogger.transform_request_log_callable&.call(custom, env)
|
|
19
|
+
log.merge!(custom)
|
|
20
|
+
UnifiedLogger.current_logger.write(UnifiedLogger::Logger.format(log))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def silenced?(path)
|
|
27
|
+
UnifiedLogger.config[:silence_paths].any? do |pattern|
|
|
28
|
+
pattern.is_a?(Regexp) ? pattern.match?(path) : pattern == path
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def build_log(started, env, status = nil, headers = nil, response = nil)
|
|
33
|
+
status ||= 500
|
|
34
|
+
headers ||= {}
|
|
35
|
+
response ||= ""
|
|
36
|
+
path_parameters = env["action_dispatch.request.path_parameters"] || {}
|
|
37
|
+
query_string = env["QUERY_STRING"]
|
|
38
|
+
log = {
|
|
39
|
+
log_type: :request,
|
|
40
|
+
id: env["action_dispatch.request_id"],
|
|
41
|
+
ip: env["action_dispatch.remote_ip"].to_s,
|
|
42
|
+
controller: path_parameters[:controller],
|
|
43
|
+
action: path_parameters[:action],
|
|
44
|
+
request: {
|
|
45
|
+
path: env["REQUEST_PATH"],
|
|
46
|
+
method: env["REQUEST_METHOD"],
|
|
47
|
+
headers: env.select { |e| e.start_with?("HTTP_") }.reject { |h| h.start_with?("HTTP_SEC_") },
|
|
48
|
+
path_params: path_parameters.except(:controller, :action),
|
|
49
|
+
query_params: query_string.blank? ? {} : Rack::Utils.parse_nested_query(query_string),
|
|
50
|
+
body: request_body(env)
|
|
51
|
+
},
|
|
52
|
+
response: {
|
|
53
|
+
headers: headers,
|
|
54
|
+
status: status,
|
|
55
|
+
body: response_body(response, headers["content-type"])
|
|
56
|
+
},
|
|
57
|
+
thread_id: Thread.current.object_id,
|
|
58
|
+
process_id: Process.pid,
|
|
59
|
+
duration: started ? UnifiedLogger.current_time - started : 0
|
|
60
|
+
}
|
|
61
|
+
log[:exception] = UnifiedLogger::Logger.format_exception($ERROR_INFO) if $ERROR_INFO.present?
|
|
62
|
+
log[:custom] = UnifiedLogger::Logger.fetch_and_reset_custom_logs if UnifiedLogger::Logger.custom_logs.any?
|
|
63
|
+
|
|
64
|
+
log
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def request_body(env)
|
|
68
|
+
return nil unless (input = env["rack.input"])
|
|
69
|
+
return env["rack.request.form_hash"] if env["rack.request.form_hash"]
|
|
70
|
+
|
|
71
|
+
input.rewind
|
|
72
|
+
body = input.read
|
|
73
|
+
input.rewind
|
|
74
|
+
|
|
75
|
+
parse_body(body, env["CONTENT_TYPE"])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def response_body(response, content_type)
|
|
79
|
+
return nil if response.nil? || (response.respond_to?(:empty?) && response.empty?)
|
|
80
|
+
return nil if content_type&.exclude?("application/") && content_type.exclude?("text/plain")
|
|
81
|
+
return response_body(response.body, content_type) if response.respond_to?(:body)
|
|
82
|
+
|
|
83
|
+
body = response.respond_to?(:map) ? response.map(&:to_s).join : response.to_s
|
|
84
|
+
|
|
85
|
+
parse_body(body, content_type)
|
|
86
|
+
ensure
|
|
87
|
+
response.close if response.respond_to?(:close)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def parse_body(body, content_type)
|
|
91
|
+
return nil if body.nil?
|
|
92
|
+
return nil if body.empty?
|
|
93
|
+
|
|
94
|
+
main_content_type = content_type&.split(";")&.first&.strip&.downcase
|
|
95
|
+
|
|
96
|
+
case main_content_type
|
|
97
|
+
when "application/json"
|
|
98
|
+
JSON.parse(body)
|
|
99
|
+
when "application/x-www-form-urlencoded"
|
|
100
|
+
Rack::Utils.parse_nested_query(body)
|
|
101
|
+
else
|
|
102
|
+
UnifiedLogger::Logger.trim(body)
|
|
103
|
+
end
|
|
104
|
+
rescue JSON::ParserError, TypeError, ArgumentError
|
|
105
|
+
body
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require "concurrent"
|
|
2
|
+
require "active_support/core_ext/object/blank"
|
|
3
|
+
require "active_support/core_ext/enumerable"
|
|
4
|
+
require "active_support/parameter_filter"
|
|
5
|
+
require "active_support/backtrace_cleaner"
|
|
6
|
+
require "json"
|
|
7
|
+
require "logger"
|
|
8
|
+
|
|
9
|
+
require_relative "unified_logger/version"
|
|
10
|
+
require_relative "unified_logger/logger"
|
|
11
|
+
require_relative "unified_logger/request_logger"
|
|
12
|
+
require_relative "unified_logger/job_logger"
|
|
13
|
+
|
|
14
|
+
module UnifiedLogger
|
|
15
|
+
class DoubleDefineError < StandardError; end
|
|
16
|
+
|
|
17
|
+
DEFAULTS = {
|
|
18
|
+
max_log_field_size: 2048,
|
|
19
|
+
filter_params: %i[passw secret token crypt salt certificate otp ssn set-cookie http_authorization http_cookie pin],
|
|
20
|
+
auto_insert_middleware: true,
|
|
21
|
+
silence_paths: []
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
def self.config
|
|
25
|
+
@config ||= DEFAULTS.dup
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.configure(options = {})
|
|
29
|
+
config.merge!(options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
attr_reader :transform_request_log_callable, :transform_job_log_callable, :log_transformer
|
|
34
|
+
|
|
35
|
+
def transform_request_log=(callable)
|
|
36
|
+
raise DoubleDefineError, "transform_request_log already defined" if @transform_request_log_callable
|
|
37
|
+
|
|
38
|
+
@transform_request_log_callable = callable
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def transform_job_log=(callable)
|
|
42
|
+
raise DoubleDefineError, "transform_job_log already defined" if @transform_job_log_callable
|
|
43
|
+
|
|
44
|
+
@transform_job_log_callable = callable
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def log_transformer=(callable)
|
|
48
|
+
raise DoubleDefineError, "log_transformer already defined" if @log_transformer
|
|
49
|
+
|
|
50
|
+
@log_transformer = callable
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
delegate :trim, :filter, :format, :format_exception,
|
|
54
|
+
:clean_log_message, :append_custom_log,
|
|
55
|
+
:custom_logs, :fetch_and_reset_custom_logs, :reset_thread_logs,
|
|
56
|
+
to: :"UnifiedLogger::Logger"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.backtrace_root
|
|
60
|
+
if defined?(Rails)
|
|
61
|
+
Rails.root.to_s
|
|
62
|
+
else
|
|
63
|
+
Dir.pwd
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.current_logger
|
|
68
|
+
return unless defined?(Rails)
|
|
69
|
+
|
|
70
|
+
return Rails.logger if Rails.logger.is_a?(UnifiedLogger::Logger)
|
|
71
|
+
return Rails.logger unless Rails.logger.respond_to?(:broadcasts)
|
|
72
|
+
|
|
73
|
+
Rails.logger.broadcasts.find { |l| l.is_a?(UnifiedLogger::Logger) } || Rails.logger
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.current_time
|
|
77
|
+
Time.zone&.now || Time.now.utc
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
require "unified_logger/railtie" if defined?(Rails::Railtie)
|
metadata
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: unified_logger
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Marcovecchio
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activesupport
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '4.2'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '9'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '4.2'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '9'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: concurrent-ruby
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - "~>"
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '1.0'
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - "~>"
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '1.0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: rack
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '1.6'
|
|
53
|
+
- - "<"
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '4'
|
|
56
|
+
type: :runtime
|
|
57
|
+
prerelease: false
|
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '1.6'
|
|
63
|
+
- - "<"
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '4'
|
|
66
|
+
description: One JSON log line per request or job. Captures request/response data,
|
|
67
|
+
in-app logger calls, exceptions with cleaned backtraces, and sensitive data filtering
|
|
68
|
+
— all in a single event.
|
|
69
|
+
executables: []
|
|
70
|
+
extensions: []
|
|
71
|
+
extra_rdoc_files: []
|
|
72
|
+
files:
|
|
73
|
+
- lib/unified_logger.rb
|
|
74
|
+
- lib/unified_logger/job_logger.rb
|
|
75
|
+
- lib/unified_logger/logger.rb
|
|
76
|
+
- lib/unified_logger/railtie.rb
|
|
77
|
+
- lib/unified_logger/request_logger.rb
|
|
78
|
+
- lib/unified_logger/version.rb
|
|
79
|
+
homepage: https://github.com/marcovecchio/unified_logger
|
|
80
|
+
licenses:
|
|
81
|
+
- MIT
|
|
82
|
+
metadata:
|
|
83
|
+
rubygems_mfa_required: 'true'
|
|
84
|
+
source_code_uri: https://github.com/marcovecchio/unified_logger
|
|
85
|
+
rdoc_options: []
|
|
86
|
+
require_paths:
|
|
87
|
+
- lib
|
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: '2.4'
|
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
requirements: []
|
|
99
|
+
rubygems_version: 3.6.7
|
|
100
|
+
specification_version: 4
|
|
101
|
+
summary: Structured JSON logging for Rack and Rails applications
|
|
102
|
+
test_files: []
|