madvertise-logging 0.1.0
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.
- data/.gitignore +17 -0
- data/.rvmrc +1 -0
- data/Gemfile +10 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +8 -0
- data/lib/madvertise-logging.rb +3 -0
- data/lib/madvertise/logging/improved_logger.rb +265 -0
- data/lib/madvertise/logging/multi_logger.rb +24 -0
- data/lib/madvertise/logging/version.rb +5 -0
- data/madvertise-logging.gemspec +20 -0
- data/spec/improved_logger_spec.rb +239 -0
- data/spec/multi_logger_spec.rb +27 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +26 -0
- data/tasks/rspec.rake +20 -0
- metadata +95 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create ruby-1.9.3-p0@madvertise-logging
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 madvertise Mobile Advertising GmbH
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Madvertise::Logging
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'madvertise-logging'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install madvertise-logging
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Madvertise
|
5
|
+
module Logging
|
6
|
+
class ImprovedLogger
|
7
|
+
|
8
|
+
attr_accessor :copy_to_stdout
|
9
|
+
attr_accessor :transaction_token
|
10
|
+
attr_accessor :progname
|
11
|
+
|
12
|
+
@severities = {
|
13
|
+
:debug => Logger::DEBUG,
|
14
|
+
:info => Logger::INFO,
|
15
|
+
:warn => Logger::WARN,
|
16
|
+
:error => Logger::ERROR,
|
17
|
+
:fatal => Logger::FATAL,
|
18
|
+
:unknown => Logger::UNKNOWN
|
19
|
+
}
|
20
|
+
|
21
|
+
@silencer = true
|
22
|
+
|
23
|
+
class << self
|
24
|
+
attr_reader :severities
|
25
|
+
attr_accessor :silencer
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(logfile = nil, progname = nil)
|
29
|
+
@copy_to_stdout = false
|
30
|
+
@progname = progname || File.basename($0)
|
31
|
+
self.logger = logfile || STDERR
|
32
|
+
end
|
33
|
+
|
34
|
+
# Silence the logger for the duration of the block.
|
35
|
+
def silence(temporary_level = :error)
|
36
|
+
if self.class.silencer
|
37
|
+
begin
|
38
|
+
old_level, self.level = self.level, temporary_level
|
39
|
+
yield self
|
40
|
+
ensure
|
41
|
+
self.level = old_level
|
42
|
+
end
|
43
|
+
else
|
44
|
+
yield self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def debug(msg)
|
49
|
+
add(:debug, msg)
|
50
|
+
end
|
51
|
+
|
52
|
+
def debug?
|
53
|
+
self.level == :debug
|
54
|
+
end
|
55
|
+
|
56
|
+
def info(msg)
|
57
|
+
add(:info, msg)
|
58
|
+
end
|
59
|
+
|
60
|
+
def info?
|
61
|
+
self.level == :info
|
62
|
+
end
|
63
|
+
|
64
|
+
def warn(msg)
|
65
|
+
add(:warn, msg)
|
66
|
+
end
|
67
|
+
|
68
|
+
def warn?
|
69
|
+
self.level == :warn
|
70
|
+
end
|
71
|
+
|
72
|
+
def error(msg)
|
73
|
+
add(:error, msg)
|
74
|
+
end
|
75
|
+
|
76
|
+
def error?
|
77
|
+
self.level == :error
|
78
|
+
end
|
79
|
+
|
80
|
+
def fatal(msg)
|
81
|
+
add(:fatal, msg)
|
82
|
+
end
|
83
|
+
|
84
|
+
def fatal?
|
85
|
+
self.level == :fatal
|
86
|
+
end
|
87
|
+
|
88
|
+
def unknown(msg)
|
89
|
+
add(:unknown, msg)
|
90
|
+
end
|
91
|
+
|
92
|
+
def unknown?
|
93
|
+
self.level == :unknown
|
94
|
+
end
|
95
|
+
|
96
|
+
def exception(e)
|
97
|
+
if e.is_a?(::Exception)
|
98
|
+
message = "EXCEPTION: #{e.message}: #{clean_trace(e.backtrace)}"
|
99
|
+
else
|
100
|
+
message = e
|
101
|
+
end
|
102
|
+
add(:error, message, true)
|
103
|
+
end
|
104
|
+
|
105
|
+
def add(severity, message, skip_caller = false)
|
106
|
+
message = "#{called(caller)}: #{message}" unless skip_caller
|
107
|
+
message = "[#{@transaction_token}] #{message}" if @transaction_token
|
108
|
+
|
109
|
+
self.logger.add(self.class.severities[severity]) { message }
|
110
|
+
|
111
|
+
STDOUT.puts(message) if self.copy_to_stdout && self.class.severities[severity] >= self.logger.level
|
112
|
+
end
|
113
|
+
|
114
|
+
def level
|
115
|
+
self.class.severities.invert[@logger.level]
|
116
|
+
end
|
117
|
+
|
118
|
+
def level=(level)
|
119
|
+
level = (Symbol === level ? self.class.severities[level] : level)
|
120
|
+
self.logger.level = level
|
121
|
+
end
|
122
|
+
|
123
|
+
def new_transaction(v)
|
124
|
+
@transaction_token = v
|
125
|
+
end
|
126
|
+
|
127
|
+
def end_transaction
|
128
|
+
@transaction_token = nil
|
129
|
+
end
|
130
|
+
|
131
|
+
def save_transaction(obj)
|
132
|
+
if @transaction_token && obj
|
133
|
+
@transactions ||= {}
|
134
|
+
@transactions[obj.object_id] = @transaction_token
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def restore_transaction(obj)
|
139
|
+
@transactions ||= {}
|
140
|
+
@transaction_token = @transactions.delete(obj.object_id) if obj
|
141
|
+
end
|
142
|
+
|
143
|
+
def logger
|
144
|
+
@logger ||= create_logger
|
145
|
+
end
|
146
|
+
|
147
|
+
def logger=(value)
|
148
|
+
@logger.close rescue nil
|
149
|
+
|
150
|
+
if value.is_a?(Logger)
|
151
|
+
@backend = :logger
|
152
|
+
@logger = value
|
153
|
+
elsif value.is_a?(Symbol)
|
154
|
+
@backend = value
|
155
|
+
@logger = create_logger
|
156
|
+
else
|
157
|
+
@backend = :logger
|
158
|
+
@logfile = value
|
159
|
+
@logger = create_logger
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def clean_trace(trace)
|
164
|
+
trace = trace.map { |l| l.gsub(ROOT, '') }
|
165
|
+
trace = trace.reject { |l| l =~ /gems\/madvertise-logging/ }
|
166
|
+
trace = trace.reject { |l| l =~ /vendor\/madvertise-logging/ }
|
167
|
+
trace
|
168
|
+
end
|
169
|
+
|
170
|
+
def close
|
171
|
+
case @backend
|
172
|
+
when :logger
|
173
|
+
self.logger.close
|
174
|
+
@logger = nil
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def buffer
|
179
|
+
if @backend == :buffer && @buffer
|
180
|
+
@buffer.string
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def called(trace)
|
187
|
+
l = trace.detect('unknown:0') do |l|
|
188
|
+
l.index(File.basename(__FILE__)).nil?
|
189
|
+
end
|
190
|
+
|
191
|
+
file, num, _ = l.split(':')
|
192
|
+
[ File.basename(file), num ].join(':')
|
193
|
+
end
|
194
|
+
|
195
|
+
def create_logger
|
196
|
+
case @backend
|
197
|
+
when :buffer
|
198
|
+
create_buffering_logger
|
199
|
+
when :syslog
|
200
|
+
create_syslog_logger
|
201
|
+
else
|
202
|
+
create_standard_logger
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def create_buffering_logger
|
207
|
+
@buffer = StringIO.new
|
208
|
+
Logger.new(@buffer).tap do |l|
|
209
|
+
l.formatter = Formatter.new
|
210
|
+
l.progname = progname
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def create_standard_logger
|
215
|
+
@logfile ||= STDERR
|
216
|
+
|
217
|
+
if @logfile.is_a?(String)
|
218
|
+
logdir = File.dirname(@logfile)
|
219
|
+
|
220
|
+
begin
|
221
|
+
FileUtils.mkdir_p(logdir)
|
222
|
+
rescue
|
223
|
+
STDERR.puts "#{logdir} not writable, using STDERR for logging"
|
224
|
+
@logfile = STDERR
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
Logger.new(@logfile).tap do |l|
|
229
|
+
l.formatter = Formatter.new
|
230
|
+
l.progname = progname
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def create_syslog_logger
|
235
|
+
begin
|
236
|
+
require 'syslogger'
|
237
|
+
Syslogger.new(progname, Syslog::LOG_PID, Syslog::LOG_LOCAL1)
|
238
|
+
rescue LoadError
|
239
|
+
self.logger = :logger
|
240
|
+
self.error("Couldn't load syslogger gem, reverting to standard logger")
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class Formatter
|
245
|
+
|
246
|
+
# YYYY:MM:DD HH:MM:SS.MS daemon_name(pid) level: message
|
247
|
+
@format = "%s %s(%d) [%s] %s\n"
|
248
|
+
|
249
|
+
class << self
|
250
|
+
attr_accessor :format
|
251
|
+
end
|
252
|
+
|
253
|
+
def call(severity, time, progname, msg)
|
254
|
+
self.class.format % [format_time( time ), progname, $$, severity, msg.to_s]
|
255
|
+
end
|
256
|
+
|
257
|
+
private
|
258
|
+
|
259
|
+
def format_time(time)
|
260
|
+
time.strftime("%Y-%m-%d %H:%M:%S.") + time.usec.to_s
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Madvertise
|
2
|
+
module Logging
|
3
|
+
class MultiLogger
|
4
|
+
def initialize(*loggers)
|
5
|
+
@loggers = loggers
|
6
|
+
end
|
7
|
+
|
8
|
+
def attach(logger)
|
9
|
+
logger.new_transaction(@loggers.first.transaction_token)
|
10
|
+
@loggers << logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def detach(logger)
|
14
|
+
@loggers.delete(logger)
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing(name, *args)
|
18
|
+
@loggers.each do |l|
|
19
|
+
l.send(name, *args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/madvertise/logging/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Benedikt Böhm"]
|
6
|
+
gem.email = ["benedikt.boehm@madvertise.com"]
|
7
|
+
gem.description = %q{Advanced logging classes with buffer backend, transactions, multi logger, etc}
|
8
|
+
gem.summary = %q{Advanced logging classes with buffer backend, transactions, multi logger, etc}
|
9
|
+
gem.homepage = "https://github.com/madvertise/logging"
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "madvertise-logging"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Madvertise::Logging::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency("bundler")
|
19
|
+
gem.add_development_dependency("rake")
|
20
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
include Madvertise::Logging
|
4
|
+
|
5
|
+
RSpec::Matchers.define :have_received_message do |expected|
|
6
|
+
match do |actual|
|
7
|
+
IO.readlines(actual).last.match(Regexp.new(expected))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ImprovedLogger do
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@logfile = "#{ROOT}/log/spec.log"
|
15
|
+
@logger = ImprovedLogger.new(@logfile)
|
16
|
+
@logger.level = :debug
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have a backend logger" do
|
20
|
+
@logger.logger.should_not be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should accept a different backend" do
|
24
|
+
l = Logger.new('/dev/null')
|
25
|
+
@logger.logger = l
|
26
|
+
@logger.logger.should == l
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to log to STDOUT as well" do
|
30
|
+
@logger.copy_to_stdout = true
|
31
|
+
STDOUT.should_receive(:puts).with(/test/)
|
32
|
+
|
33
|
+
@logger.debug "test"
|
34
|
+
@logfile.should have_received_message("test")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should log debug level messages" do
|
38
|
+
@logger.debug("Debug test")
|
39
|
+
@logfile.should have_received_message(/\[DEBUG\].*Debug test/)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return true if debug level is set" do
|
43
|
+
@logger.level = :debug
|
44
|
+
@logger.debug?.should be true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should log info level messages" do
|
48
|
+
@logger.info("Info test")
|
49
|
+
@logfile.should have_received_message(/\[INFO\].*Info test/)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return true if info level is set" do
|
53
|
+
@logger.level = :info
|
54
|
+
@logger.info?.should be true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should log warn level messages" do
|
58
|
+
@logger.warn("Warn test")
|
59
|
+
@logfile.should have_received_message(/\[WARN\].*Warn test/)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return true if warn level is set" do
|
63
|
+
@logger.level = :warn
|
64
|
+
@logger.warn?.should be true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should log error level messages" do
|
68
|
+
@logger.error("Err test")
|
69
|
+
@logfile.should have_received_message(/\[ERROR\].*Err test/)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return true if error level is set" do
|
73
|
+
@logger.level = :error
|
74
|
+
@logger.error?.should be true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should log fatal level messages" do
|
78
|
+
@logger.fatal("Fatal test")
|
79
|
+
|
80
|
+
@logfile.should have_received_message(/\[FATAL\].*Fatal test/)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return true if fatal level is set" do
|
84
|
+
@logger.level = :fatal
|
85
|
+
@logger.fatal?.should be true
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should log unknown level messages" do
|
89
|
+
@logger.unknown("Unknown test")
|
90
|
+
@logfile.should have_received_message(/\[ANY\].*Unknown test/)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return true if unknown level is set" do
|
94
|
+
@logger.level = :unknown
|
95
|
+
@logger.unknown?.should be true
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should log the caller file and line number" do
|
99
|
+
f = File.basename(__FILE__)
|
100
|
+
l = __LINE__ + 2
|
101
|
+
|
102
|
+
@logger.info("Caller test")
|
103
|
+
@logfile.should have_received_message("#{f}:#{l}:")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should log exceptions with daemon traces" do
|
107
|
+
fake_trace = [
|
108
|
+
"/home/jdoe/app/libexec/app.rb:1:in `foo'",
|
109
|
+
"/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
|
110
|
+
]
|
111
|
+
|
112
|
+
e = RuntimeError.new('Test error')
|
113
|
+
e.set_backtrace(fake_trace)
|
114
|
+
|
115
|
+
@logger.exception(e)
|
116
|
+
@logfile.should have_received_message("EXCEPTION: Test error")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should log exceptions without framework traces" do
|
120
|
+
fake_trace = [
|
121
|
+
"/home/jdoe/app/libexec/app.rb:1:in `foo'",
|
122
|
+
"/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
|
123
|
+
]
|
124
|
+
|
125
|
+
clean_trace = @logger.clean_trace(fake_trace)
|
126
|
+
clean_trace.should include("/home/jdoe/app/libexec/app.rb:1:in `foo'")
|
127
|
+
clean_trace.should_not include("/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'")
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should not handle a backtrace if object is not an exception" do
|
131
|
+
@logger.exception("not an exception object")
|
132
|
+
@logfile.should_not have_received_message("EXCEPTION:")
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should support reopening log files" do
|
136
|
+
@logger.close
|
137
|
+
|
138
|
+
FileUtils.rm(@logfile)
|
139
|
+
|
140
|
+
@logger.info('Reopen')
|
141
|
+
@logfile.should have_received_message("Reopen")
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should support silencing" do
|
145
|
+
@logger.silence do |logger|
|
146
|
+
logger.info "This should never be logged"
|
147
|
+
end
|
148
|
+
|
149
|
+
@logfile.should_not have_received_message("This should never be logged")
|
150
|
+
|
151
|
+
@logger.info "This should be logged"
|
152
|
+
@logfile.should have_received_message("This should be logged")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should not discard messages if silencer is disabled globally" do
|
156
|
+
ImprovedLogger.silencer = false
|
157
|
+
|
158
|
+
@logger.silence do |logger|
|
159
|
+
logger.info "This should actually be logged"
|
160
|
+
end
|
161
|
+
|
162
|
+
@logfile.should have_received_message("This should actually be logged")
|
163
|
+
|
164
|
+
ImprovedLogger.silencer = true
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should support a transaction token" do
|
168
|
+
token = "3d5e27f7-b97c-4adc-b1fd-adf1bd4314e0"
|
169
|
+
|
170
|
+
@logger.new_transaction(token)
|
171
|
+
@logger.info "This should include a transaction token"
|
172
|
+
@logfile.should have_received_message(token)
|
173
|
+
|
174
|
+
@logger.end_transaction
|
175
|
+
@logger.info "This should not include a transaction token"
|
176
|
+
@logfile.should_not have_received_message(token)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should support save/restore on transaction tokens" do
|
180
|
+
token1 = "3d5e27f7-b97c-4adc-b1fd-adf1bd4314e0"
|
181
|
+
token2 = "1bdef605-34b9-4ec7-9a1c-cb58efc8a635"
|
182
|
+
|
183
|
+
obj1 = Object.new
|
184
|
+
|
185
|
+
@logger.new_transaction(token1)
|
186
|
+
@logger.info "This should include transaction token1"
|
187
|
+
@logfile.should have_received_message(token1)
|
188
|
+
|
189
|
+
@logger.save_transaction(obj1)
|
190
|
+
@logger.new_transaction(token2)
|
191
|
+
@logger.info "This should include transaction token2"
|
192
|
+
@logfile.should have_received_message(token2)
|
193
|
+
@logger.end_transaction
|
194
|
+
|
195
|
+
@logger.restore_transaction(obj1)
|
196
|
+
@logger.info "This should include transaction token1"
|
197
|
+
@logfile.should have_received_message(token1)
|
198
|
+
|
199
|
+
@logger.end_transaction
|
200
|
+
@logger.info "This should not include a transaction token"
|
201
|
+
@logfile.should_not have_received_message(token1)
|
202
|
+
@logfile.should_not have_received_message(token2)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should support a buffered logger" do
|
206
|
+
@logger = ImprovedLogger.new(:buffer)
|
207
|
+
@logger.level = :debug
|
208
|
+
@logger.info "test"
|
209
|
+
@logger.buffer.should match(/test/)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should fall back to STDERR if logfile is not writable" do
|
213
|
+
STDERR.should_receive(:puts).with(/not writable.*STDERR/)
|
214
|
+
|
215
|
+
@logfile = "/not/writable/spec.log"
|
216
|
+
@logger = ImprovedLogger.new(@logfile)
|
217
|
+
@logger.level = :debug
|
218
|
+
|
219
|
+
STDERR.should_receive(:write).with(/test/)
|
220
|
+
@logger.info "test"
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should fallback to standard logger if syslogger gem is missing" do
|
224
|
+
syslogger_paths = $:.select { |p| p.match(/gems\/.*syslogger-/) }
|
225
|
+
$:.replace($: - syslogger_paths)
|
226
|
+
|
227
|
+
STDERR.should_receive(:write).with(/reverting to standard logger/)
|
228
|
+
@logger = ImprovedLogger.new(:syslog)
|
229
|
+
@logger.logger.should be_instance_of(Logger)
|
230
|
+
|
231
|
+
$:.replace($: + syslogger_paths)
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should support a syslog backend" do
|
235
|
+
@logger = ImprovedLogger.new(:syslog)
|
236
|
+
@logger.level = :debug
|
237
|
+
@logger.logger.should be_instance_of(Syslogger)
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
include Madvertise::Logging
|
4
|
+
|
5
|
+
describe MultiLogger do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@logger = ImprovedLogger.new
|
9
|
+
@logger.level = :debug
|
10
|
+
@ml = MultiLogger.new(@logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should support attach/detach of loggers" do
|
14
|
+
buflog = ImprovedLogger.new(:buffer)
|
15
|
+
@ml.attach(buflog)
|
16
|
+
|
17
|
+
STDERR.should_receive(:write).with(/test1/)
|
18
|
+
@ml.info("test1")
|
19
|
+
buflog.buffer.should match(/test1/)
|
20
|
+
|
21
|
+
@ml.detach(buflog)
|
22
|
+
|
23
|
+
STDERR.should_receive(:write).with(/test2/)
|
24
|
+
@ml.info("test2")
|
25
|
+
buflog.buffer.should_not match(/test2/)
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.start
|
7
|
+
|
8
|
+
ROOT = "#{File.dirname(__FILE__)}/../tmp"
|
9
|
+
|
10
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
11
|
+
require 'madvertise-logging'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
# == Mock Framework
|
15
|
+
#
|
16
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
17
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
18
|
+
#
|
19
|
+
# config.mock_with :mocha
|
20
|
+
# config.mock_with :flexmock
|
21
|
+
# config.mock_with :rr
|
22
|
+
|
23
|
+
# setup a fake root
|
24
|
+
config.before(:all) { File.directory?(ROOT) ? FileUtils.rm_rf("#{ROOT}/*") : FileUtils.mkdir_p(ROOT) }
|
25
|
+
config.after(:all) { FileUtils.rm_rf("#{ROOT}/*") }
|
26
|
+
end
|
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
begin
|
2
|
+
require 'rspec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
require 'rspec'
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
|
11
|
+
desc "Run the specs"
|
12
|
+
RSpec::Core::RakeTask.new do |t|
|
13
|
+
t.rspec_opts = ['--options', "spec/spec.opts"]
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts <<-EOS
|
17
|
+
To use rspec for testing you must install rspec gem:
|
18
|
+
gem install rspec
|
19
|
+
EOS
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: madvertise-logging
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Benedikt Böhm
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: &15364280 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *15364280
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &15363560 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *15363560
|
36
|
+
description: Advanced logging classes with buffer backend, transactions, multi logger,
|
37
|
+
etc
|
38
|
+
email:
|
39
|
+
- benedikt.boehm@madvertise.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- .rvmrc
|
46
|
+
- Gemfile
|
47
|
+
- LICENSE
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- lib/madvertise-logging.rb
|
51
|
+
- lib/madvertise/logging/improved_logger.rb
|
52
|
+
- lib/madvertise/logging/multi_logger.rb
|
53
|
+
- lib/madvertise/logging/version.rb
|
54
|
+
- madvertise-logging.gemspec
|
55
|
+
- spec/improved_logger_spec.rb
|
56
|
+
- spec/multi_logger_spec.rb
|
57
|
+
- spec/spec.opts
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
- tasks/rspec.rake
|
60
|
+
homepage: https://github.com/madvertise/logging
|
61
|
+
licenses: []
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
hash: 3354586897547183297
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
hash: 3354586897547183297
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.8.10
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Advanced logging classes with buffer backend, transactions, multi logger,
|
90
|
+
etc
|
91
|
+
test_files:
|
92
|
+
- spec/improved_logger_spec.rb
|
93
|
+
- spec/multi_logger_spec.rb
|
94
|
+
- spec/spec.opts
|
95
|
+
- spec/spec_helper.rb
|