scrolls 0.3.7 → 0.9.1

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