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