scrolls 0.3.7 → 0.9.1

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.
data/test/test_parser.rb CHANGED
@@ -1,6 +1,6 @@
1
- require_relative "test_helper"
1
+ require File.expand_path("../test_helper", __FILE__)
2
2
 
3
- class TestScrollsParser < Test::Unit::TestCase
3
+ class TestScrollsParser < Minitest::Test
4
4
  include Scrolls::Parser
5
5
 
6
6
  def test_parse_bool
@@ -79,6 +79,15 @@ class TestScrollsParser < Test::Unit::TestCase
79
79
  assert_equal 't="2012-06-19T16:02:35+01:00"', unparse(data)
80
80
  end
81
81
 
82
+ def test_unparse_escape_keys
83
+ html = "<p>p</p>"
84
+ slash = "p/p"
85
+
86
+ data = { html => "d", slash => "d" }
87
+ assert_equal '&lt;p&gt;p&lt;&#x2F;p&gt;=d p&#x2F;p=d',
88
+ unparse(data, escape_keys=true)
89
+ end
90
+
82
91
  def test_parse_time
83
92
  time = Time.new(2012, 06, 19, 16, 02, 35, "+01:00")
84
93
  string = "t=2012-06-19T16:02:35+01:00"
data/test/test_scrolls.rb CHANGED
@@ -1,44 +1,35 @@
1
- require_relative "test_helper"
1
+ require File.expand_path("../test_helper", __FILE__)
2
2
 
3
- class TestScrolls < Test::Unit::TestCase
3
+ class TestScrolls < Minitest::Test
4
4
  def setup
5
5
  @out = StringIO.new
6
- Scrolls.stream = @out
6
+ Scrolls.init(
7
+ :stream => @out
8
+ )
7
9
  end
8
10
 
9
- def teardown
10
- Scrolls.global_context({})
11
- # Reset our syslog context
12
- Scrolls.facility = Scrolls::LOG_FACILITY
13
- Scrolls.add_timestamp = false
14
- end
15
-
16
- def test_construct
17
- assert_equal StringIO, Scrolls.stream.class
11
+ def test_default_construct
12
+ Scrolls.init
13
+ assert_equal Scrolls::IOLogger, Scrolls.logger.class
18
14
  end
19
15
 
20
16
  def test_default_global_context
17
+ Scrolls.init(:stream => @out)
21
18
  assert_equal Hash.new, Scrolls.global_context
22
19
  end
23
20
 
24
21
  def test_setting_global_context
25
- Scrolls.global_context(:g => "g")
26
- Scrolls.log(:d => "d")
27
- global = @out.string.gsub("\n", 'XX')
28
- assert_match /g=g.*d=d/, global
29
- end
30
-
31
- def test_adding_to_global_context
32
- Scrolls.global_context(:g => "g")
33
- Scrolls.add_global_context(:h => "h")
22
+ Scrolls.init(
23
+ :stream => @out,
24
+ :global_context => {:g => "g"},
25
+ )
34
26
  Scrolls.log(:d => "d")
35
- global = @out.string.gsub("\n", 'XX')
36
- assert_match /g=g.*h=h.*d=d/, global
27
+ assert_equal "g=g d=d\n", @out.string
37
28
  end
38
29
 
39
30
  def test_default_context
40
- Scrolls.log(:data => "d")
41
- assert_equal Hash.new, Scrolls::Log.context
31
+ Scrolls.log(:d => "d")
32
+ assert_equal Hash.new, Scrolls.internal.context
42
33
  end
43
34
 
44
35
  def test_setting_context
@@ -48,15 +39,19 @@ class TestScrolls < Test::Unit::TestCase
48
39
  end
49
40
 
50
41
  def test_all_the_contexts
51
- Scrolls.global_context(:g => "g")
42
+ Scrolls.init(
43
+ :stream => @out,
44
+ :global_context => {:g => "g"},
45
+ )
52
46
  Scrolls.log(:o => "o") do
