lumber 1.0.0 → 1.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3a46d745783b60fff11ef0721004f12f9f63bd96
4
+ data.tar.gz: 3eba30bf67000eb632ed7a43b874b9311c06ea7d
5
+ SHA512:
6
+ metadata.gz: 90f2ac82d2c07a1c41de9f1135bf635826829bb26f055d65c0d71935276eb407a5f07f23e27a2bdcb41075f655492ce566392f8606cac0c440df7fac4f8874bc
7
+ data.tar.gz: e982a2aa70f9201f721cbd05fb9a32a7a6cdf651e9a2afb3ad324a9e3ae1bf4035c734049a4c4b52be67ef4b9c0480c61b5cb8cd2f96bc1c7955a1664376eef4
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ 1.0.1 (10/11/2013)
2
+ ------------------
3
+
4
+ add log4r json formatter
5
+
6
+ 1.0.0 (10/11/2013)
7
+ ------------------
8
+
9
+ Add coveralls and use poltergeist/phantomjs instead of capybara-webkit so we
10
+ fix capybara usage for capybara 2.x for travis
11
+ only supporting ruby 1.9.3 and higher
12
+
1
13
  0.13.6 (08/23/2013)
2
14
  -------------------
3
15
 
@@ -0,0 +1,114 @@
1
+ require "log4r/formatter/formatter"
2
+ require 'json'
3
+
4
+ module Lumber
5
+
6
+ class JsonFormatter < Log4r::BasicFormatter
7
+
8
+ def initialize(hash={})
9
+ @key_mapping = {}
10
+ mapping = hash['key_mapping'] || {}
11
+ @key_mapping = Hash[mapping.collect {|k, v| [k.to_s, v.to_s.split('.')]}]
12
+ end
13
+
14
+ def format(logevent)
15
+ data = {}
16
+ assign_mapped_key(data, :timestamp, Time.now.to_s)
17
+ assign_mapped_key(data, :logger, logevent.fullname)
18
+ assign_mapped_key(data, :level, Log4r::LNAMES[logevent.level].downcase)
19
+
20
+ if logevent.data.kind_of? Exception
21
+ message = "Caught #{logevent.data.class}"
22
+ message << ": #{logevent.data.message}" if logevent.data.message
23
+ assign_mapped_key(data, :message, message)
24
+ assign_mapped_key(data, :exception, logevent.data.class.to_s)
25
+ trace = logevent.data.backtrace if logevent.data.respond_to?(:backtrace)
26
+ if trace
27
+ assign_mapped_key(data, :backtrace, trace.join("\n\t"))
28
+ assign_mapped_key(data, :file, trace[0].split(":")[0])
29
+ assign_mapped_key(data, :line, trace[0].split(":")[1].to_i)
30
+ end
31
+ else
32
+ assign_mapped_key(data, :message, format_object(logevent.data))
33
+ end
34
+
35
+ if logevent.tracer
36
+ file, line, method = parse_caller(logevent.tracer[0])
37
+ assign_mapped_key(data, :file, file)
38
+ assign_mapped_key(data, :line, line)
39
+ assign_mapped_key(data, :method, method)
40
+ end
41
+
42
+ gdc = Log4r::GDC.get
43
+ if gdc && gdc != $0
44
+ value = nil
45
+ begin
46
+ value = gdc.inspect
47
+ rescue
48
+ end
49
+ assign_mapped_key(data, :gdc, value)
50
+ end
51
+
52
+ if Log4r::NDC.get_depth > 0
53
+ value = []
54
+ Log4r::NDC.clone_stack.each do |x|
55
+ begin
56
+ value << x.inspect
57
+ rescue
58
+ end
59
+ end
60
+ assign_mapped_key(data, :ndc, value)
61
+ end
62
+
63
+ mdc = Log4r::MDC.get_context
64
+ if mdc && mdc.size > 0
65
+ value = {}
66
+ mdc.each do |k, v|
67
+ begin
68
+ value[k] = v.inspect
69
+ rescue
70
+ end
71
+ end
72
+ assign_mapped_key(data, :mdc, value)
73
+ end
74
+
75
+ data.to_json
76
+ end
77
+
78
+ private
79
+
80
+ def assign_mapped_key(data, key, value)
81
+ return if value.nil? || (value.respond_to?(:size) && value.size == 0)
82
+ key = key.to_s
83
+ mapped_key = @key_mapping[key]
84
+ if mapped_key.nil?
85
+ data[key] = value
86
+ else
87
+ current = data
88
+ mapped_key.each_with_index do |k, i|
89
+ if mapped_key.size > i+1
90
+ current[k] ||= {}
91
+ current = current[k]
92
+ else
93
+ current[k] = value
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def parse_caller(line)
100
+ if /^(.+?):(\d+)(?::in `(.*)')?/ =~ line
101
+ file = Regexp.last_match[1]
102
+ line = Regexp.last_match[2].to_i
103
+ method = Regexp.last_match[3]
104
+ [file, line, method]
105
+ else
106
+ []
107
+ end
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ # Log4r yml config only looks for constants in Log4r namespace
114
+ Log4r::JsonFormatter = Lumber::JsonFormatter
@@ -1,3 +1,3 @@
1
1
  module Lumber
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/lib/lumber.rb CHANGED
@@ -5,6 +5,7 @@ require "lumber/lumber"
5
5
  require "lumber/logger_support"
6
6
  require "lumber/log4r"
7
7
  require "lumber/level_util"
8
+ require "lumber/json_formatter"
8
9
 
9
10
 
10
11
  if defined?(Rails::Railtie)
@@ -0,0 +1,199 @@
1
+ require "spec_helper"
2
+
3
+ describe Lumber::JsonFormatter do
4
+
5
+ context "log4r yaml configuration" do
6
+
7
+ it "has default values without configuration" do
8
+ yml = <<-EOF
9
+ log4r_config:
10
+ pre_config:
11
+ root:
12
+ level: 'DEBUG'
13
+ loggers:
14
+ - name: "mylogger"
15
+
16
+ outputters:
17
+ - type: StdoutOutputter
18
+ name: stdout
19
+ formatter:
20
+ type: JsonFormatter
21
+ EOF
22
+
23
+ cfg = Log4r::YamlConfigurator
24
+ cfg.load_yaml_string(yml)
25
+ outputter = Log4r::Outputter['stdout']
26
+ outputter.formatter.should_not be_nil
27
+ outputter.formatter.should be_a_kind_of Lumber::JsonFormatter
28
+ end
29
+
30
+ it "can receive configuration" do
31
+ yml = <<-EOF
32
+ log4r_config:
33
+ pre_config:
34
+ root:
35
+ level: 'DEBUG'
36
+ loggers:
37
+ - name: "mylogger"
38
+
39
+ outputters:
40
+ - type: StdoutOutputter
41
+ name: stdout
42
+ formatter:
43
+ type: JsonFormatter
44
+ key_mapping:
45
+ level: severity
46
+ backtrace: exception.bt
47
+ EOF
48
+
49
+ cfg = Log4r::YamlConfigurator
50
+ cfg.load_yaml_string(yml)
51
+ outputter = Log4r::Outputter['stdout']
52
+ outputter.formatter.should_not be_nil
53
+ outputter.formatter.should be_a_kind_of Lumber::JsonFormatter
54
+ outputter.formatter.instance_variable_get(:@key_mapping).should eq({'level' => ['severity'], 'backtrace' => ['exception', 'bt']})
55
+ end
56
+
57
+ end
58
+
59
+ context "#assign_mapped_key" do
60
+
61
+ it "handles no mapping" do
62
+ formatter = Lumber::JsonFormatter.new()
63
+ data = {}
64
+ formatter.send(:assign_mapped_key, data, 'foo', 'bar')
65
+ data['foo'].should == 'bar'
66
+ end
67
+
68
+ it "handles simple mapping" do
69
+ formatter = Lumber::JsonFormatter.new('key_mapping' => {'foo' => 'baz'})
70
+ data = {}
71
+ formatter.send(:assign_mapped_key, data, 'foo', 'bar')
72
+ data['foo'].should be_nil
73
+ data['baz'].should == 'bar'
74
+ end
75
+
76
+ it "handles deep mapping" do
77
+ formatter = Lumber::JsonFormatter.new('key_mapping' => {'foo' => 'baz.bum'})
78
+ data = {}
79
+ formatter.send(:assign_mapped_key, data, 'foo', 'bar')
80
+ data['foo'].should be_nil
81
+ data['baz'].should eq({'bum' => 'bar'})
82
+ end
83
+
84
+ it "handles overlapping deep mapping" do
85
+ formatter = Lumber::JsonFormatter.new('key_mapping' => {'foo' => 'baz.bum', 'dum' => 'baz.derf'})
86
+ data = {}
87
+ formatter.send(:assign_mapped_key, data, 'foo', 'bar')
88
+ formatter.send(:assign_mapped_key, data, 'dum', 'hum')
89
+ data['foo'].should be_nil
90
+ data['dum'].should be_nil
91
+ data['baz'].should eq({'bum' => 'bar', 'derf' => 'hum'})
92
+ end
93
+
94
+ end
95
+
96
+ context "log contents" do
97
+
98
+ before(:each) do
99
+ @logger = Lumber.find_or_create_logger('mylogger')
100
+ @sio = StringIO.new
101
+ @outputter = Log4r::IOOutputter.new("sbout", @sio)
102
+ @formatter = Lumber::JsonFormatter.new
103
+ @outputter.formatter = @formatter
104
+ @logger.outputters.clear
105
+ @logger.outputters << @outputter
106
+
107
+ Log4r::GDC.set(nil)
108
+ Log4r::NDC.clear
109
+ Log4r::MDC.get_context.keys.each {|k| Log4r::MDC.remove(k) }
110
+ end
111
+
112
+ it "logs as json" do
113
+ @logger.info("howdy")
114
+ @sio.string.size.should be_present
115
+ json = JSON.parse(@sio.string)
116
+ json['logger'].should == 'mylogger'
117
+ json['level'].should == 'info'
118
+ json['message'].should == 'howdy'
119
+ json['timestamp'].should be_present
120
+ end
121
+
122
+ it "logs as json with mapping" do
123
+ @formatter = Lumber::JsonFormatter.new('key_mapping' => {'level' => 'severity'})
124
+ @outputter.formatter = @formatter
125
+
126
+ @logger.info("howdy")
127
+ json = JSON.parse(@sio.string)
128
+ json['level'].should be_nil
129
+ json['severity'].should == 'info'
130
+ end
131
+
132
+ it "logs exception as json" do
133
+ ex = StandardError.new("mybad")
134
+ raise ex rescue nil
135
+ @logger.error(ex)
136
+ json = JSON.parse(@sio.string)
137
+ json['message'].should == 'Caught StandardError: mybad'
138
+ json['level'].should == 'error'
139
+ json['backtrace'].should =~ /json_formatter_spec.rb:\d+/
140
+ json['file'].should =~ /^\/.*json_formatter_spec.rb$/
141
+ json['line'].should > 0
142
+ end
143
+
144
+ it "doesn't set file/line/method by default" do
145
+ @logger.fatal("no tracing")
146
+ json = JSON.parse(@sio.string)
147
+ json['file'].should be_nil
148
+ json['line'].should be_nil
149
+ json['method'].should be_nil
150
+ end
151
+
152
+ it "uses trace data if enabled" do
153
+ @logger.trace = true
154
+ @logger.fatal("no tracing")
155
+ json = JSON.parse(@sio.string)
156
+ json['file'].should =~ /^\/.*json_formatter_spec.rb$/
157
+ json['line'].should > 0
158
+ json['method'].should be_present
159
+ end
160
+
161
+ it "uses global log4r context if available" do
162
+ Log4r::GDC.set("mygdc")
163
+ @logger.info("context")
164
+ json = JSON.parse(@sio.string)
165
+ json['gdc'].should == '"mygdc"'
166
+ end
167
+
168
+ it "uses nested log4r context if available" do
169
+ Log4r::NDC.push("myndc0")
170
+ Log4r::NDC.push(99)
171
+ @logger.info("context")
172
+ json = JSON.parse(@sio.string)
173
+ json['ndc'].should == ['"myndc0"', "99"]
174
+ end
175
+
176
+ it "uses mapped log4r context if available" do
177
+ Log4r::MDC.put("foo", "mymdcfoo")
178
+ Log4r::MDC.put("lucky", 7)
179
+ Log4r::MDC.put("myclass", Object)
180
+ @logger.info("context")
181
+ json = JSON.parse(@sio.string)
182
+ json['mdc'].should == {"foo" => '"mymdcfoo"', "lucky" => "7", "myclass" => "Object"}
183
+ end
184
+
185
+ it "handles failure inspecting log4r context" do
186
+ o = Object.new
187
+ o.stub(:inspect).and_raise("bad")
188
+ Log4r::GDC.set(o)
189
+ Log4r::NDC.push(o); Log4r::NDC.push(5)
190
+ Log4r::MDC.put("obj", o); Log4r::MDC.put("foo", "bar")
191
+ @logger.info("context")
192
+ json = JSON.parse(@sio.string)
193
+ json['gdc'].should be_nil
194
+ json['ndc'].should == ["5"]
195
+ json['mdc'].should == {"foo" => '"bar"'}
196
+ end
197
+ end
198
+
199
+ end
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,16 @@ if ENV['CI']
5
5
  Coveralls.wear!
6
6
  end
7
7
 
8
- Bundler.require(:development, :test)
8
+ require 'bundler'
9
+ begin
10
+ Bundler.setup(:default, :development)
11
+ rescue Bundler::BundlerError => e
12
+ $stderr.puts e.message
13
+ $stderr.puts "Run `bundle install` to install missing gems"
14
+ exit e.status_code
15
+ end
16
+
17
+ require 'sinatra'
9
18
  Sinatra::Base.set :environment, :test
10
19
 
11
20
  require 'lumber'
metadata CHANGED
@@ -1,177 +1,159 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lumber
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.0.0
4
+ version: 1.0.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Matt Conway
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-08-23 00:00:00.000000000 Z
11
+ date: 2013-10-11 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: log4r
16
- version_requirements: !ruby/object:Gem::Requirement
15
+ requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
17
  - - ~>
19
18
  - !ruby/object:Gem::Version
20
19
  version: 1.1.10
21
- none: false
22
- requirement: !ruby/object:Gem::Requirement
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.1.10
27
- none: false
28
- prerelease: false
29
- type: :runtime
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: activesupport
32
- version_requirements: !ruby/object:Gem::Requirement
33
- requirements:
34
- - - '>='
35
- - !ruby/object:Gem::Version
36
- version: '0'
37
- none: false
38
29
  requirement: !ruby/object:Gem::Requirement
39
30
  requirements:
40
31
  - - '>='
41
32
  - !ruby/object:Gem::Version
42
33
  version: '0'
43
- none: false
44
- prerelease: false
45
34
  type: :runtime
46
- - !ruby/object:Gem::Dependency
47
- name: sinatra
35
+ prerelease: false
48
36
  version_requirements: !ruby/object:Gem::Requirement
49
37
  requirements:
50
38
  - - '>='
51
39
  - !ruby/object:Gem::Version
52
40
  version: '0'
53
- none: false
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
54
43
  requirement: !ruby/object:Gem::Requirement
55
44
  requirements:
56
45
  - - '>='
57
46
  - !ruby/object:Gem::Version
58
47
  version: '0'
59
- none: false
60
- prerelease: false
61
48
  type: :runtime
62
- - !ruby/object:Gem::Dependency
63
- name: rake
49
+ prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - '>='
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
- none: false
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
70
57
  requirement: !ruby/object:Gem::Requirement
71
58
  requirements:
72
59
  - - '>='
73
60
  - !ruby/object:Gem::Version
74
61
  version: '0'
75
- none: false
76
- prerelease: false
77
62
  type: :development
78
- - !ruby/object:Gem::Dependency
79
- name: rspec
63
+ prerelease: false
80
64
  version_requirements: !ruby/object:Gem::Requirement
81
65
  requirements:
82
66
  - - '>='
83
67
  - !ruby/object:Gem::Version
84
68
  version: '0'
85
- none: false
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
86
71
  requirement: !ruby/object:Gem::Requirement
87
72
  requirements:
88
73
  - - '>='
89
74
  - !ruby/object:Gem::Version
90
75
  version: '0'
91
- none: false
92
- prerelease: false
93
76
  type: :development
94
- - !ruby/object:Gem::Dependency
95
- name: rack-test
77
+ prerelease: false
96
78
  version_requirements: !ruby/object:Gem::Requirement
97
79
  requirements:
98
80
  - - '>='
99
81
  - !ruby/object:Gem::Version
100
82
  version: '0'
101
- none: false
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack-test
102
85
  requirement: !ruby/object:Gem::Requirement
103
86
  requirements:
104
87
  - - '>='
105
88
  - !ruby/object:Gem::Version
106
89
  version: '0'
107
- none: false
108
- prerelease: false
109
90
  type: :development
110
- - !ruby/object:Gem::Dependency
111
- name: capybara
91
+ prerelease: false
112
92
  version_requirements: !ruby/object:Gem::Requirement
113
93
  requirements:
114
94
  - - '>='
115
95
  - !ruby/object:Gem::Version
116
96
  version: '0'
117
- none: false
97
+ - !ruby/object:Gem::Dependency
98
+ name: capybara
118
99
  requirement: !ruby/object:Gem::Requirement
119
100
  requirements:
120
101
  - - '>='
121
102
  - !ruby/object:Gem::Version
122
103
  version: '0'
123
- none: false
124
- prerelease: false
125
104
  type: :development
126
- - !ruby/object:Gem::Dependency
127
- name: poltergeist
105
+ prerelease: false
128
106
  version_requirements: !ruby/object:Gem::Requirement
129
107
  requirements:
130
108
  - - '>='
131
109
  - !ruby/object:Gem::Version
132
110
  version: '0'
133
- none: false
111
+ - !ruby/object:Gem::Dependency
112
+ name: poltergeist
134
113
  requirement: !ruby/object:Gem::Requirement
135
114
  requirements:
136
115
  - - '>='
137
116
  - !ruby/object:Gem::Version
138
117
  version: '0'
139
- none: false
140
- prerelease: false
141
118
  type: :development
142
- - !ruby/object:Gem::Dependency
143
- name: awesome_print
119
+ prerelease: false
144
120
  version_requirements: !ruby/object:Gem::Requirement
145
121
  requirements:
146
122
  - - '>='
147
123
  - !ruby/object:Gem::Version
148
124
  version: '0'
149
- none: false
125
+ - !ruby/object:Gem::Dependency
126
+ name: awesome_print
150
127
  requirement: !ruby/object:Gem::Requirement
151
128
  requirements:
152
129
  - - '>='
153
130
  - !ruby/object:Gem::Version
154
131
  version: '0'
155
- none: false
156
- prerelease: false
157
132
  type: :development
158
- - !ruby/object:Gem::Dependency
159
- name: sinatra-contrib
133
+ prerelease: false
160
134
  version_requirements: !ruby/object:Gem::Requirement
161
135
  requirements:
162
136
  - - '>='
163
137
  - !ruby/object:Gem::Version
164
138
  version: '0'
165
- none: false
139
+ - !ruby/object:Gem::Dependency
140
+ name: sinatra-contrib
166
141
  requirement: !ruby/object:Gem::Requirement
167
142
  requirements:
168
143
  - - '>='
169
144
  - !ruby/object:Gem::Version
170
145
  version: '0'
171
- none: false
172
- prerelease: false
173
146
  type: :development
174
- description: Lumber tries to make it easy to use the more robust log4r logging system within your rails application. To do this it sets up log4r configuration from a yml file, and provides utility methods for adding a :logger accessor to classes dynamicaly as they get created.
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: Lumber tries to make it easy to use the more robust log4r logging system
154
+ within your rails application. To do this it sets up log4r configuration from a
155
+ yml file, and provides utility methods for adding a :logger accessor to classes
156
+ dynamicaly as they get created.
175
157
  email:
176
158
  - matt@conwaysplace.com
177
159
  executables: []
@@ -193,6 +175,7 @@ files:
193
175
  - generators/lumber/lumber_generator.rb
194
176
  - generators/lumber/templates/log4r.yml
195
177
  - lib/lumber.rb
178
+ - lib/lumber/json_formatter.rb
196
179
  - lib/lumber/level_util.rb
197
180
  - lib/lumber/log4r.rb
198
181
  - lib/lumber/logger_support.rb
@@ -213,6 +196,7 @@ files:
213
196
  - lib/lumber/server/views/levels.erb
214
197
  - lib/lumber/version.rb
215
198
  - lumber.gemspec
199
+ - spec/json_formatter_spec.rb
216
200
  - spec/level_util_spec.rb
217
201
  - spec/logger_support_spec.rb
218
202
  - spec/lumber_spec.rb
@@ -222,7 +206,8 @@ files:
222
206
  homepage: http://github.com/wr0ngway/lumber
223
207
  licenses:
224
208
  - MIT
225
- post_install_message:
209
+ metadata: {}
210
+ post_install_message:
226
211
  rdoc_options: []
227
212
  require_paths:
228
213
  - lib
@@ -230,30 +215,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
230
215
  requirements:
231
216
  - - '>='
232
217
  - !ruby/object:Gem::Version
233
- segments:
234
- - 0
235
- hash: 2
236
218
  version: '0'
237
- none: false
238
219
  required_rubygems_version: !ruby/object:Gem::Requirement
239
220
  requirements:
240
221
  - - '>='
241
222
  - !ruby/object:Gem::Version
242
- segments:
243
- - 0
244
- hash: 2
245
223
  version: '0'
246
- none: false
247
224
  requirements: []
248
- rubyforge_project:
249
- rubygems_version: 1.8.24
250
- signing_key:
251
- specification_version: 3
225
+ rubyforge_project:
226
+ rubygems_version: 2.0.6
227
+ signing_key:
228
+ specification_version: 4
252
229
  summary: Lumber integrates the log4r logging system within your application.
253
230
  test_files:
231
+ - spec/json_formatter_spec.rb
254
232
  - spec/level_util_spec.rb
255
233
  - spec/logger_support_spec.rb
256
234
  - spec/lumber_spec.rb
257
235
  - spec/server_spec.rb
258
236
  - spec/spec.opts
259
237
  - spec/spec_helper.rb
238
+ has_rdoc: