scrolls 0.3.9 → 0.9.3
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 +5 -5
- data/Gemfile +2 -0
- data/README.md +53 -14
- data/Rakefile +4 -2
- data/docs/global-context.md +1 -1
- data/docs/syslog.md +14 -1
- data/lib/scrolls/{iolog.rb → iologger.rb} +4 -2
- data/lib/scrolls/logger.rb +323 -0
- data/lib/scrolls/parser.rb +4 -2
- data/lib/scrolls/sysloglogger.rb +17 -0
- data/lib/scrolls/utils.rb +55 -13
- data/lib/scrolls/version.rb +1 -1
- data/lib/scrolls.rb +57 -77
- data/test/test_helper.rb +4 -1
- data/test/test_parser.rb +17 -2
- data/test/test_scrolls.rb +58 -47
- metadata +6 -10
- data/lib/scrolls/atomic.rb +0 -59
- data/lib/scrolls/log.rb +0 -262
- data/lib/scrolls/syslog.rb +0 -46
- data/test/test_atomic.rb +0 -33
data/lib/scrolls/log.rb
DELETED
@@ -1,262 +0,0 @@
|
|
1
|
-
require "scrolls/parser"
|
2
|
-
require "scrolls/utils"
|
3
|
-
require "scrolls/iolog"
|
4
|
-
require "scrolls/syslog"
|
5
|
-
|
6
|
-
module Scrolls
|
7
|
-
|
8
|
-
class TimeUnitError < RuntimeError; end
|
9
|
-
|
10
|
-
module Log
|
11
|
-
extend self
|
12
|
-
|
13
|
-
extend Parser
|
14
|
-
extend Utils
|
15
|
-
|
16
|
-
LOG_LEVEL = (ENV['LOG_LEVEL'] || 6).to_i
|
17
|
-
LOG_LEVEL_MAP = {
|
18
|
-
"emergency" => 0,
|
19
|
-
"alert" => 1,
|
20
|
-
"critical" => 2,
|
21
|
-
"error" => 3,
|
22
|
-
"warning" => 4,
|
23
|
-
"notice" => 5,
|
24
|
-
"info" => 6,
|
25
|
-
"debug" => 7
|
26
|
-
}
|
27
|
-
|
28
|
-
def context
|
29
|
-
Thread.current[:scrolls_context] ||= {}
|
30
|
-
end
|
31
|
-
|
32
|
-
def context=(h)
|
33
|
-
Thread.current[:scrolls_context] = h
|
34
|
-
end
|
35
|
-
|
36
|
-
def global_context
|
37
|
-
get_global_context
|
38
|
-
end
|
39
|
-
|
40
|
-
def global_context=(data)
|
41
|
-
set_global_context(data)
|
42
|
-
end
|
43
|
-
|
44
|
-
def add_global_context(new_data)
|
45
|
-
default_global_context unless @global_context
|
46
|
-
@global_context.update { |previous_data| previous_data.merge(new_data) }
|
47
|
-
end
|
48
|
-
|
49
|
-
def facility=(f)
|
50
|
-
@facility = LOG_FACILITY_MAP[f] if f
|
51
|
-
if Scrolls::SyslogLogger.opened?
|
52
|
-
Scrolls::SyslogLogger.new(progname, facility)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def facility
|
57
|
-
@facility ||= default_log_facility
|
58
|
-
end
|
59
|
-
|
60
|
-
def stream=(out=nil)
|
61
|
-
@defined = out.nil? ? false : true
|
62
|
-
if out == 'syslog'
|
63
|
-
@stream = Scrolls::SyslogLogger.new(progname, facility)
|
64
|
-
else
|
65
|
-
@stream = sync_stream(out)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def stream
|
70
|
-
@stream ||= sync_stream
|
71
|
-
end
|
72
|
-
|
73
|
-
def time_unit=(u)
|
74
|
-
set_time_unit(u)
|
75
|
-
end
|
76
|
-
|
77
|
-
def time_unit
|
78
|
-
@tunit ||= default_time_unit
|
79
|
-
end
|
80
|
-
|
81
|
-
def add_timestamp=(b)
|
82
|
-
@add_timestamp = !!b
|
83
|
-
end
|
84
|
-
|
85
|
-
def add_timestamp
|
86
|
-
@add_timestamp || false
|
87
|
-
end
|
88
|
-
|
89
|
-
def single_line_exceptions=(b)
|
90
|
-
@single_line_exceptions = !!b
|
91
|
-
end
|
92
|
-
|
93
|
-
def single_line_exceptions?
|
94
|
-
@single_line_exceptions || false
|
95
|
-
end
|
96
|
-
|
97
|
-
def log(data, &blk)
|
98
|
-
# If we get a string lets bring it into our structure.
|
99
|
-
if data.kind_of? String
|
100
|
-
rawhash = { "log_message" => data }
|
101
|
-
else
|
102
|
-
rawhash = data
|
103
|
-
end
|
104
|
-
|
105
|
-
if gc = get_global_context
|
106
|
-
ctx = gc.merge(context)
|
107
|
-
logdata = ctx.merge(rawhash)
|
108
|
-
end
|
109
|
-
|
110
|
-
# By merging the logdata into the timestamp, rather than vice-versa, we
|
111
|
-
# ensure that the timestamp comes first in the Hash, and is placed first
|
112
|
-
# on the output, which helps with readability.
|
113
|
-
logdata = { :now => Time.now.utc }.merge(logdata) if add_timestamp
|
114
|
-
|
115
|
-
unless blk
|
116
|
-
write(logdata)
|
117
|
-
else
|
118
|
-
start = Time.now
|
119
|
-
res = nil
|
120
|
-
log(logdata.merge(:at => "start"))
|
121
|
-
begin
|
122
|
-
res = yield
|
123
|
-
rescue StandardError => e
|
124
|
-
log(logdata.merge(
|
125
|
-
:at => "exception",
|
126
|
-
:reraise => true,
|
127
|
-
:class => e.class,
|
128
|
-
:message => e.message,
|
129
|
-
:exception_id => e.object_id.abs,
|
130
|
-
:elapsed => calc_time(start, Time.now)
|
131
|
-
))
|
132
|
-
raise e
|
133
|
-
end
|
134
|
-
log(logdata.merge(:at => "finish", :elapsed => calc_time(start, Time.now)))
|
135
|
-
res
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def log_exception(data, e)
|
140
|
-
sync_stream(STDERR) unless @defined
|
141
|
-
|
142
|
-
# If we get a string lets bring it into our structure.
|
143
|
-
if data.kind_of? String
|
144
|
-
rawhash = { "log_message" => data }
|
145
|
-
else
|
146
|
-
rawhash = data
|
147
|
-
end
|
148
|
-
|
149
|
-
if gc = get_global_context
|
150
|
-
logdata = gc.merge(rawhash)
|
151
|
-
end
|
152
|
-
|
153
|
-
excepdata = {
|
154
|
-
:at => "exception",
|
155
|
-
:class => e.class,
|
156
|
-
:message => e.message,
|
157
|
-
:exception_id => e.object_id.abs
|
158
|
-
}
|
159
|
-
|
160
|
-
if e.backtrace
|
161
|
-
if single_line_exceptions?
|
162
|
-
btlines = []
|
163
|
-
e.backtrace.each do |line|
|
164
|
-
btlines << line.gsub(/[`'"]/, "")
|
165
|
-
end
|
166
|
-
|
167
|
-
if btlines.length > 0
|
168
|
-
squish = { :site => btlines.join('\n') }
|
169
|
-
log(logdata.merge(excepdata.merge(squish)))
|
170
|
-
end
|
171
|
-
else
|
172
|
-
log(logdata.merge(excepdata))
|
173
|
-
|
174
|
-
e.backtrace.each do |line|
|
175
|
-
log(logdata.merge(excepdata).merge(
|
176
|
-
:at => "exception",
|
177
|
-
:class => e.class,
|
178
|
-
:exception_id => e.object_id.abs,
|
179
|
-
:site => line.gsub(/[`'"]/, "")
|
180
|
-
))
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def with_context(prefix)
|
187
|
-
return unless block_given?
|
188
|
-
old = context
|
189
|
-
self.context = old.merge(prefix)
|
190
|
-
res = yield if block_given?
|
191
|
-
ensure
|
192
|
-
self.context = old
|
193
|
-
res
|
194
|
-
end
|
195
|
-
|
196
|
-
private
|
197
|
-
|
198
|
-
def get_global_context
|
199
|
-
default_global_context unless @global_context
|
200
|
-
@global_context.value
|
201
|
-
end
|
202
|
-
|
203
|
-
def set_global_context(data=nil)
|
204
|
-
default_global_context unless @global_context
|
205
|
-
@global_context.update { |_| data }
|
206
|
-
end
|
207
|
-
|
208
|
-
def default_global_context
|
209
|
-
@global_context = Atomic.new({})
|
210
|
-
end
|
211
|
-
|
212
|
-
def set_time_unit(u=nil)
|
213
|
-
unless ["ms","milli","milliseconds","s","seconds"].include?(u)
|
214
|
-
raise TimeUnitError, "Specify only 'seconds' or 'milliseconds'"
|
215
|
-
end
|
216
|
-
|
217
|
-
if ["ms", "milli", "milliseconds", 1000].include?(u)
|
218
|
-
@tunit = "milliseconds"
|
219
|
-
@t = 1000.0
|
220
|
-
else
|
221
|
-
default_time_unit
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def default_time_unit
|
226
|
-
@t = 1.0
|
227
|
-
@tunit = "seconds"
|
228
|
-
end
|
229
|
-
|
230
|
-
def calc_time(start, finish)
|
231
|
-
default_time_unit unless @t
|
232
|
-
((finish - start).to_f * @t)
|
233
|
-
end
|
234
|
-
|
235
|
-
def sync_stream(out = STDOUT)
|
236
|
-
IOLog.new(out)
|
237
|
-
end
|
238
|
-
|
239
|
-
def write(data)
|
240
|
-
if log_level_ok?(data[:level])
|
241
|
-
msg = unparse(data)
|
242
|
-
stream.log(msg)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
def log_level_ok?(level)
|
247
|
-
if level
|
248
|
-
LOG_LEVEL_MAP[level.to_s] <= LOG_LEVEL
|
249
|
-
else
|
250
|
-
true
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def progname
|
255
|
-
File.basename($0)
|
256
|
-
end
|
257
|
-
|
258
|
-
def default_log_facility
|
259
|
-
LOG_FACILITY
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
data/lib/scrolls/syslog.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'syslog'
|
2
|
-
|
3
|
-
module Scrolls
|
4
|
-
|
5
|
-
LOG_FACILITY = ENV['LOG_FACILITY'] || Syslog::LOG_USER
|
6
|
-
LOG_FACILITY_MAP = {
|
7
|
-
"auth" => Syslog::LOG_AUTH,
|
8
|
-
"authpriv" => Syslog::LOG_AUTHPRIV,
|
9
|
-
"cron" => Syslog::LOG_CRON,
|
10
|
-
"daemon" => Syslog::LOG_DAEMON,
|
11
|
-
"ftp" => Syslog::LOG_FTP,
|
12
|
-
"kern" => Syslog::LOG_KERN,
|
13
|
-
"mail" => Syslog::LOG_MAIL,
|
14
|
-
"news" => Syslog::LOG_NEWS,
|
15
|
-
"syslog" => Syslog::LOG_SYSLOG,
|
16
|
-
"user" => Syslog::LOG_USER,
|
17
|
-
"uucp" => Syslog::LOG_UUCP,
|
18
|
-
"local0" => Syslog::LOG_LOCAL0,
|
19
|
-
"local1" => Syslog::LOG_LOCAL1,
|
20
|
-
"local2" => Syslog::LOG_LOCAL2,
|
21
|
-
"local3" => Syslog::LOG_LOCAL3,
|
22
|
-
"local4" => Syslog::LOG_LOCAL4,
|
23
|
-
"local5" => Syslog::LOG_LOCAL5,
|
24
|
-
"local6" => Syslog::LOG_LOCAL6,
|
25
|
-
"local7" => Syslog::LOG_LOCAL7,
|
26
|
-
}
|
27
|
-
|
28
|
-
class SyslogLogger
|
29
|
-
def initialize(ident = 'scrolls', facility = Syslog::LOG_USER)
|
30
|
-
options = Syslog::LOG_PID|Syslog::LOG_CONS
|
31
|
-
if Syslog.opened?
|
32
|
-
@syslog = Syslog.reopen(ident, options, facility)
|
33
|
-
else
|
34
|
-
@syslog = Syslog.open(ident, options, facility)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def log(data)
|
39
|
-
@syslog.log(Syslog::LOG_INFO, "%s", data)
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.opened?
|
43
|
-
Syslog.opened?
|
44
|
-
end
|
45
|
-
end
|
46
|
-
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
|