53
47
  Scrolls.context(:c => "c") do
54
48
  Scrolls.log(:ic => "i")
55
49
  end
56
50
  Scrolls.log(:i => "i")
57
51
  end
58
- global = @out.string.gsub("\n", 'XX')
59
- assert_match /g=g.*at=start.*i=i/, global
52
+ @out.truncate(37)
53
+ output = "g=g o=o at=start\ng=g c=c ic=i\ng=g i=i"
54
+ assert_equal output, @out.string
60
55
  end
61
56
 
62
57
  def test_deeply_nested_context
@@ -89,12 +84,27 @@ class TestScrolls < Test::Unit::TestCase
89
84
  raise "Error from inside of context"
90
85
  end
91
86
  fail "Exception did not escape context block"
92
- rescue => e
87
+ rescue
93
88
  Scrolls.log(:o => 'o')
94
89
  assert_equal "o=o\n", @out.string
95
90
  end
96
91
  end
97
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
+
98
108
  def test_default_time_unit
99
109
  assert_equal "seconds", Scrolls.time_unit
100
110
  end
@@ -105,8 +115,15 @@ class TestScrolls < Test::Unit::TestCase
105
115
  end
106
116
 
107
117
  def test_setting_incorrect_time_unit
108
- assert_raise Scrolls::TimeUnitError do
118
+ assert_raises Scrolls::TimeUnitError do
109
119
  Scrolls.time_unit = "years"
120
+ Scrolls.log(:tu => "yrs")
121
+ end
122
+ end
123
+
124
+ def test_unknown_log_level
125
+ assert_raises Scrolls::LogLevelError do
126
+ Scrolls.log(:level => "nope")
110
127
  end
111
128
  end
112
129
 
@@ -125,28 +142,28 @@ class TestScrolls < Test::Unit::TestCase
125
142
  begin
126
143
  raise Exception
127
144
  rescue Exception => e
128
- Scrolls.log_exception({:test => "exception"}, e)
145
+ Scrolls.log_exception(e, {:test => "exception"})
129
146
  end
130
147
 
131
- oneline_backtrace = @out.string.gsub("\n", 'XX')
132
-
133
- assert_match /test=exception at=exception.*test_log_exception.*XX.*minitest/,
134
- oneline_backtrace
148
+ oneline_bt = @out.string.gsub("\n", 'XX')
149
+ assert_match(/test=exception at=exception.*test_log_exception.*XX/, oneline_bt)
135
150
  end
136
151
 
137
- def test_single_line_exceptions
138
- Scrolls.single_line_exceptions = true
152
+ def test_multi_line_exceptions
153
+ Scrolls.single_line_exceptions = "multi"
139
154
  begin
140
155
  raise Exception
141
156
  rescue Exception => e
142
- Scrolls.log_exception({:o => "o"}, e)
157
+ Scrolls.log_exception(e, {:o => "o"})
143
158
  end
144
- assert_equal 1, @out.string.scan(/.*site=.*/).size
159
+
160
+ oneline_bt = @out.string.gsub("\n", 'XX')
161
+ assert_match(/o=o at=exception.*test_multi_line_exceptions.*XX/, oneline_bt)
145
162
  end
146
163
 
147
164
  def test_syslog_integration
148
165
  Scrolls.stream = 'syslog'
149
- assert_equal Scrolls::SyslogLogger, Scrolls.stream.class
166
+ assert_equal Scrolls::SyslogLogger, Scrolls.internal.logger.class
150
167
  end
151
168
 
152
169
  def test_syslog_facility
@@ -162,7 +179,7 @@ class TestScrolls < Test::Unit::TestCase
162
179
  def test_setting_syslog_facility_after_instantiation
163
180
  Scrolls.stream = 'syslog'
164
181
  Scrolls.facility = 'local7'
