scrolls 0.9.0 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|