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 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.