165
- assert_match /facility=184/, Scrolls.stream.inspect
182
+ assert_match(/facility=184/, Scrolls.internal.logger.inspect)
166
183
  end
167
184
 
168
185
  def test_add_timestamp
@@ -204,4 +221,24 @@ class TestScrolls < Test::Unit::TestCase
204
221
  assert_equal "t=t level=alert\n", @out.string
205
222
  end
206
223
 
224
+ def test_sending_string_error
225
+ Scrolls.error("error")
226
+ assert_equal "log_message=error\n", @out.string
227
+ end
228
+
229
+ def test_sending_string_fatal
230
+ Scrolls.fatal("fatal")
231
+ assert_equal "log_message=fatal\n", @out.string
232
+ end
233
+
234
+ def test_sending_string_warn
235
+ Scrolls.warn("warn")
236
+ assert_equal "log_message=warn\n", @out.string
237
+ end
238
+
239
+ def test_sending_string_unknown
240
+ Scrolls.unknown("unknown")
241
+ assert_equal "log_message=unknown\n", @out.string
242
+ end
243
+
207
244
  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.3.7
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Curt Micol
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-10 00:00:00.000000000 Z
11
+ date: 2021-06-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Logging, easier, more consistent.
14
14
  email:
@@ -25,14 +25,13 @@ files:
25
25
  - docs/global-context.md
26
26
  - docs/syslog.md
27
27
  - lib/scrolls.rb
28
- - lib/scrolls/atomic.rb
29
- - lib/scrolls/log.rb
28
+ - lib/scrolls/iologger.rb
29
+ - lib/scrolls/logger.rb
30
30
  - lib/scrolls/parser.rb
31
- - lib/scrolls/syslog.rb
31
+ - lib/scrolls/sysloglogger.rb
32
32
  - lib/scrolls/utils.rb
33
33
  - lib/scrolls/version.rb
34
34
  - scrolls.gemspec
35
- - test/test_atomic.rb
36
35
  - test/test_helper.rb
37
36
  - test/test_parser.rb
38
37
  - test/test_scrolls.rb
@@ -55,13 +54,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
54
  - !ruby/object:Gem::Version
56
55
  version: '0'
57
56
  requirements: []
58
- rubyforge_project:
59
- rubygems_version: 2.2.0
57
+ rubygems_version: 3.0.3
60
58
  signing_key:
61
59
  specification_version: 4
62
60
  summary: When do we log? All the time.
63
61
  test_files:
64
- - test/test_atomic.rb
65
62
  - test/test_helper.rb
66
63
  - test/test_parser.rb
67
64
  - test/test_scrolls.rb
