madvertise-logging 1.2.1-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ ---
2
+ LongParameterList:
3
+ exclude:
4
+ - Formatter#call
5
+ FeatureEnvy:
6
+ exclude:
7
+ - ImprovedLogger#clean_trace
8
+ - ImprovedLogger#exception
9
+ UtilityFunction:
10
+ exclude:
11
+ - ImprovedLogger#clean_trace
12
+ LargeClass:
13
+ exclude:
14
+ - ImprovedLogger
@@ -0,0 +1,34 @@
1
+ module Madvertise
2
+ module Logging
3
+
4
+ ##
5
+ # MultiLogger is a simple class for multiplexing ImprovedLogger objects. It
6
+ # support attach/detach to send messages to any number of loggers.
7
+
8
+ class MultiLogger
9
+ def initialize(*loggers)
10
+ @loggers = loggers
11
+ end
12
+
13
+ # Attach an ImprovedLogger object.
14
+ def attach(logger)
15
+ logger.token = @loggers.first.token rescue nil
16
+ @loggers << logger
17
+ end
18
+
19
+ # Detach an ImprovedLogger object.
20
+ def detach(logger)
21
+ @loggers.delete(logger)
22
+ end
23
+
24
+ # Delegate all method calls to all attached loggers.
25
+ #
26
+ # @private
27
+ def method_missing(name, *args, &block)
28
+ @loggers.map do |logger|
29
+ logger.send(name, *args, &block)
30
+ end.first
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "madvertise-logging"
5
+ spec.version = "1.2.1"
6
+ spec.authors = ["madvertise Mobile Advertising GmbH"]
7
+ spec.email = ["tech@madvertise.com"]
8
+ spec.description = %q{Advanced logging classes with buffer backend, transactions, multi logger, etc}
9
+ spec.summary = %q{Advanced logging classes with buffer backend, transactions, multi logger, etc}
10
+ spec.homepage = "https://github.com/madvertise/logging"
11
+
12
+ spec.files = `git ls-files`.split($/)
13
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.require_paths = ["lib"]
16
+
17
+ if RUBY_PLATFORM == "java"
18
+ spec.platform = 'java'
19
+ spec.add_dependency "log4jruby", "~> 1.0.0.rc1"
20
+ spec.add_dependency "slyphon-log4j", "~> 1.2.15"
21
+ end
22
+ end
@@ -0,0 +1,322 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe ImprovedLogger do
4
+
5
+ let(:logger) { ImprovedLogger.new(:document) }
6
+
7
+ before(:each) { logger.level = :debug }
8
+
9
+ subject { logger.messages }
10
+
11
+ ImprovedLogger.severities.keys.each do |level|
12
+ describe level do
13
+ before { logger.send(level, "testing #{level}") }
14
+ let(:prefix) { level == :unknown ? "ANY" : level.to_s.upcase }
15
+ it "logs #{level} messages" do
16
+ subject.last[:message].should == "testing #{level}"
17
+ end
18
+ end
19
+ end
20
+
21
+ it "logs info level messages with <<" do
22
+ logger << "Info test <<"
23
+ subject.last[:message].should == "Info test <<"
24
+ end
25
+
26
+ it "logs info level messages with write" do
27
+ logger.write("Info test write")
28
+ subject.last[:message].should == "Info test write"
29
+ end
30
+
31
+ it "supports additional attributes" do
32
+ logger.info("foo", key: "value", test: "with space")
33
+ subject.last[:message].should == 'foo key=value test="with space"'
34
+ end
35
+
36
+ it "supports lazy-evaluation via blocks" do
37
+ logger.debug { "debug message" }
38
+ subject.last[:message].should == "debug message"
39
+ end
40
+
41
+ it "supports lazy-evaluation with attributes" do
42
+ logger.debug { ["debug message", {key: "value"}] }
43
+ subject.last[:message].should == "debug message key=value"
44
+ end
45
+
46
+ it "accepts a different backend" do
47
+ l = Logger.new('/dev/null')
48
+ logger.logger = l
49
+ logger.logger.should == l
50
+ end
51
+
52
+ describe :log_caller do
53
+ it "logs the caller file and line number" do
54
+ f = __FILE__
55
+ l = __LINE__ + 3
56
+
57
+ logger.log_caller = true
58
+ logger.info("Caller test")
59
+ subject.last[:message].should == "Caller test file=#{f} line=#{l}"
60
+ end
61
+
62
+ it "does not log the caller file and line number" do
63
+ f = File.basename(__FILE__)
64
+ l = __LINE__ + 3
65
+
66
+ logger.log_caller = false
67
+ logger.info("Caller test")
68
+ subject.last[:message].should_not == "Caller test file=#{f} line=#{l}"
69
+ end
70
+ end
71
+
72
+ let(:fake_trace) do
73
+ [
74
+ "/home/jdoe/app/libexec/app.rb:1:in `foo'",
75
+ "/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
76
+ ]
77
+ end
78
+
79
+ describe :exceptions do
80
+ let(:exc) do
81
+ RuntimeError.new('Test error').tap do |exc|
82
+ exc.set_backtrace(fake_trace)
83
+ end
84
+ end
85
+
86
+ it "logs an exception object" do
87
+ logger.exception(exc)
88
+ subject.last[:message].should match(%r{exception class=RuntimeError reason=\"Test error\" message= backtrace=\"\['/home/jdoe/app/libexec/app\.rb:1:in `foo''\]\"})
89
+ end
90
+
91
+ it "logs an exception object and prefix" do
92
+ logger.exception(exc, "app failed to foo")
93
+ subject.last[:message].should match(%r{exception class=RuntimeError reason=\"Test error\" message=\"app failed to foo\" backtrace=\"\['/home/jdoe/app/libexec/app\.rb:1:in `foo''\]\"})
94
+ end
95
+ end
96
+
97
+ describe :clean_trace do
98
+ subject { logger.clean_trace(fake_trace) }
99
+ it { should include("/home/jdoe/app/libexec/app.rb:1:in `foo'") }
100
+ it { should_not include("/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'") }
101
+ end
102
+
103
+ it "should support silencing" do
104
+ logger.silence do |logger|
105
+ logger.info "This should never be logged"
106
+ end
107
+
108
+ subject.last.should be_nil
109
+ end
110
+
111
+ it "should not discard messages if silencer is disabled globally" do
112
+ ImprovedLogger.silencer = false
113
+
114
+ logger.silence do |logger|
115
+ logger.info "This should actually be logged"
116
+ end
117
+
118
+ subject.last[:message].should == "This should actually be logged"
119
+
120
+ ImprovedLogger.silencer = true
121
+ end
122
+
123
+ it "should support a token" do
124
+ token = "3d5e27f7-b97c-4adc-b1fd-adf1bd4314e0"
125
+
126
+ logger.token = token
127
+ logger.info "This should include a token"
128
+ subject.last[:message].should match(token)
129
+
130
+ logger.token = nil
131
+ logger.info "This should not include a token"
132
+ subject.last[:message].should_not match(token)
133
+ end
134
+
135
+ it "should support save/restore on tokens" do
136
+ token1 = "3d5e27f7-b97c-4adc-b1fd-adf1bd4314e0"
137
+ token2 = "1bdef605-34b9-4ec7-9a1c-cb58efc8a635"
138
+
139
+ obj = Object.new
140
+
141
+ logger.token = token1
142
+ logger.info "This should include token1"
143
+ subject.last[:message].should match(token1)
144
+
145
+ logger.save_token(obj)
146
+ logger.token = token2
147
+ logger.info "This should include token2"
148
+ subject.last[:message].should match(token2)
149
+
150
+ logger.restore_token(obj)
151
+ logger.info "This should include token1"
152
+ subject.last[:message].should match(token1)
153
+
154
+ logger.token = nil
155
+ logger.info "This should not include a token"
156
+ subject.last[:message].should_not match(token1)
157
+ subject.last[:message].should_not match(token2)
158
+ end
159
+
160
+ it "should fall back to stderr if logfile is not writable" do
161
+ $stderr.should_receive(:write).with(/not writable.*STDERR/)
162
+
163
+ @logfile = "/not/writable/spec.log"
164
+ logger = ImprovedLogger.new(@logfile)
165
+ logger.level = :debug
166
+
167
+ $stderr.should_receive(:write).with(/test/)
168
+ logger.info "test"
169
+ end
170
+
171
+ it "should fallback to standard logger if syslogger gem is missing" do
172
+ syslogger_paths = $:.select { |p| p.match(/gems\/.*syslogger-/) }
173
+ $:.replace($: - syslogger_paths)
174
+
175
+ $stderr.should_receive(:write).with(/reverting to STDERR/)
176
+ logger = ImprovedLogger.new(:syslog)
177
+ logger.logger.should be_instance_of(Logger)
178
+
179
+ $:.replace($: + syslogger_paths)
180
+ end
181
+
182
+ context "should behave like write-only IO and" do
183
+ subject { logger }
184
+
185
+ it { should be_a IO }
186
+ its(:logger) { should_not be_nil }
187
+ its(:flush) { should == logger }
188
+ its(:set_encoding) { should == logger }
189
+ its(:sync) { should == true }
190
+ its(:tty?) { should == false }
191
+
192
+ it "should close on close_write" do
193
+ logger.should_receive(:close)
194
+ logger.close_write
195
+ end
196
+
197
+ it "should not implement closed?" do
198
+ expect { logger.closed? }.to raise_error(NotImplementedError)
199
+ end
200
+
201
+ it "should not implement sync=" do
202
+ expect { logger.sync = false }.to raise_error(NotImplementedError)
203
+ end
204
+
205
+ it "should implement readbyte, readchar, readline" do
206
+ {
207
+ :readbyte => :getbyte,
208
+ :readchar => :getc,
209
+ :readline => :gets,
210
+ }.each do |m, should|
211
+ logger.should_receive(should)
212
+ expect { logger.send(m) }.to raise_error(IOError)
213
+ end
214
+ end
215
+
216
+ [
217
+ :bytes,
218
+ :chars,
219
+ :codepoints,
220
+ :lines,
221
+ :eof?,
222
+ :getbyte,
223
+ :getc,
224
+ :gets,
225
+ :pos,
226
+ :pos=,
227
+ :read,
228
+ :readlines,
229
+ :readpartial,
230
+ :rewind,
231
+ :seek,
232
+ :ungetbyte,
233
+ :ungetc
234
+ ].each do |m|
235
+ it "should raise IOError for method #{m}" do
236
+ expect { logger.send(m) }.to raise_error(IOError)
237
+ end
238
+ end
239
+
240
+ context "print functions" do
241
+ subject { logger.messages }
242
+
243
+ it "should support printf" do
244
+ logger.printf("%.2f %s", 1.12345, "foo")
245
+ subject.last[:message].should == "1.12 foo"
246
+ end
247
+
248
+ it "should support print" do
249
+ $,, old = ' ', $,
250
+ logger.print("foo", "bar", 123, ["baz", 345])
251
+ subject.last[:message].should == "foo bar 123 baz 345"
252
+ $, = old
253
+ end
254
+
255
+ it "should support puts" do
256
+ logger.puts("a", "b")
257
+ subject.last[:message].should == "b"
258
+ logger.puts(["c", "d"])
259
+ subject.last[:message].should == "d"
260
+ logger.puts(1, 2, 3)
261
+ subject.last[:message].should == "3"
262
+ end
263
+ end
264
+ end
265
+
266
+ context "buffer backend" do
267
+ let(:logger) { ImprovedLogger.new(:buffer) }
268
+ subject { logger }
269
+
270
+ its(:sync) { should == false }
271
+
272
+ it "should support a buffered logger" do
273
+ logger.info "test"
274
+ logger.buffer.should match(/test/)
275
+ end
276
+ end
277
+
278
+ context "document backend" do
279
+ let(:logger) { ImprovedLogger.new(:document) }
280
+
281
+ before do
282
+ @msg = "test"
283
+
284
+ @now = Time.now
285
+ Time.stub(:now).and_return(@now)
286
+
287
+ @expected = {
288
+ severity: Logger::INFO,
289
+ time: @now.to_f,
290
+ progname: "rspec",
291
+ message: @msg
292
+ }
293
+ end
294
+
295
+ it "should store all messages as documents" do
296
+ logger.info(@msg)
297
+ logger.messages.first.should == @expected
298
+ end
299
+
300
+ it "should add custom attributes" do
301
+ attrs = {txid: 1234}
302
+ logger.logger.attrs = attrs
303
+ logger.info(@msg)
304
+ logger.messages.first.should == attrs.merge(@expected)
305
+ end
306
+
307
+ end
308
+
309
+ context "syslog backend" do
310
+ let(:logger) { ImprovedLogger.new(:syslog) }
311
+ subject { logger }
312
+ its(:sync) { should == true }
313
+ its(:logger) { should be_instance_of(Syslogger) }
314
+ end
315
+
316
+ context "unknown backend" do
317
+ it "should raise for unknown backends " do
318
+ expect { ImprovedLogger.new(:unknown_logger) }.to raise_error(RuntimeError)
319
+ end
320
+ end
321
+
322
+ 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
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start
6
+
7
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
8
+ require 'madvertise-logging'
9
+
10
+ RSpec.configure do |config|
11
+ # == Mock Framework
12
+ #
13
+ # RSpec uses it's own mocking framework by default. If you prefer to
14
+ # use mocha, flexmock or RR, uncomment the appropriate line:
15
+ #
16
+ # config.mock_with :mocha
17
+ # config.mock_with :flexmock
18
+ # config.mock_with :rr
19
+ end