scrolls 0.3.9 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d70168aa379a644e25091bce26f7ce86e3ffb9d6564a97246d3e6251fbe353ad
|
4
|
+
data.tar.gz: 813b7fc23789ea3436e4f18f1be99f601ec034fbf737e70bfbf8705948676aed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a419f6a9473eeaa2f7957db5d30ee5d1977149861542a7e28feb7e126f7413ee6a9876ff76e30414620fcf8a43eaa0abafe79408b23db0c4415a06f048ad5653
|
7
|
+
data.tar.gz: 3be6e7a630e21b35be17bf59ac480a40f2b98eec106c27dacfc245765574e317c680b5587a55064e5883b420c272ca1cdab687ac2052316fdbf53efdde7f9e45
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -20,26 +20,65 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
Scrolls follows the belief that logs should be treated as data. One way to think of them is the blood of your infrastructure. Logs are a realtime view of what is happening on your systems.
|
22
22
|
|
23
|
-
##
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### 0.9.0 and later
|
24
26
|
|
25
|
-
|
27
|
+
```ruby
|
28
|
+
require 'scrolls'
|
26
29
|
|
27
|
-
|
30
|
+
Scrolls.init(
|
31
|
+
timestamp: true,
|
32
|
+
global_context: {app: "scrolls", deploy: "production"},
|
33
|
+
exceptions: "multi"
|
34
|
+
)
|
28
35
|
|
29
|
-
|
36
|
+
Scrolls.log(at: "test")
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
* Misc Features
|
38
|
+
Scrolls.context(context: "block") do
|
39
|
+
Scrolls.log(at: "exec")
|
40
|
+
end
|
35
41
|
|
36
|
-
|
42
|
+
begin
|
43
|
+
raise
|
44
|
+
rescue Exception => e
|
45
|
+
Scrolls.log_exception(e, at: "raise")
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
You can also use `Scrolls#log` and `Scrolls#log_exception` without initalizing:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
require 'scrolls'
|
53
|
+
|
54
|
+
Scrolls.log(test: "test")
|
55
|
+
```
|
56
|
+
|
57
|
+
### Defaults
|
58
|
+
|
59
|
+
Here are the defaults `Scrolls#init`:
|
60
|
+
|
61
|
+
```
|
62
|
+
stream: STDOUT
|
63
|
+
facility: Syslog::LOG_USER
|
64
|
+
time_unit: "seconds"
|
65
|
+
timestamp: false
|
66
|
+
exceptions: "single"
|
67
|
+
global_context: {}
|
68
|
+
syslog_options: Syslog::LOG_PID|Syslog::LOG_CONS
|
69
|
+
escape_keys: false
|
70
|
+
strict_logfmt: false
|
71
|
+
```
|
72
|
+
|
73
|
+
## Older Versions
|
74
|
+
|
75
|
+
### Pre 0.9.0
|
37
76
|
|
38
77
|
```ruby
|
39
78
|
require 'scrolls'
|
40
79
|
|
41
80
|
Scrolls.add_timestamp = true
|
42
|
-
Scrolls.global_context(:app => "scrolls", :deploy =>
|
81
|
+
Scrolls.global_context(:app => "scrolls", :deploy => "production")
|
43
82
|
|
44
83
|
Scrolls.log(:at => "test")
|
45
84
|
|
@@ -57,10 +96,10 @@ end
|
|
57
96
|
Produces:
|
58
97
|
|
59
98
|
```
|
60
|
-
now="
|
61
|
-
now="
|
62
|
-
now="
|
63
|
-
now="
|
99
|
+
now="2017-09-01T00:37:13Z" app=scrolls deploy=production at=test
|
100
|
+
now="2017-09-01T00:37:13Z" app=scrolls deploy=production context=block at=exec
|
101
|
+
now="2017-09-01T00:37:13Z" app=scrolls deploy=production at=exception class=RuntimeError exception_id=70149797587080
|
102
|
+
now="2017-09-01T00:37:13Z" app=scrolls deploy=production at=exception class=RuntimeError exception_id=70149797587080 site="./test-scrolls.rb:16:in <main>"
|
64
103
|
```
|
65
104
|
|
66
105
|
## History
|
data/Rakefile
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
+
|
2
3
|
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
3
5
|
|
4
6
|
ENV['TESTOPTS'] = "-v"
|
5
7
|
|
6
|
-
require "rake/testtask"
|
7
8
|
Rake::TestTask.new do |t|
|
8
|
-
t.
|
9
|
+
t.test_files = FileList["test/**/test_*.rb"]
|
10
|
+
t.verbose = true
|
9
11
|
end
|
10
12
|
|
11
13
|
task :default => :test
|
data/docs/global-context.md
CHANGED
data/docs/syslog.md
CHANGED
@@ -6,6 +6,14 @@ By default Scrolls writes log messages to `STDOUT`. With the release of [v0.2.8]
|
|
6
6
|
Scrolls.stream = "syslog"
|
7
7
|
```
|
8
8
|
|
9
|
+
Or using `Scrolls#init` in versions 0.9.0 and after:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
Scrolls.init(
|
13
|
+
stream: "syslog"
|
14
|
+
)
|
15
|
+
```
|
16
|
+
|
9
17
|
This defaults to syslog facility USER and log level ERROR. You can adjust the log facility like so:
|
10
18
|
|
11
19
|
```ruby
|
@@ -14,4 +22,9 @@ Scrolls.facility = "local7"
|
|
14
22
|
|
15
23
|
Scrolls generally doesn't care about log levels. The library defaults to ERROR (or 3), but ultimately is of the opinion that levels are useless. The reasoning behind this is that applications should log useful data, all of the time. Debugging data is great for development, but should never be deployed. The richness of structured logging allows exceptions and error messages to sit along side the context of the data in which the error was thrown, there is no need to send to an "emergency" level.
|
16
24
|
|
17
|
-
With that said, if one wanted to adjust the log level, you can set an environment variable `LOG_LEVEL
|
25
|
+
With that said, if one wanted to adjust the log level, you can set an environment variable `LOG_LEVEL` or use one of the level methods. This allows this particular feature to be rather fluid throughout your application.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Scrolls.info(d: "data")
|
29
|
+
Scrolls.warn(d: "data")
|
30
|
+
```
|
@@ -0,0 +1,323 @@
|
|
1
|
+
require "syslog"
|
2
|
+
|
3
|
+
require "scrolls/parser"
|
4
|
+
require "scrolls/iologger"
|
5
|
+
require "scrolls/sysloglogger"
|
6
|
+
require "scrolls/utils"
|
7
|
+
|
8
|
+
module Scrolls
|
9
|
+
# Default log facility
|
10
|
+
LOG_FACILITY = ENV['LOG_FACILITY'] || Syslog::LOG_USER
|
11
|
+
|
12
|
+
# Default log level
|
13
|
+
LOG_LEVEL = (ENV['LOG_LEVEL'] || 6).to_i
|
14
|
+
|
15
|
+
# Default syslog options
|
16
|
+
SYSLOG_OPTIONS = Syslog::LOG_PID|Syslog::LOG_CONS
|
17
|
+
|
18
|
+
class TimeUnitError < RuntimeError; end
|
19
|
+
class LogLevelError < StandardError; end
|
20
|
+
|
21
|
+
# Top level class to hold our global context
|
22
|
+
#
|
23
|
+
# Global context is defined using Scrolls#init
|
24
|
+
class GlobalContext
|
25
|
+
def initialize(ctx)
|
26
|
+
@ctx = ctx || {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
@ctx
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Logger
|
35
|
+
|
36
|
+
attr_reader :logger
|
37
|
+
attr_accessor :exceptions, :timestamp
|
38
|
+
|
39
|
+
def initialize(options={})
|
40
|
+
@stream = options.fetch(:stream, STDOUT)
|
41
|
+
@log_facility = options.fetch(:facility, LOG_FACILITY)
|
42
|
+
@time_unit = options.fetch(:time_unit, "seconds")
|
43
|
+
@timestamp = options.fetch(:timestamp, false)
|
44
|
+
@exceptions = options.fetch(:exceptions, "single")
|
45
|
+
@global_ctx = options.fetch(:global_context, {})
|
46
|
+
@syslog_opts = options.fetch(:syslog_options, SYSLOG_OPTIONS)
|
47
|
+
@escape_keys = options.fetch(:escape_keys, false)
|
48
|
+
@strict_logfmt = options.fetch(:strict_logfmt, false)
|
49
|
+
|
50
|
+
# Our main entry point to ensure our options are setup properly
|
51
|
+
setup!
|
52
|
+
end
|
53
|
+
|
54
|
+
def context
|
55
|
+
if Thread.current.thread_variables.include?(:scrolls_context)
|
56
|
+
Thread.current.thread_variable_get(:scrolls_context)
|
57
|
+
else
|
58
|
+
Thread.current.thread_variable_set(:scrolls_context, {})
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def context=(h)
|
63
|
+
Thread.current.thread_variable_set(:scrolls_context, h || {})
|
64
|
+
end
|
65
|
+
|
66
|
+
def stream
|
67
|
+
@stream
|
68
|
+
end
|
69
|
+
|
70
|
+
def stream=(s)
|
71
|
+
# Return early to avoid setup
|
72
|
+
return if s == @stream
|
73
|
+
|
74
|
+
@stream = s
|
75
|
+
setup_stream
|
76
|
+
end
|
77
|
+
|
78
|
+
def escape_keys?
|
79
|
+
@escape_keys
|
80
|
+
end
|
81
|
+
|
82
|
+
def strict_logfmt?
|
83
|
+
@strict_logfmt
|
84
|
+
end
|
85
|
+
|
86
|
+
def syslog_options
|
87
|
+
@syslog_opts
|
88
|
+
end
|
89
|
+
|
90
|
+
def facility
|
91
|
+
@facility
|
92
|
+
end
|
93
|
+
|
94
|
+
def facility=(f)
|
95
|
+
if f
|
96
|
+
setup_facility(f)
|
97
|
+
# If we are using syslog, we need to setup our connection again
|
98
|
+
if stream == "syslog"
|
99
|
+
@logger = Scrolls::SyslogLogger.new(
|
100
|
+
progname,
|
101
|
+
syslog_options,
|
102
|
+
facility
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def time_unit
|
109
|
+
@time_unit
|
110
|
+
end
|
111
|
+
|
112
|
+
def time_unit=(u)
|
113
|
+
@time_unit = u
|
114
|
+
setup_time_unit
|
115
|
+
end
|
116
|
+
|
117
|
+
def global_context
|
118
|
+
@global_context.to_h
|
119
|
+
end
|
120
|
+
|
121
|
+
def log(data, &blk)
|
122
|
+
# If we get a string lets bring it into our structure.
|
123
|
+
if data.kind_of? String
|
124
|
+
rawhash = { "log_message" => data }
|
125
|
+
else
|
126
|
+
rawhash = data
|
127
|
+
end
|
128
|
+
|
129
|
+
if gc = @global_context.to_h
|
130
|
+
ctx = gc.merge(context)
|
131
|
+
logdata = ctx.merge(rawhash)
|
132
|
+
end
|
133
|
+
|
134
|
+
# By merging the logdata into the timestamp, rather than vice-versa, we
|
135
|
+
# ensure that the timestamp comes first in the Hash, and is placed first
|
136
|
+
# on the output, which helps with readability.
|
137
|
+
logdata = { :now => Time.now.utc }.merge(logdata) if prepend_timestamp?
|
138
|
+
|
139
|
+
unless blk
|
140
|
+
write(logdata)
|
141
|
+
else
|
142
|
+
start = Time.now
|
143
|
+
res = nil
|
144
|
+
log(logdata.merge(:at => "start"))
|
145
|
+
begin
|
146
|
+
res = yield
|
147
|
+
rescue StandardError => e
|
148
|
+
logdata.merge!({
|
149
|
+
at: "exception",
|
150
|
+
reraise: true,
|
151
|
+
class: e.class,
|
152
|
+
message: e.message,
|
153
|
+
exception_id: e.object_id.abs,
|
154
|
+
elapsed: calculate_time(start, Time.now)
|
155
|
+
})
|
156
|
+
logdata.delete_if { |k,v| k if v == "" }
|
157
|
+
log(logdata)
|
158
|
+
raise e
|
159
|
+
end
|
160
|
+
log(logdata.merge(:at => "finish", :elapsed => calculate_time(start, Time.now)))
|
161
|
+
res
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def log_exception(e, data=nil)
|
166
|
+
unless @defined
|
167
|
+
@stream = STDERR
|
168
|
+
setup_stream
|
169
|
+
end
|
170
|
+
|
171
|
+
# We check our arguments for type
|
172
|
+
case data
|
173
|
+
when String
|
174
|
+
rawhash = { "log_message" => data }
|
175
|
+
when Hash
|
176
|
+
rawhash = data
|
177
|
+
else
|
178
|
+
rawhash = {}
|
179
|
+
end
|
180
|
+
|
181
|
+
if gc = @global_context.to_h
|
182
|
+
logdata = gc.merge(rawhash)
|
183
|
+
end
|
184
|
+
|
185
|
+
excepdata = {
|
186
|
+
at: "exception",
|
187
|
+
class: e.class,
|
188
|
+
message: e.message,
|
189
|
+
exception_id: e.object_id.abs
|
190
|
+
}
|
191
|
+
|
192
|
+
excepdata.delete_if { |k,v| k if v == "" }
|
193
|
+
|
194
|
+
if e.backtrace
|
195
|
+
if single_line_exceptions?
|
196
|
+
lines = e.backtrace.map { |line| line.gsub(/[`'"]/, "") }
|
197
|
+
|
198
|
+
if lines.length > 0
|
199
|
+
excepdata[:site] = lines.join('\n')
|
200
|
+
log(logdata.merge(excepdata))
|
201
|
+
end
|
202
|
+
else
|
203
|
+
log(logdata.merge(excepdata))
|
204
|
+
|
205
|
+
e.backtrace.each do |line|
|
206
|
+
log(logdata.merge(excepdata).merge(
|
207
|
+
:at => "exception",
|
208
|
+
:class => e.class,
|
209
|
+
:exception_id => e.object_id.abs,
|
210
|
+
:site => line.gsub(/[`'"]/, "")
|
211
|
+
))
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def with_context(prefix)
|
218
|
+
return unless block_given?
|
219
|
+
old = context
|
220
|
+
self.context = old.merge(prefix)
|
221
|
+
res = yield if block_given?
|
222
|
+
ensure
|
223
|
+
self.context = old
|
224
|
+
res
|
225
|
+
end
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
def setup!
|
230
|
+
setup_global_context
|
231
|
+
prepend_timestamp?
|
232
|
+
setup_facility
|
233
|
+
setup_stream
|
234
|
+
single_line_exceptions?
|
235
|
+
setup_time_unit
|
236
|
+
end
|
237
|
+
|
238
|
+
def setup_global_context
|
239
|
+
# Builds up an immutable object for our global_context
|
240
|
+
# This is not backwards compatiable and was introduced after 0.3.7.
|
241
|
+
# Removes ability to add to global context once we initialize our
|
242
|
+
# logging object. This also deprecates #add_global_context.
|
243
|
+
@global_context = GlobalContext.new(@global_ctx)
|
244
|
+
@global_context.freeze
|
245
|
+
end
|
246
|
+
|
247
|
+
def prepend_timestamp?
|
248
|
+
@timestamp
|
249
|
+
end
|
250
|
+
|
251
|
+
def setup_facility(f=nil)
|
252
|
+
if f
|
253
|
+
@facility = LOG_FACILITY_MAP.fetch(f, LOG_FACILITY)
|
254
|
+
else
|
255
|
+
@facility = LOG_FACILITY_MAP.fetch(@log_facility, LOG_FACILITY)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def setup_stream
|
260
|
+
unless @stream == STDOUT
|
261
|
+
# Set this so we know we aren't using our default stream
|
262
|
+
@defined = true
|
263
|
+
end
|
264
|
+
|
265
|
+
if @stream == "syslog"
|
266
|
+
@logger = Scrolls::SyslogLogger.new(
|
267
|
+
progname,
|
268
|
+
syslog_options,
|
269
|
+
facility
|
270
|
+
)
|
271
|
+
else
|
272
|
+
@logger = IOLogger.new(@stream)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def single_line_exceptions?
|
277
|
+
return false if @exceptions == "multi"
|
278
|
+
true
|
279
|
+
end
|
280
|
+
|
281
|
+
def setup_time_unit
|
282
|
+
unless %w{s ms seconds milliseconds}.include? @time_unit
|
283
|
+
raise TimeUnitError, "Specify the following: s, ms, seconds, milliseconds"
|
284
|
+
end
|
285
|
+
|
286
|
+
case @time_unit
|
287
|
+
when %w{s seconds}
|
288
|
+
@t = 1.0
|
289
|
+
when %w{ms milliseconds}
|
290
|
+
@t = 1000.0
|
291
|
+
else
|
292
|
+
@t = 1.0
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# We need this for our syslog setup
|
297
|
+
def progname
|
298
|
+
File.basename($0)
|
299
|
+
end
|
300
|
+
|
301
|
+
def calculate_time(start, finish)
|
302
|
+
translate_time_unit unless @t
|
303
|
+
((finish - start).to_f * @t)
|
304
|
+
end
|
305
|
+
|
306
|
+
def log_level_ok?(level)
|
307
|
+
if level
|
308
|
+
raise LogLevelError, "Log level unknown" unless LOG_LEVEL_MAP.key?(level)
|
309
|
+
LOG_LEVEL_MAP[level.to_s] <= LOG_LEVEL
|
310
|
+
else
|
311
|
+
true
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def write(data)
|
316
|
+
if log_level_ok?(data[:level])
|
317
|
+
msg = Scrolls::Parser.unparse(data, escape_keys=escape_keys?, strict_logfmt=strict_logfmt?)
|
318
|
+
@logger.log(msg)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
end
|
data/lib/scrolls/parser.rb
CHANGED
@@ -4,8 +4,10 @@ module Scrolls
|
|
4
4
|
module Parser
|
5
5
|
extend self
|
6
6
|
|
7
|
-
def unparse(data)
|
7
|
+
def unparse(data, escape_keys=false, strict_logfmt=false)
|
8
8
|
data.map do |(k,v)|
|
9
|
+
k = Scrolls::Utils.escape_chars(k) if escape_keys
|
10
|
+
|
9
11
|
if (v == true)
|
10
12
|
"#{k}=true"
|
11
13
|
elsif (v == false)
|
@@ -21,7 +23,7 @@ module Scrolls
|
|
21
23
|
has_single_quote = v.index("'")
|
22
24
|
has_double_quote = v.index('"')
|
23
25
|
if v =~ /[ =:,]/
|
24
|
-
if has_single_quote && has_double_quote
|
26
|
+
if (has_single_quote || strict_logfmt) && has_double_quote
|
25
27
|
v = '"' + v.gsub(/\\|"/) { |c| "\\#{c}" } + '"'
|
26
28
|
elsif has_double_quote
|
27
29
|
v = "'" + v.gsub('\\', '\\\\\\') + "'"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Scrolls
|
2
|
+
class SyslogLogger
|
3
|
+
def initialize(ident = 'scrolls',
|
4
|
+
options = Scrolls::SYSLOG_OPTIONS,
|
5
|
+
facility = Scrolls::LOG_FACILITY)
|
6
|
+
if Syslog.opened?
|
7
|
+
@syslog = Syslog.reopen(ident, options, facility)
|
8
|
+
else
|
9
|
+
@syslog = Syslog.open(ident, options, facility)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def log(data)
|
14
|
+
@syslog.log(Syslog::LOG_INFO, "%s", data)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/scrolls/utils.rb
CHANGED
@@ -1,19 +1,61 @@
|
|
1
1
|
module Scrolls
|
2
|
-
module Utils
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
# Helpful map of syslog facilities
|
4
|
+
LOG_FACILITY_MAP = {
|
5
|
+
"auth" => Syslog::LOG_AUTH,
|
6
|
+
"authpriv" => Syslog::LOG_AUTHPRIV,
|
7
|
+
"cron" => Syslog::LOG_CRON,
|
8
|
+
"daemon" => Syslog::LOG_DAEMON,
|
9
|
+
"ftp" => Syslog::LOG_FTP,
|
10
|
+
"kern" => Syslog::LOG_KERN,
|
11
|
+
"mail" => Syslog::LOG_MAIL,
|
12
|
+
"news" => Syslog::LOG_NEWS,
|
13
|
+
"syslog" => Syslog::LOG_SYSLOG,
|
14
|
+
"user" => Syslog::LOG_USER,
|
15
|
+
"uucp" => Syslog::LOG_UUCP,
|
16
|
+
"local0" => Syslog::LOG_LOCAL0,
|
17
|
+
"local1" => Syslog::LOG_LOCAL1,
|
18
|
+
"local2" => Syslog::LOG_LOCAL2,
|
19
|
+
"local3" => Syslog::LOG_LOCAL3,
|
20
|
+
"local4" => Syslog::LOG_LOCAL4,
|
21
|
+
"local5" => Syslog::LOG_LOCAL5,
|
22
|
+
"local6" => Syslog::LOG_LOCAL6,
|
23
|
+
"local7" => Syslog::LOG_LOCAL7,
|
24
|
+
}
|
25
|
+
|
26
|
+
# Helpful map of syslog log levels
|
27
|
+
LOG_LEVEL_MAP = {
|
28
|
+
"emerg" => 0, # Syslog::LOG_EMERG
|
29
|
+
"emergency" => 0, # Syslog::LOG_EMERG
|
30
|
+
"alert" => 1, # Syslog::LOG_ALERT
|
31
|
+
"crit" => 2, # Syslog::LOG_CRIT
|
32
|
+
"critical" => 2, # Syslog::LOG_CRIT
|
33
|
+
"error" => 3, # Syslog::LOG_ERR
|
34
|
+
"warn" => 4, # Syslog::LOG_WARNING
|
35
|
+
"warning" => 4, # Syslog::LOG_WARNING
|
36
|
+
"notice" => 5, # Syslog::LOG_NOTICE
|
37
|
+
"info" => 6, # Syslog::LOG_INFO
|
38
|
+
"debug" => 7 # Syslog::LOG_DEBUG
|
39
|
+
}
|
40
|
+
|
41
|
+
ESCAPE_CHAR = {
|
42
|
+
"&" => "&",
|
43
|
+
"<" => "<",
|
44
|
+
">" => ">",
|
45
|
+
"'" => "'",
|
46
|
+
'"' => """,
|
47
|
+
"/" => "/"
|
48
|
+
}
|
49
|
+
|
50
|
+
ESCAPE_CHAR_PATTERN = Regexp.union(*ESCAPE_CHAR.keys)
|
51
|
+
|
52
|
+
module Utils
|
11
53
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
54
|
+
def self.escape_chars(d)
|
55
|
+
if d.is_a?(String) and d =~ ESCAPE_CHAR_PATTERN
|
56
|
+
esc = d.to_s.gsub(ESCAPE_CHAR_PATTERN) {|c| ESCAPE_CHAR[c] }
|
57
|
+
else
|
58
|
+
esc = d
|
17
59
|
end
|
18
60
|
end
|
19
61
|
|
data/lib/scrolls/version.rb
CHANGED