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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0beda1c02c56ef85e12ea9a241e4a2077d47455d
4
- data.tar.gz: 60228ade9fab4786baafc08e186b9fb3de509a3e
2
+ SHA256:
3
+ metadata.gz: c9e31caada359ce18dceed5246a8da245c3a8587f02ebe079e3317baf2f50551
4
+ data.tar.gz: 28cfb3b4ed27598042d5499d9b3e5105bab48562b3d18dd6c678398cbcee6d0b
5
5
  SHA512:
6
- metadata.gz: 913819999b29cb0c5d039440340260b38ea92ff9c1877260946dc2129fc3f9d6df66643935403bc4fc3ea743f2512e7025e0231ffe7e950d51f83002d8cd377d
7
- data.tar.gz: 7163d0841cd810a1741e2e333cf62b8cabd1c512da443cd16d10fb4f4f4b02c73f8e10248f58c5c98ac0324f573056521766b0770276f501159ebc212c22f695
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 © Curt Micol <asenchi@asenchi.com> 2012,2013,2014
4
- Copyright © Heroku 2012
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
@@ -67,6 +67,7 @@ exceptions: "single"
67
67
  global_context: {}
68
68
  syslog_options: Syslog::LOG_PID|Syslog::LOG_CONS
69
69
  escape_keys: false
70
+ strict_logfmt: false
70
71
  ```
71
72
 
72
73
  ## Older Versions
@@ -37,14 +37,15 @@ module Scrolls
37
37
  attr_accessor :exceptions, :timestamp
38
38
 
39
39
  def initialize(options={})
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)
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
@@ -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('\\', '\\\\\\') + "'"
@@ -1,3 +1,3 @@
1
1
  module Scrolls
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.5"
3
3
  end
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 - 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
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"}, e)
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(data, e)
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(data, e)
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 = data.merge(:level => "warning") if data.is_a?(Hash)
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 = data.merge(:level => "error") if data.is_a?(Hash)
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 = data.merge(:level => "notice") if data.is_a?(Hash)
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.0
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: 2017-09-04 00:00:00.000000000 Z
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
- rubyforge_project:
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.