madvertise-logging 1.2.1-java

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.
@@ -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