@@ -1,59 +0,0 @@
1
- require 'thread'
2
-
3
- module Scrolls
4
- # The result of issues with an update I made to Scrolls. After talking with
5
- # Fabio Kung about a fix I started work on an atomic object, but he added some
6
- # fixes to #context without it and then used Headius' atomic gem.
7
- #
8
- # The code below is the start and cleanup of my atomic object. It's slim on
9
- # details and eventually cleaned up around inspiration from Headius' code.
10
- #
11
- # LICENSE: Apache 2.0
12
- #
13
- # See Headius' atomic gem here:
14
- # https://github.com/headius/ruby-atomic
15
- class AtomicObject
16
- def initialize(o)
17
- @mtx = Mutex.new
18
- @o = o
19
- end
20
-
21
- def get
22
- @mtx.synchronize { @o }
23
- end
24
-
25
- def set(n)
26
- @mtx.synchronize { @o = n }
27
- end
28
-
29
- def verify_set(o, n)
30
- return false unless @mtx.try_lock
31
- begin
32
- return false unless @o.equal? o
33
- @o = n
34
- ensure
35
- @mtx.unlock
36
- end
37
- end
38
- end
39
-
40
- class Atomic < AtomicObject
41
- def initialize(v=nil)
42
- super(v)
43
- end
44
-
45
- def value
46
- self.get
47
- end
48
-
49
- def value=(v)
50
- self.set(v)
51
- v
52
- end
53
-
54
- def update
55
- true until self.verify_set(o = self.get, n = yield(o))
56
- n
57
- end
58
- end
59
- end
data/lib/scrolls/log.rb DELETED
@@ -1,274 +0,0 @@
1
- require "scrolls/parser"
2
- require "scrolls/utils"
3
- require "scrolls/syslog"
4
-
5
- module Scrolls
6
-
7
- class TimeUnitError < RuntimeError; end
8
-
9
- module Log
10
- extend self
11
-
12
- extend Parser
13
- extend Utils
14
-
15
- LOG_LEVEL = (ENV['LOG_LEVEL'] || 6).to_i
16
- LOG_LEVEL_MAP = {
17
- "emergency" => 0,
18
- "alert" => 1,
19
- "critical" => 2,
20
- "error" => 3,
21
- "warning" => 4,
22
- "notice" => 5,
23
- "info" => 6,
24
- "debug" => 7
25
- }
26
-
27
- def context
28
- Thread.current[:scrolls_context] ||= {}
29
- end
30
-
31
- def context=(h)
32
- Thread.current[:scrolls_context] = h
33
- end
34
-
35
- def global_context
36
- get_global_context
37
- end
38
-
39
- def global_context=(data)
40
- set_global_context(data)
41
- end
42
-
43
- def add_global_context(new_data)
44
- default_global_context unless @global_context
45
- @global_context.update { |previous_data| previous_data.merge(new_data) }
46
- end
47
-
48
- def facility=(f)
49
- @facility = LOG_FACILITY_MAP[f] if f
50
- if Scrolls::SyslogLogger.opened?
51
- Scrolls::SyslogLogger.new(progname, facility)
52
- end
53
- end
54
-
55
- def facility
56
- @facility ||= default_log_facility
57
- end
58
-
59
- def stream=(out=nil)
60
- @defined = out.nil? ? false : true
61
- if out == 'syslog'
62
- @stream = Scrolls::SyslogLogger.new(progname, facility)
63
- else
64
- @stream = sync_stream(out)
65
- end
66
- end
67
-
68
- def stream
69
- @stream ||= sync_stream
70
- end
71
-
72
- def time_unit=(u)
73
- set_time_unit(u)
74
- end
75
-
76
- def time_unit
77
- @tunit ||= default_time_unit
78
- end
79
-
80
- def add_timestamp=(b)
81
- @add_timestamp = !!b
82
- end
83
-
84
- def add_timestamp
85
- @add_timestamp || false
86
- end
87
-
88
- def single_line_exceptions=(b)
89
- @single_line_exceptions = !!b
90
- end
91
-
92
- def single_line_exceptions?
93
- @single_line_exceptions || false
94
- end
95
-
96
- def log(data, &blk)
97
- # If we get a string lets bring it into our structure.
98
- if data.kind_of? String
99
- rawhash = { "log_message" => data }
100
- else
101
- rawhash = data
102
- end
103
-
104
- if gc = get_global_context
105
- ctx = gc.merge(context)
106
- logdata = ctx.merge(rawhash)
107
- end
108
-
109
- # By merging the logdata into the timestamp, rather than vice-versa, we
110
- # ensure that the timestamp comes first in the Hash, and is placed first
111
- # on the output, which helps with readability.
112
- logdata = { :now => Time.now.utc }.merge(logdata) if add_timestamp
113
-
114
- unless blk
115
- write(logdata)
116
- else
117
- start = Time.now
118
- res = nil
119
- log(logdata.merge(:at => "start"))
120
- begin
121
- res = yield
122
- rescue StandardError => e
123
- log(logdata.merge(
124
- :at => "exception",
125
- :reraise => true,
126
- :class => e.class,
127
- :message => e.message,
128
- :exception_id => e.object_id.abs,
129
- :elapsed => calc_time(start, Time.now)
130
- ))
131
- raise e
132
- end
133
- log(logdata.merge(:at => "finish", :elapsed => calc_time(start, Time.now)))
134
- res
135
- end
136
- end
137
-
138
- def log_exception(data, e)
139
- sync_stream(STDERR) unless @defined
140
-
141
- # If we get a string lets bring it into our structure.
142
- if data.kind_of? String
143
- rawhash = { "log_message" => data }
144
- else
145
- rawhash = data
146
- end
147
-
148
- if gc = get_global_context
149
- logdata = gc.merge(rawhash)
150
- end
151
-
152
- excepdata = {
153
- :at => "exception",
154
- :class => e.class,
155
- :message => e.message,
156
- :exception_id => e.object_id.abs
157
- }
158
-
159
- if e.backtrace
160
- if single_line_exceptions?
161
- btlines = []
162
- e.backtrace.each do |line|
163
- btlines << line.gsub(/[`'"]/, "")
164
- end
165
-
166
- if btlines.length > 0
167
- squish = { :site => btlines.join('\n') }
168
- log(logdata.merge(excepdata.merge(squish)))
169
- end
170
- else
171
- log(logdata.merge(excepdata))
172
-
173
- e.backtrace.each do |line|
174
- log(logdata.merge(excepdata).merge(
175
- :at => "exception",
176
- :class => e.class,
177
- :exception_id => e.object_id.abs,
178
- :site => line.gsub(/[`'"]/, "")
179
- ))
180
- end
181
- end
182
- end
183
- end
184
-
185
- def with_context(prefix)
186
- return unless block_given?
187
- old = context
188
- self.context = old.merge(prefix)
189
- res = yield if block_given?
190
- ensure
191
- self.context = old
192
- res
193
- end
194
-
195
- private
196
-
197
- def get_global_context
198
- default_global_context unless @global_context
199
- @global_context.value
200
- end
201
-
202
- def set_global_context(data=nil)
203
- default_global_context unless @global_context
204
- @global_context.update { |_| data }
205
- end
206
-
207
- def default_global_context
208
- @global_context = Atomic.new({})
209
- end
210
-
211
- def set_time_unit(u=nil)
212
- unless ["ms","milli","milliseconds","s","seconds"].include?(u)
213
- raise TimeUnitError, "Specify only 'seconds' or 'milliseconds'"
214
- end
215
-
216
- if ["ms", "milli", "milliseconds", 1000].include?(u)
217
- @tunit = "milliseconds"
218
- @t = 1000.0
219
- else
220
- default_time_unit
221
- end
222
- end
223
-
224
- def default_time_unit
225
- @t = 1.0
226
- @tunit = "seconds"
227
- end
228
-
229
- def calc_time(start, finish)
230
- default_time_unit unless @t
231
- ((finish - start).to_f * @t)
232
- end
233
-
234
- def mtx
235
- @mtx ||= Mutex.new
236
- end
237
-
238
- def sync_stream(out=nil)
239
- out = STDOUT if out.nil?
240
- s = out
241
- s.sync = true
242
- s
243
- end
244
-
245
- def write(data)
246
- if log_level_ok?(data[:level])
247
- msg = unparse(data)
248
- mtx.synchronize do
249
- begin
250
- stream.puts(msg)
251
- rescue NoMethodError => e
252
- raise
253
- end
254
- end
255
- end
256
- end
257
-
258
- def log_level_ok?(level)
259
- if level
260
- LOG_LEVEL_MAP[level.to_s] <= LOG_LEVEL
261
- else
262
- true
263
- end
264
- end
265
-
266
- def progname
267
- File.basename($0)
268
- end
269
-
270
- def default_log_facility
271
- LOG_FACILITY
272
- end
273
- end
274
- end