scrolls 0.3.9 → 0.9.0.pre
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 +4 -4
- data/lib/scrolls.rb +31 -73
- data/lib/scrolls/iolog.rb +3 -1
- data/lib/scrolls/logger.rb +297 -0
- data/lib/scrolls/version.rb +1 -1
- data/test/test_parser.rb +1 -1
- data/test/test_scrolls.rb +32 -39
- metadata +5 -7
- data/lib/scrolls/atomic.rb +0 -59
- data/test/test_atomic.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b78c2d850fe048ad6f192be59e56b6d04daee1c5
|
4
|
+
data.tar.gz: 49934f36ea64c5fe6a8a1b44ecb5689ea4574a75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d05994bb1dfdd62a76ad372a56ac83270fe8853e19f5f402d86031e90b22eec8ff09f26d3208efe91e392a6b2d6391a56c8236eb3b6d29390183cbd8abf58ef
|
7
|
+
data.tar.gz: c45dca818ec283f03f238de1201d5ea70198375b55a458e5a1441f2f8fa069f85198894cd11827496541084cd403ae356b6b9ce40376a499876f72be44f183fc
|
data/lib/scrolls.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require "thread"
|
2
|
-
require "scrolls/
|
3
|
-
require "scrolls/log"
|
2
|
+
require "scrolls/logger"
|
4
3
|
require "scrolls/version"
|
5
4
|
|
6
5
|
module Scrolls
|
@@ -8,33 +7,10 @@ module Scrolls
|
|
8
7
|
|
9
8
|
# Public: Initialize a Scrolls logger
|
10
9
|
#
|
11
|
-
# Convienence method to prepare for future releases. Currently mimics
|
12
|
-
# behavior found in other methods. This prepares the developer for a future
|
13
|
-
# backward incompatible change, see:
|
14
|
-
# https://github.com/asenchi/scrolls/pull/54
|
15
|
-
#
|
16
10
|
# options - A hash of key/values for configuring Scrolls
|
17
11
|
#
|
18
|
-
def init(options)
|
19
|
-
|
20
|
-
facility = options.fetch(:facility, Syslog::LOG_USER)
|
21
|
-
time_unit = options.fetch(:time_unit, "seconds")
|
22
|
-
timestamp = options.fetch(:timestamp, false)
|
23
|
-
exceptions = options.fetch(:exceptions, "multi")
|
24
|
-
global_ctx = options.fetch(:global_context, {})
|
25
|
-
|
26
|
-
Log.stream = stream
|
27
|
-
Log.facility = facility if facility
|
28
|
-
Log.time_unit = time_unit unless time_unit == "seconds"
|
29
|
-
Log.add_timestamp = timestamp unless timestamp == false
|
30
|
-
|
31
|
-
if exceptions == "single"
|
32
|
-
Log.single_line_exceptions = true
|
33
|
-
end
|
34
|
-
|
35
|
-
unless global_ctx == {}
|
36
|
-
Log.global_context = global_ctx
|
37
|
-
end
|
12
|
+
def init(options={})
|
13
|
+
@log = Log.new(options)
|
38
14
|
end
|
39
15
|
|
40
16
|
# Public: Set a context in a block for logs
|
@@ -45,37 +21,13 @@ module Scrolls
|
|
45
21
|
# Examples:
|
46
22
|
#
|
47
23
|
def context(data, &blk)
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
# Deprecated: Get or set a global context that prefixs all logs
|
52
|
-
#
|
53
|
-
# data - A hash of key/values to prepend to each log
|
54
|
-
#
|
55
|
-
# This method will be deprecated two releases after 0.3.8.
|
56
|
-
# See https://github.com/asenchi/scrolls/releases/tag/v0.3.8
|
57
|
-
# for more details.
|
58
|
-
#
|
59
|
-
def global_context(data=nil)
|
60
|
-
$stderr.puts "global_context() will be deprecated after v0.3.8, please see https://github.com/asenchi/scrolls for more information."
|
61
|
-
if data
|
62
|
-
Log.global_context = data
|
63
|
-
else
|
64
|
-
Log.global_context
|
65
|
-
end
|
24
|
+
@log.with_context(data, &blk)
|
66
25
|
end
|
67
26
|
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# data - A hash of key/values to prepend to each log
|
71
|
-
#
|
72
|
-
# This method will be deprecated two releases after 0.3.8.
|
73
|
-
# See https://github.com/asenchi/scrolls/releases/tag/v0.3.8
|
74
|
-
# for more details.
|
27
|
+
# Public: Get the global context that prefixs all logs
|
75
28
|
#
|
76
|
-
def
|
77
|
-
|
78
|
-
Log.add_global_context(data)
|
29
|
+
def global_context
|
30
|
+
@log.global_context
|
79
31
|
end
|
80
32
|
|
81
33
|
# Public: Log data and/or wrap a block with start/finish
|
@@ -96,7 +48,7 @@ module Scrolls
|
|
96
48
|
# => nil
|
97
49
|
#
|
98
50
|
def log(data, &blk)
|
99
|
-
|
51
|
+
@log.log(data, &blk)
|
100
52
|
end
|
101
53
|
|
102
54
|
# Public: Log an exception
|
@@ -115,7 +67,7 @@ module Scrolls
|
|
115
67
|
# ...
|
116
68
|
#
|
117
69
|
def log_exception(data, e)
|
118
|
-
|
70
|
+
@log.log_exception(data, e)
|
119
71
|
end
|
120
72
|
|
121
73
|
# Public: Setup a logging facility (default: Syslog::LOG_USER)
|
@@ -127,7 +79,7 @@ module Scrolls
|
|
127
79
|
# Scrolls.facility = Syslog::LOG_LOCAL7
|
128
80
|
#
|
129
81
|
def facility=(f)
|
130
|
-
|
82
|
+
@log.facility=(f)
|
131
83
|
end
|
132
84
|
|
133
85
|
# Public: Return the Syslog facility
|
@@ -138,7 +90,7 @@ module Scrolls
|
|
138
90
|
# => 8
|
139
91
|
#
|
140
92
|
def facility
|
141
|
-
|
93
|
+
@log.facility
|
142
94
|
end
|
143
95
|
|
144
96
|
# Public: Setup a new output (default: STDOUT)
|
@@ -154,7 +106,7 @@ module Scrolls
|
|
154
106
|
# Scrolls.stream = StringIO.new
|
155
107
|
#
|
156
108
|
def stream=(out)
|
157
|
-
|
109
|
+
@log.stream=(out)
|
158
110
|
end
|
159
111
|
|
160
112
|
# Public: Return the stream
|
@@ -165,7 +117,7 @@ module Scrolls
|
|
165
117
|
# => #<IO:<STDOUT>>
|
166
118
|
#
|
167
119
|
def stream
|
168
|
-
|
120
|
+
@log.stream
|
169
121
|
end
|
170
122
|
|
171
123
|
# Public: Set the time unit we use for 'elapsed' (default: "seconds")
|
@@ -177,7 +129,7 @@ module Scrolls
|
|
177
129
|
# Scrolls.time_unit = "milliseconds"
|
178
130
|
#
|
179
131
|
def time_unit=(unit)
|
180
|
-
|
132
|
+
@log.time_unit = unit
|
181
133
|
end
|
182
134
|
|
183
135
|
# Public: Return the time unit currently configured
|
@@ -188,7 +140,7 @@ module Scrolls
|
|
188
140
|
# => "seconds"
|
189
141
|
#
|
190
142
|
def time_unit
|
191
|
-
|
143
|
+
@log.time_unit
|
192
144
|
end
|
193
145
|
|
194
146
|
# Public: Set whether to include a timestamp (now=<ISO8601>) field in the log
|
@@ -199,7 +151,7 @@ module Scrolls
|
|
199
151
|
# Scrolls.add_timestamp = true
|
200
152
|
#
|
201
153
|
def add_timestamp=(boolean)
|
202
|
-
|
154
|
+
@log.timestamp = boolean
|
203
155
|
end
|
204
156
|
|
205
157
|
# Public: Return whether the timestamp field will be included in the log
|
@@ -211,7 +163,7 @@ module Scrolls
|
|
211
163
|
# => true
|
212
164
|
#
|
213
165
|
def add_timestamp
|
214
|
-
|
166
|
+
@log.timestamp
|
215
167
|
end
|
216
168
|
|
217
169
|
# Public: Set whether exceptions should generate a single log
|
@@ -222,7 +174,7 @@ module Scrolls
|
|
222
174
|
# Scrolls.single_line_exceptions = true
|
223
175
|
#
|
224
176
|
def single_line_exceptions=(boolean)
|
225
|
-
|
177
|
+
@log.exceptions = boolean
|
226
178
|
end
|
227
179
|
|
228
180
|
# Public: Return whether exceptions generate a single log message.
|
@@ -233,7 +185,7 @@ module Scrolls
|
|
233
185
|
# => true
|
234
186
|
#
|
235
187
|
def single_line_exceptions?
|
236
|
-
|
188
|
+
@log.single_line_exceptions?
|
237
189
|
end
|
238
190
|
|
239
191
|
# Public: Convience method for Logger replacement
|
@@ -249,7 +201,7 @@ module Scrolls
|
|
249
201
|
#
|
250
202
|
def debug(data, &blk)
|
251
203
|
data = data.merge(:level => "debug") if data.is_a?(Hash)
|
252
|
-
|
204
|
+
@log.log(data, &blk)
|
253
205
|
end
|
254
206
|
|
255
207
|
# Public: Convience method for Logger replacement
|
@@ -267,7 +219,7 @@ module Scrolls
|
|
267
219
|
#
|
268
220
|
def error(data, &blk)
|
269
221
|
data = data.merge(:level => "warning") if data.is_a?(Hash)
|
270
|
-
|
222
|
+
@log.log(data, &blk)
|
271
223
|
end
|
272
224
|
|
273
225
|
# Public: Convience method for Logger replacement
|
@@ -285,7 +237,7 @@ module Scrolls
|
|
285
237
|
#
|
286
238
|
def fatal(data, &blk)
|
287
239
|
data = data.merge(:level => "error") if data.is_a?(Hash)
|
288
|
-
|
240
|
+
@log.log(data, &blk)
|
289
241
|
end
|
290
242
|
|
291
243
|
# Public: Convience method for Logger replacement
|
@@ -303,7 +255,7 @@ module Scrolls
|
|
303
255
|
#
|
304
256
|
def info(data, &blk)
|
305
257
|
data = data.merge(:level => "info") if data.is_a?(Hash)
|
306
|
-
|
258
|
+
@log.log(data, &blk)
|
307
259
|
end
|
308
260
|
|
309
261
|
# Public: Convience method for Logger replacement
|
@@ -321,7 +273,7 @@ module Scrolls
|
|
321
273
|
#
|
322
274
|
def warn(data, &blk)
|
323
275
|
data = data.merge(:level => "notice") if data.is_a?(Hash)
|
324
|
-
|
276
|
+
@log.log(data, &blk)
|
325
277
|
end
|
326
278
|
|
327
279
|
# Public: Convience method for Logger replacement
|
@@ -339,7 +291,13 @@ module Scrolls
|
|
339
291
|
#
|
340
292
|
def unknown(data, &blk)
|
341
293
|
data = data.merge(:level => "alert") if data.is_a?(Hash)
|
342
|
-
|
294
|
+
@log.log(data, &blk)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Internal: The Logger initialized by #init
|
298
|
+
#
|
299
|
+
def internal
|
300
|
+
@log
|
343
301
|
end
|
344
302
|
|
345
303
|
end
|
data/lib/scrolls/iolog.rb
CHANGED
@@ -0,0 +1,297 @@
|
|
1
|
+
require "scrolls/parser"
|
2
|
+
require "scrolls/iolog"
|
3
|
+
require "scrolls/syslog"
|
4
|
+
|
5
|
+
module Scrolls
|
6
|
+
class TimeUnitError < RuntimeError; end
|
7
|
+
|
8
|
+
class GlobalContext
|
9
|
+
attr_reader :context
|
10
|
+
def initialize(context)
|
11
|
+
@context = context || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
@context
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Log
|
20
|
+
LOG_FACILITY = ENV['LOG_FACILITY'] || Syslog::LOG_USER
|
21
|
+
LOG_FACILITY_MAP = {
|
22
|
+
"auth" => Syslog::LOG_AUTH,
|
23
|
+
"authpriv" => Syslog::LOG_AUTHPRIV,
|
24
|
+
"cron" => Syslog::LOG_CRON,
|
25
|
+
"daemon" => Syslog::LOG_DAEMON,
|
26
|
+
"ftp" => Syslog::LOG_FTP,
|
27
|
+
"kern" => Syslog::LOG_KERN,
|
28
|
+
"mail" => Syslog::LOG_MAIL,
|
29
|
+
"news" => Syslog::LOG_NEWS,
|
30
|
+
"syslog" => Syslog::LOG_SYSLOG,
|
31
|
+
"user" => Syslog::LOG_USER,
|
32
|
+
"uucp" => Syslog::LOG_UUCP,
|
33
|
+
"local0" => Syslog::LOG_LOCAL0,
|
34
|
+
"local1" => Syslog::LOG_LOCAL1,
|
35
|
+
"local2" => Syslog::LOG_LOCAL2,
|
36
|
+
"local3" => Syslog::LOG_LOCAL3,
|
37
|
+
"local4" => Syslog::LOG_LOCAL4,
|
38
|
+
"local5" => Syslog::LOG_LOCAL5,
|
39
|
+
"local6" => Syslog::LOG_LOCAL6,
|
40
|
+
"local7" => Syslog::LOG_LOCAL7,
|
41
|
+
}
|
42
|
+
|
43
|
+
LOG_LEVEL = (ENV['LOG_LEVEL'] || 6).to_i
|
44
|
+
LOG_LEVEL_MAP = {
|
45
|
+
"emergency" => 0,
|
46
|
+
"alert" => 1,
|
47
|
+
"critical" => 2,
|
48
|
+
"error" => 3,
|
49
|
+
"warning" => 4,
|
50
|
+
"notice" => 5,
|
51
|
+
"info" => 6,
|
52
|
+
"debug" => 7
|
53
|
+
}
|
54
|
+
|
55
|
+
attr_reader :logger
|
56
|
+
attr_accessor :exceptions, :timestamp
|
57
|
+
|
58
|
+
def initialize(options={})
|
59
|
+
@stream = options.fetch(:stream, sync_stream)
|
60
|
+
@facility = options.fetch(:facility, LOG_FACILITY)
|
61
|
+
@time_unit = options.fetch(:time_unit, "seconds")
|
62
|
+
@timestamp = options.fetch(:timestamp, false)
|
63
|
+
@exceptions = options.fetch(:exceptions, "single")
|
64
|
+
@global_ctx = options.fetch(:global_context, {})
|
65
|
+
|
66
|
+
setup!
|
67
|
+
end
|
68
|
+
|
69
|
+
def context
|
70
|
+
Thread.current[:scrolls_context] ||= {}
|
71
|
+
end
|
72
|
+
|
73
|
+
def context=(h)
|
74
|
+
Thread.current[:scrolls_context] = h
|
75
|
+
end
|
76
|
+
|
77
|
+
def stream
|
78
|
+
@stream
|
79
|
+
end
|
80
|
+
|
81
|
+
def stream=(stream)
|
82
|
+
# Return early to avoid setup
|
83
|
+
return if stream == @stream
|
84
|
+
|
85
|
+
@stream = stream
|
86
|
+
setup_stream
|
87
|
+
end
|
88
|
+
|
89
|
+
def facility
|
90
|
+
@facility ||= LOG_FACILITY
|
91
|
+
end
|
92
|
+
|
93
|
+
def facility=(f)
|
94
|
+
if f
|
95
|
+
@facility = LOG_FACILITY_MAP[f]
|
96
|
+
# Assume we are using syslog and set it up again
|
97
|
+
@logger = Scrolls::SyslogLogger.new(progname, facility)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def time_unit
|
102
|
+
@time_unit
|
103
|
+
end
|
104
|
+
|
105
|
+
def time_unit=(u)
|
106
|
+
@time_unit = u
|
107
|
+
translate_time_unit
|
108
|
+
end
|
109
|
+
|
110
|
+
def global_context
|
111
|
+
@global_context.to_h
|
112
|
+
end
|
113
|
+
|
114
|
+
def log(data, &blk)
|
115
|
+
# If we get a string lets bring it into our structure.
|
116
|
+
if data.kind_of? String
|
117
|
+
rawhash = { "log_message" => data }
|
118
|
+
else
|
119
|
+
rawhash = data
|
120
|
+
end
|
121
|
+
|
122
|
+
if gc = @global_context.to_h
|
123
|
+
ctx = gc.merge(context)
|
124
|
+
logdata = ctx.merge(rawhash)
|
125
|
+
end
|
126
|
+
|
127
|
+
# By merging the logdata into the timestamp, rather than vice-versa, we
|
128
|
+
# ensure that the timestamp comes first in the Hash, and is placed first
|
129
|
+
# on the output, which helps with readability.
|
130
|
+
logdata = { :now => Time.now.utc }.merge(logdata) if prepend_timestamp?
|
131
|
+
|
132
|
+
unless blk
|
133
|
+
write(logdata)
|
134
|
+
else
|
135
|
+
start = Time.now
|
136
|
+
res = nil
|
137
|
+
log(logdata.merge(:at => "start"))
|
138
|
+
begin
|
139
|
+
res = yield
|
140
|
+
rescue StandardError => e
|
141
|
+
log(logdata.merge(
|
142
|
+
:at => "exception",
|
143
|
+
:reraise => true,
|
144
|
+
:class => e.class,
|
145
|
+
:message => e.message,
|
146
|
+
:exception_id => e.object_id.abs,
|
147
|
+
:elapsed => calculate_time(start, Time.now)
|
148
|
+
))
|
149
|
+
raise e
|
150
|
+
end
|
151
|
+
log(logdata.merge(:at => "finish", :elapsed => calculate_time(start, Time.now)))
|
152
|
+
res
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def log_exception(data, e)
|
157
|
+
unless @defined
|
158
|
+
@stream = STDERR
|
159
|
+
setup_stream
|
160
|
+
end
|
161
|
+
|
162
|
+
# If we get a string lets bring it into our structure.
|
163
|
+
if data.kind_of? String
|
164
|
+
rawhash = { "log_message" => data }
|
165
|
+
else
|
166
|
+
rawhash = data
|
167
|
+
end
|
168
|
+
|
169
|
+
if gc = @global_context.to_h
|
170
|
+
logdata = gc.merge(rawhash)
|
171
|
+
end
|
172
|
+
|
173
|
+
excepdata = {
|
174
|
+
:at => "exception",
|
175
|
+
:class => e.class,
|
176
|
+
:message => e.message,
|
177
|
+
:exception_id => e.object_id.abs
|
178
|
+
}
|
179
|
+
|
180
|
+
if e.backtrace
|
181
|
+
if single_line_exceptions?
|
182
|
+
lines = e.backtrace.map { |line| line.gsub(/[`'"]/, "") }
|
183
|
+
|
184
|
+
if lines.length > 0
|
185
|
+
excepdata[:site] = lines.join('\n')
|
186
|
+
log(logdata.merge(excepdata))
|
187
|
+
end
|
188
|
+
else
|
189
|
+
log(logdata.merge(excepdata))
|
190
|
+
|
191
|
+
e.backtrace.each do |line|
|
192
|
+
log(logdata.merge(excepdata).merge(
|
193
|
+
:at => "exception",
|
194
|
+
:class => e.class,
|
195
|
+
:exception_id => e.object_id.abs,
|
196
|
+
:site => line.gsub(/[`'"]/, "")
|
197
|
+
))
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def with_context(prefix)
|
204
|
+
return unless block_given?
|
205
|
+
old = context
|
206
|
+
self.context = old.merge(prefix)
|
207
|
+
res = yield if block_given?
|
208
|
+
ensure
|
209
|
+
self.context = old
|
210
|
+
res
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
|
215
|
+
def setup!
|
216
|
+
build_global_context
|
217
|
+
prepend_timestamp?
|
218
|
+
setup_stream
|
219
|
+
single_line_exceptions?
|
220
|
+
translate_time_unit
|
221
|
+
end
|
222
|
+
|
223
|
+
def build_global_context
|
224
|
+
# Builds up an immutable object for our global_context
|
225
|
+
# This is not backwards compatiable and was introduced after 0.3.7.
|
226
|
+
# Removes ability to add to global context once we initialize our
|
227
|
+
# logging object. This also deprecates #add_global_context.
|
228
|
+
@global_context = GlobalContext.new(@global_ctx)
|
229
|
+
@global_context.freeze
|
230
|
+
end
|
231
|
+
|
232
|
+
def prepend_timestamp?
|
233
|
+
@timestamp
|
234
|
+
end
|
235
|
+
|
236
|
+
def setup_stream
|
237
|
+
unless @stream == STDOUT
|
238
|
+
@defined = true
|
239
|
+
end
|
240
|
+
|
241
|
+
if @stream == "syslog"
|
242
|
+
@logger = Scrolls::SyslogLogger.new(progname, facility)
|
243
|
+
else
|
244
|
+
@logger = sync_stream(@stream)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def single_line_exceptions?
|
249
|
+
return false if @exceptions == "multi"
|
250
|
+
true
|
251
|
+
end
|
252
|
+
|
253
|
+
def translate_time_unit
|
254
|
+
unless %w{s ms seconds milliseconds}.include? @time_unit
|
255
|
+
raise TimeUnitError, "Specify the following: s, ms, seconds, milliseconds"
|
256
|
+
end
|
257
|
+
|
258
|
+
case @time_unit
|
259
|
+
when %w{s seconds}
|
260
|
+
@t = 1.0
|
261
|
+
when %w{ms milliseconds}
|
262
|
+
@t = 1000.0
|
263
|
+
else
|
264
|
+
@t = 1.0
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def sync_stream(out = STDOUT)
|
269
|
+
IOLog.new(out)
|
270
|
+
end
|
271
|
+
|
272
|
+
def progname
|
273
|
+
File.basename($0)
|
274
|
+
end
|
275
|
+
|
276
|
+
def calculate_time(start, finish)
|
277
|
+
translate_time_unit unless @t
|
278
|
+
((finish - start).to_f * @t)
|
279
|
+
end
|
280
|
+
|
281
|
+
def log_level_ok?(level)
|
282
|
+
if level
|
283
|
+
LOG_LEVEL_MAP[level.to_s] <= LOG_LEVEL
|
284
|
+
else
|
285
|
+
true
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def write(data)
|
290
|
+
if log_level_ok?(data[:level])
|
291
|
+
msg = Scrolls::Parser.unparse(data)
|
292
|
+
logger.log(msg)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
end
|
data/lib/scrolls/version.rb
CHANGED
data/test/test_parser.rb
CHANGED
data/test/test_scrolls.rb
CHANGED
@@ -1,44 +1,38 @@
|
|
1
|
-
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
2
|
|
3
3
|
class TestScrolls < Test::Unit::TestCase
|
4
4
|
def setup
|
5
5
|
@out = StringIO.new
|
6
|
-
Scrolls.init(
|
6
|
+
Scrolls.init(
|
7
|
+
:stream => @out
|
8
|
+
)
|
7
9
|
end
|
8
10
|
|
9
11
|
def teardown
|
10
|
-
Scrolls.global_context({})
|
11
|
-
# Reset our syslog context
|
12
|
-
Scrolls.facility = Scrolls::LOG_FACILITY
|
13
|
-
Scrolls.add_timestamp = false
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
14
|
+
def test_default_construct
|
15
|
+
Scrolls.init
|
17
16
|
assert_equal Scrolls::IOLog, Scrolls.stream.class
|
18
17
|
end
|
19
18
|
|
20
19
|
def test_default_global_context
|
20
|
+
Scrolls.init(:stream => @out)
|
21
21
|
assert_equal Hash.new, Scrolls.global_context
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_setting_global_context
|
25
|
-
Scrolls.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_adding_to_global_context
|
32
|
-
Scrolls.global_context(:g => "g")
|
33
|
-
Scrolls.add_global_context(:h => "h")
|
25
|
+
Scrolls.init(
|
26
|
+
:stream => @out,
|
27
|
+
:global_context => {:g => "g"},
|
28
|
+
)
|
34
29
|
Scrolls.log(:d => "d")
|
35
|
-
|
36
|
-
assert_match /g=g.*h=h.*d=d/, global
|
30
|
+
assert_equal "g=g d=d\n", @out.string
|
37
31
|
end
|
38
32
|
|
39
33
|
def test_default_context
|
40
|
-
Scrolls.log(:
|
41
|
-
assert_equal Hash.new, Scrolls
|
34
|
+
Scrolls.log(:d => "d")
|
35
|
+
assert_equal Hash.new, Scrolls.internal.context
|
42
36
|
end
|
43
37
|
|
44
38
|
def test_setting_context
|
@@ -48,15 +42,19 @@ class TestScrolls < Test::Unit::TestCase
|
|
48
42
|
end
|
49
43
|
|
50
44
|
def test_all_the_contexts
|
51
|
-
Scrolls.
|
45
|
+
Scrolls.init(
|
46
|
+
:stream => @out,
|
47
|
+
:global_context => {:g => "g"},
|
48
|
+
)
|
52
49
|
Scrolls.log(:o => "o") do
|
53
50
|
Scrolls.context(:c => "c") do
|
54
51
|
Scrolls.log(:ic => "i")
|
55
52
|
end
|
56
53
|
Scrolls.log(:i => "i")
|
57
54
|
end
|
58
|
-
|
59
|
-
|
55
|
+
@out.truncate(37)
|
56
|
+
output = "g=g o=o at=start\ng=g c=c ic=i\ng=g i=i"
|
57
|
+
assert_equal output, @out.string
|
60
58
|
end
|
61
59
|
|
62
60
|
def test_deeply_nested_context
|
@@ -89,7 +87,7 @@ class TestScrolls < Test::Unit::TestCase
|
|
89
87
|
raise "Error from inside of context"
|
90
88
|
end
|
91
89
|
fail "Exception did not escape context block"
|
92
|
-
rescue
|
90
|
+
rescue
|
93
91
|
Scrolls.log(:o => 'o')
|
94
92
|
assert_equal "o=o\n", @out.string
|
95
93
|
end
|
@@ -107,6 +105,7 @@ class TestScrolls < Test::Unit::TestCase
|
|
107
105
|
def test_setting_incorrect_time_unit
|
108
106
|
assert_raise Scrolls::TimeUnitError do
|
109
107
|
Scrolls.time_unit = "years"
|
108
|
+
Scrolls.log(:tu => "yrs")
|
110
109
|
end
|
111
110
|
end
|
112
111
|
|
@@ -128,25 +127,25 @@ class TestScrolls < Test::Unit::TestCase
|
|
128
127
|
Scrolls.log_exception({:test => "exception"}, e)
|
129
128
|
end
|
130
129
|
|
131
|
-
|
132
|
-
|
133
|
-
assert_match /test=exception at=exception.*test_log_exception.*XX/,
|
134
|
-
oneline_backtrace
|
130
|
+
oneline_bt = @out.string.gsub("\n", 'XX')
|
131
|
+
assert_match(/test=exception at=exception.*test_log_exception.*XX/, oneline_bt)
|
135
132
|
end
|
136
133
|
|
137
|
-
def
|
138
|
-
Scrolls.single_line_exceptions =
|
134
|
+
def test_multi_line_exceptions
|
135
|
+
Scrolls.single_line_exceptions = "multi"
|
139
136
|
begin
|
140
137
|
raise Exception
|
141
138
|
rescue Exception => e
|
142
139
|
Scrolls.log_exception({:o => "o"}, e)
|
143
140
|
end
|
144
|
-
|
141
|
+
|
142
|
+
oneline_bt = @out.string.gsub("\n", 'XX')
|
143
|
+
assert_match(/o=o at=exception.*test_multi_line_exceptions.*XX/, oneline_bt)
|
145
144
|
end
|
146
145
|
|
147
146
|
def test_syslog_integration
|
148
147
|
Scrolls.stream = 'syslog'
|
149
|
-
assert_equal Scrolls::SyslogLogger, Scrolls.
|
148
|
+
assert_equal Scrolls::SyslogLogger, Scrolls.internal.logger.class
|
150
149
|
end
|
151
150
|
|
152
151
|
def test_syslog_facility
|
@@ -162,13 +161,7 @@ class TestScrolls < Test::Unit::TestCase
|
|
162
161
|
def test_setting_syslog_facility_after_instantiation
|
163
162
|
Scrolls.stream = 'syslog'
|
164
163
|
Scrolls.facility = 'local7'
|
165
|
-
assert_match
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_logging_message_with_syslog
|
169
|
-
Scrolls.stream = 'syslog'
|
170
|
-
Scrolls.facility = 'local7'
|
171
|
-
Scrolls.log "scrolls test"
|
164
|
+
assert_match(/facility=184/, Scrolls.internal.logger.inspect)
|
172
165
|
end
|
173
166
|
|
174
167
|
def test_add_timestamp
|
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.
|
4
|
+
version: 0.9.0.pre
|
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-08-
|
11
|
+
date: 2017-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Logging, easier, more consistent.
|
14
14
|
email:
|
@@ -25,15 +25,14 @@ files:
|
|
25
25
|
- docs/global-context.md
|
26
26
|
- docs/syslog.md
|
27
27
|
- lib/scrolls.rb
|
28
|
-
- lib/scrolls/atomic.rb
|
29
28
|
- lib/scrolls/iolog.rb
|
30
29
|
- lib/scrolls/log.rb
|
30
|
+
- lib/scrolls/logger.rb
|
31
31
|
- lib/scrolls/parser.rb
|
32
32
|
- lib/scrolls/syslog.rb
|
33
33
|
- lib/scrolls/utils.rb
|
34
34
|
- lib/scrolls/version.rb
|
35
35
|
- scrolls.gemspec
|
36
|
-
- test/test_atomic.rb
|
37
36
|
- test/test_helper.rb
|
38
37
|
- test/test_parser.rb
|
39
38
|
- test/test_scrolls.rb
|
@@ -52,9 +51,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
51
|
version: '0'
|
53
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
53
|
requirements:
|
55
|
-
- - "
|
54
|
+
- - ">"
|
56
55
|
- !ruby/object:Gem::Version
|
57
|
-
version:
|
56
|
+
version: 1.3.1
|
58
57
|
requirements: []
|
59
58
|
rubyforge_project:
|
60
59
|
rubygems_version: 2.6.11
|
@@ -62,7 +61,6 @@ signing_key:
|
|
62
61
|
specification_version: 4
|
63
62
|
summary: When do we log? All the time.
|
64
63
|
test_files:
|
65
|
-
- test/test_atomic.rb
|
66
64
|
- test/test_helper.rb
|
67
65
|
- test/test_parser.rb
|
68
66
|
- test/test_scrolls.rb
|
data/lib/scrolls/atomic.rb
DELETED
@@ -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/test/test_atomic.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class TestAtomic < Test::Unit::TestCase
|
4
|
-
def test_construct
|
5
|
-
atomic = Scrolls::Atomic.new
|
6
|
-
assert_equal nil, atomic.value
|
7
|
-
|
8
|
-
atomic = Scrolls::Atomic.new(0)
|
9
|
-
assert_equal 0, atomic.value
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_value
|
13
|
-
atomic = Scrolls::Atomic.new(0)
|
14
|
-
atomic.value = 1
|
15
|
-
|
16
|
-
assert_equal 1, atomic.value
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_update
|
20
|
-
atomic = Scrolls::Atomic.new(1000)
|
21
|
-
res = atomic.update {|v| v + 1}
|
22
|
-
|
23
|
-
assert_equal 1001, atomic.value
|
24
|
-
assert_equal 1001, res
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_update_retries
|
28
|
-
tries = 0
|
29
|
-
atomic = Scrolls::Atomic.new(1000)
|
30
|
-
atomic.update{|v| tries += 1 ; atomic.value = 1001 ; v + 1}
|
31
|
-
assert_equal 2, tries
|
32
|
-
end
|
33
|
-
end
|