scrolls 0.9.0 → 0.9.5
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 +5 -5
- data/LICENSE +2 -2
- data/README.md +1 -0
- data/lib/scrolls/logger.rb +16 -11
- data/lib/scrolls/parser.rb +2 -2
- data/lib/scrolls/version.rb +1 -1
- data/lib/scrolls.rb +28 -15
- data/test/test_parser.rb +6 -0
- data/test/test_scrolls.rb +37 -4
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c9e31caada359ce18dceed5246a8da245c3a8587f02ebe079e3317baf2f50551
|
4
|
+
data.tar.gz: 28cfb3b4ed27598042d5499d9b3e5105bab48562b3d18dd6c678398cbcee6d0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9fadc0c6475e40c4d427295f1d9b9db218e1038bcca634ebd00da18a80aced226510e6ea69a1c66c817cae947cff7cff621a7532cbeb6428c7e3bbaf9049913
|
7
|
+
data.tar.gz: 99293d2de9ac23a5d07e3551a88964f3f76ca5537002915480ba898acc8ba0171355da7930e27d3d085a5eb34e75e865237bc192c6bf4396884366c7230b344b
|
data/LICENSE
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright
|
4
|
-
Copyright
|
3
|
+
Copyright (c) 2013-2021 Curt Micol <asenchi@asenchi.com>
|
4
|
+
Copyright (c) 2012, Heroku
|
5
5
|
|
6
6
|
Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
data/lib/scrolls/logger.rb
CHANGED
@@ -37,14 +37,15 @@ module Scrolls
|
|
37
37
|
attr_accessor :exceptions, :timestamp
|
38
38
|
|
39
39
|
def initialize(options={})
|
40
|
-
@stream
|
41
|
-
@log_facility
|
42
|
-
@time_unit
|
43
|
-
@timestamp
|
44
|
-
@exceptions
|
45
|
-
@global_ctx
|
46
|
-
@syslog_opts
|
47
|
-
@escape_keys
|
40
|
+
@stream = options.fetch(:stream, STDOUT)
|
41
|
+
@log_facility = options.fetch(:facility, LOG_FACILITY)
|
42
|
+
@time_unit = options.fetch(:time_unit, "seconds")
|
43
|
+
@timestamp = options.fetch(:timestamp, false)
|
44
|
+
@exceptions = options.fetch(:exceptions, "single")
|
45
|
+
@global_ctx = options.fetch(:global_context, {})
|
46
|
+
@syslog_opts = options.fetch(:syslog_options, SYSLOG_OPTIONS)
|
47
|
+
@escape_keys = options.fetch(:escape_keys, false)
|
48
|
+
@strict_logfmt = options.fetch(:strict_logfmt, false)
|
48
49
|
|
49
50
|
# Our main entry point to ensure our options are setup properly
|
50
51
|
setup!
|
@@ -69,7 +70,7 @@ module Scrolls
|
|
69
70
|
def stream=(s)
|
70
71
|
# Return early to avoid setup
|
71
72
|
return if s == @stream
|
72
|
-
|
73
|
+
|
73
74
|
@stream = s
|
74
75
|
setup_stream
|
75
76
|
end
|
@@ -78,6 +79,10 @@ module Scrolls
|
|
78
79
|
@escape_keys
|
79
80
|
end
|
80
81
|
|
82
|
+
def strict_logfmt?
|
83
|
+
@strict_logfmt
|
84
|
+
end
|
85
|
+
|
81
86
|
def syslog_options
|
82
87
|
@syslog_opts
|
83
88
|
end
|
@@ -140,7 +145,7 @@ module Scrolls
|
|
140
145
|
begin
|
141
146
|
res = yield
|
142
147
|
rescue StandardError => e
|
143
|
-
logdata.merge({
|
148
|
+
logdata.merge!({
|
144
149
|
at: "exception",
|
145
150
|
reraise: true,
|
146
151
|
class: e.class,
|
@@ -309,7 +314,7 @@ module Scrolls
|
|
309
314
|
|
310
315
|
def write(data)
|
311
316
|
if log_level_ok?(data[:level])
|
312
|
-
msg = Scrolls::Parser.unparse(data, escape_keys=escape_keys?)
|
317
|
+
msg = Scrolls::Parser.unparse(data, escape_keys=escape_keys?, strict_logfmt=strict_logfmt?)
|
313
318
|
@logger.log(msg)
|
314
319
|
end
|
315
320
|
end
|
data/lib/scrolls/parser.rb
CHANGED
@@ -4,7 +4,7 @@ module Scrolls
|
|
4
4
|
module Parser
|
5
5
|
extend self
|
6
6
|
|
7
|
-
def unparse(data, escape_keys=false)
|
7
|
+
def unparse(data, escape_keys=false, strict_logfmt=false)
|
8
8
|
data.map do |(k,v)|
|
9
9
|
k = Scrolls::Utils.escape_chars(k) if escape_keys
|
10
10
|
|
@@ -23,7 +23,7 @@ module Scrolls
|
|
23
23
|
has_single_quote = v.index("'")
|
24
24
|
has_double_quote = v.index('"')
|
25
25
|
if v =~ /[ =:,]/
|
26
|
-
if has_single_quote && has_double_quote
|
26
|
+
if (has_single_quote || strict_logfmt) && has_double_quote
|
27
27
|
v = '"' + v.gsub(/\\|"/) { |c| "\\#{c}" } + '"'
|
28
28
|
elsif has_double_quote
|
29
29
|
v = "'" + v.gsub('\\', '\\\\\\') + "'"
|
data/lib/scrolls/version.rb
CHANGED
data/lib/scrolls.rb
CHANGED
@@ -7,18 +7,21 @@ module Scrolls
|
|
7
7
|
# Public: Initialize a Scrolls logger
|
8
8
|
#
|
9
9
|
# options - A hash of key/values for configuring Scrolls
|
10
|
-
# stream
|
11
|
-
# log_facility
|
12
|
-
# time_unit
|
13
|
-
# timestamp
|
14
|
-
# exceptions
|
15
|
-
# global_context
|
16
|
-
# syslog_options
|
17
|
-
# escape_keys
|
10
|
+
# stream - Stream to output data (default: STDOUT)
|
11
|
+
# log_facility - Syslog facility (default: Syslog::LOG_USER)
|
12
|
+
# time_unit - Unit of time (default: seconds)
|
13
|
+
# timestamp - Prepend logs with a timestamp (default: false)
|
14
|
+
# exceptions - Method for outputting exceptions (default: single line)
|
15
|
+
# global_context - Immutable context to prepend all messages with
|
16
|
+
# syslog_options - Syslog options (default: Syslog::LOG_PID|Syslog::LOG_CONS)
|
17
|
+
# escape_keys - Escape chars in keys
|
18
|
+
# strict_logfmt - Always use double quotes to quote values
|
19
|
+
# adapt_severity_for_syslog - Downgrade severity one level to match syslog (default: true) per https://docs.ruby-lang.org/en/2.1.0/Syslog/Logger.html
|
18
20
|
#
|
19
21
|
def init(options={})
|
20
22
|
# Set a hint whether #init was called.
|
21
23
|
@initialized = true
|
24
|
+
@adapt_severity_for_syslog = options.fetch(:adapt_severity_for_syslog, true)
|
22
25
|
@log = Logger.new(options)
|
23
26
|
end
|
24
27
|
|
@@ -71,24 +74,24 @@ module Scrolls
|
|
71
74
|
|
72
75
|
# Public: Log an exception
|
73
76
|
#
|
74
|
-
# data - A hash of key/values to log
|
75
77
|
# e - An exception to pass to the logger
|
78
|
+
# data - A hash of key/values to log
|
76
79
|
#
|
77
80
|
# Examples:
|
78
81
|
#
|
79
82
|
# begin
|
80
83
|
# raise Exception
|
81
84
|
# rescue Exception => e
|
82
|
-
# Scrolls.log_exception({test: "test"}
|
85
|
+
# Scrolls.log_exception(e, {test: "test"})
|
83
86
|
# end
|
84
87
|
# test=test at=exception class=Exception message=Exception exception_id=70321999017240
|
85
88
|
# ...
|
86
89
|
#
|
87
|
-
def log_exception(
|
90
|
+
def log_exception(e, data)
|
88
91
|
# Allows us to call #log directly and initialize defaults
|
89
92
|
@log = Logger.new({}) unless @initialized
|
90
93
|
|
91
|
-
@log.log_exception(
|
94
|
+
@log.log_exception(e, data)
|
92
95
|
end
|
93
96
|
|
94
97
|
# Public: Setup a logging facility (default: Syslog::LOG_USER)
|
@@ -221,6 +224,7 @@ module Scrolls
|
|
221
224
|
# => nil
|
222
225
|
#
|
223
226
|
def debug(data, &blk)
|
227
|
+
data = coalesce_strings_to_hash(data)
|
224
228
|
data = data.merge(:level => "debug") if data.is_a?(Hash)
|
225
229
|
@log.log(data, &blk)
|
226
230
|
end
|
@@ -239,7 +243,8 @@ module Scrolls
|
|
239
243
|
# => nil
|
240
244
|
#
|
241
245
|
def error(data, &blk)
|
242
|
-
data =
|
246
|
+
data = coalesce_strings_to_hash(data)
|
247
|
+
data = data.merge(:level => @adapt_severity_for_syslog ? "warning" : "error") if data.is_a?(Hash)
|
243
248
|
@log.log(data, &blk)
|
244
249
|
end
|
245
250
|
|
@@ -257,7 +262,8 @@ module Scrolls
|
|
257
262
|
# => nil
|
258
263
|
#
|
259
264
|
def fatal(data, &blk)
|
260
|
-
data =
|
265
|
+
data = coalesce_strings_to_hash(data)
|
266
|
+
data = data.merge(:level => @adapt_severity_for_syslog ? "error" : "critical") if data.is_a?(Hash)
|
261
267
|
@log.log(data, &blk)
|
262
268
|
end
|
263
269
|
|
@@ -275,6 +281,7 @@ module Scrolls
|
|
275
281
|
# => nil
|
276
282
|
#
|
277
283
|
def info(data, &blk)
|
284
|
+
data = coalesce_strings_to_hash(data)
|
278
285
|
data = data.merge(:level => "info") if data.is_a?(Hash)
|
279
286
|
@log.log(data, &blk)
|
280
287
|
end
|
@@ -293,7 +300,8 @@ module Scrolls
|
|
293
300
|
# => nil
|
294
301
|
#
|
295
302
|
def warn(data, &blk)
|
296
|
-
data =
|
303
|
+
data = coalesce_strings_to_hash(data)
|
304
|
+
data = data.merge(:level => @adapt_severity_for_syslog ? "notice" : "warn") if data.is_a?(Hash)
|
297
305
|
@log.log(data, &blk)
|
298
306
|
end
|
299
307
|
|
@@ -311,6 +319,7 @@ module Scrolls
|
|
311
319
|
# => nil
|
312
320
|
#
|
313
321
|
def unknown(data, &blk)
|
322
|
+
data = coalesce_strings_to_hash(data)
|
314
323
|
data = data.merge(:level => "alert") if data.is_a?(Hash)
|
315
324
|
@log.log(data, &blk)
|
316
325
|
end
|
@@ -321,4 +330,8 @@ module Scrolls
|
|
321
330
|
@log
|
322
331
|
end
|
323
332
|
|
333
|
+
def coalesce_strings_to_hash(string_or_something_else)
|
334
|
+
return string_or_something_else unless string_or_something_else.is_a?(String)
|
335
|
+
{ "log_message" => string_or_something_else }
|
336
|
+
end
|
324
337
|
end
|
data/test/test_parser.rb
CHANGED
@@ -88,6 +88,12 @@ class TestScrollsParser < Minitest::Test
|
|
88
88
|
unparse(data, escape_keys=true)
|
89
89
|
end
|
90
90
|
|
91
|
+
def test_unparse_strict_logfmt
|
92
|
+
data = { s: 'echo "hello"' }
|
93
|
+
assert_equal 's="echo \"hello\""', unparse(data, escape_keys=false, strict_logfmt=true)
|
94
|
+
assert_equal data.inspect, parse(unparse(data, escape_keys=false, strict_logfmt=true)).inspect
|
95
|
+
end
|
96
|
+
|
91
97
|
def test_parse_time
|
92
98
|
time = Time.new(2012, 06, 19, 16, 02, 35, "+01:00")
|
93
99
|
string = "t=2012-06-19T16:02:35+01:00"
|
data/test/test_scrolls.rb
CHANGED
@@ -90,6 +90,21 @@ class TestScrolls < Minitest::Test
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
def test_deeply_nested_context_after_exception
|
94
|
+
Scrolls.log(:o => "o") do
|
95
|
+
begin
|
96
|
+
Scrolls.log(:io => 'io') do
|
97
|
+
raise "Error from inside of nested logging"
|
98
|
+
end
|
99
|
+
rescue
|
100
|
+
Scrolls.log(:o => 'o')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
@out.truncate(124)
|
104
|
+
output = "o=o at=start\nio=io at=start\nio=io at=exception reraise=true class=RuntimeError message=\"Error from inside of nested logging\""
|
105
|
+
assert_equal output, @out.string
|
106
|
+
end
|
107
|
+
|
93
108
|
def test_default_time_unit
|
94
109
|
assert_equal "seconds", Scrolls.time_unit
|
95
110
|
end
|
@@ -208,22 +223,40 @@ class TestScrolls < Minitest::Test
|
|
208
223
|
|
209
224
|
def test_sending_string_error
|
210
225
|
Scrolls.error("error")
|
211
|
-
assert_equal "log_message=error\n", @out.string
|
226
|
+
assert_equal "log_message=error level=warning\n", @out.string
|
212
227
|
end
|
213
228
|
|
214
229
|
def test_sending_string_fatal
|
215
230
|
Scrolls.fatal("fatal")
|
216
|
-
assert_equal "log_message=fatal\n", @out.string
|
231
|
+
assert_equal "log_message=fatal level=error\n", @out.string
|
217
232
|
end
|
218
233
|
|
219
234
|
def test_sending_string_warn
|
220
235
|
Scrolls.warn("warn")
|
221
|
-
assert_equal "log_message=warn\n", @out.string
|
236
|
+
assert_equal "log_message=warn level=notice\n", @out.string
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_adapted_log_error
|
240
|
+
Scrolls.init({:stream => @out, :adapt_severity_for_syslog => false })
|
241
|
+
Scrolls.error("error")
|
242
|
+
assert_equal "log_message=error level=error\n", @out.string
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_adapted_log_fatal
|
246
|
+
Scrolls.init({:stream => @out, :adapt_severity_for_syslog => false })
|
247
|
+
Scrolls.fatal("fatal")
|
248
|
+
assert_equal "log_message=fatal level=critical\n", @out.string
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_adapted_log_warn
|
252
|
+
Scrolls.init({:stream => @out, :adapt_severity_for_syslog => false })
|
253
|
+
Scrolls.warn("warn")
|
254
|
+
assert_equal "log_message=warn level=warn\n", @out.string
|
222
255
|
end
|
223
256
|
|
224
257
|
def test_sending_string_unknown
|
225
258
|
Scrolls.unknown("unknown")
|
226
|
-
assert_equal "log_message=unknown\n", @out.string
|
259
|
+
assert_equal "log_message=unknown level=alert\n", @out.string
|
227
260
|
end
|
228
261
|
|
229
262
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scrolls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Curt Micol
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Logging, easier, more consistent.
|
14
14
|
email:
|
@@ -54,8 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
requirements: []
|
57
|
-
|
58
|
-
rubygems_version: 2.6.13
|
57
|
+
rubygems_version: 3.2.29
|
59
58
|
signing_key:
|
60
59
|
specification_version: 4
|
61
60
|
summary: When do we log? All the time.
|