lines 0.2.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,61 +0,0 @@
1
- module Lines
2
- # Backward-compatible logger
3
- # http://ruby-doc.org/stdlib-2.0/libdoc/logger/rdoc/Logger.html#method-i-log
4
- class Logger
5
- LEVELS = {
6
- 0 => :debug,
7
- 1 => :info,
8
- 2 => :warn,
9
- 3 => :error,
10
- 4 => :fatal,
11
- 5 => :unknown,
12
- }
13
-
14
- def initialize(line)
15
- @line = line
16
- end
17
-
18
- def log(severity, message = nil, progname = nil, &block)
19
- pri = LEVELS[severity] || severity
20
- if block_given?
21
- progname = message
22
- message = yield.to_s rescue $!.to_s
23
- end
24
-
25
- data = { pri: pri }
26
- data[:app] = progname if progname
27
- data[:msg] = message if message
28
-
29
- @line.log(data)
30
- end
31
-
32
- LEVELS.values.each do |level|
33
- define_method(level) do |message=nil, &block|
34
- log(level, message, &block)
35
- end
36
- end
37
-
38
- alias << info
39
- alias unknown info
40
-
41
- def noop(*a); true end
42
- %w[add
43
- clone
44
- datetime_format
45
- datetime_format=
46
- debug?
47
- info?
48
- error?
49
- fatal?
50
- warn?
51
- level
52
- level=
53
- progname
54
- progname=
55
- sev_threshold
56
- sev_threshold=
57
- ].each do |op|
58
- alias_method(op, :noop)
59
- end
60
- end
61
- end
@@ -1,39 +0,0 @@
1
- require 'rack/commonlogger'
2
- require 'lines'
3
-
4
- module Lines
5
- class RackLogger < Rack::CommonLogger
6
- # In development mode the common logger is always inserted
7
- def self.silence_common_logger!
8
- Rack::CommonLogger.module_eval('def call(env); @app.call(env); end')
9
- self
10
- end
11
-
12
- def initialize(app)
13
- @app = app
14
- end
15
-
16
- def call(env)
17
- began_at = Time.now
18
- status, header, body = @app.call(env)
19
- header = Rack::Utils::HeaderHash.new(header)
20
- body = Rack::BodyProxy.new(body) { log(env, status, header, began_at) }
21
- [status, header, body]
22
- end
23
-
24
- protected
25
-
26
- def log(env, status, header, began_at)
27
- Lines.log(
28
- remote_addr: env['HTTP_X_FORWARDED_FOR'] || env['REMOTE_ADDR'],
29
- remote_user: env['REMOTE_USER'] || '',
30
- method: env['REQUEST_METHOD'],
31
- path: env['PATH_INFO'],
32
- query: env['QUERY_STRING'],
33
- status: status.to_s[0..3],
34
- length: extract_content_length(header),
35
- elapsed: [Time.now - began_at, 's'],
36
- )
37
- end
38
- end
39
- end
@@ -1,46 +0,0 @@
1
- require 'benchmark/ips'
2
-
3
- $:.unshift File.expand_path('../../lib', __FILE__)
4
- require 'lines'
5
-
6
- class FakeIO
7
- def write(*a)
8
- end
9
- alias syswrite write
10
- end
11
-
12
- globals = {
13
- app: 'benchmark',
14
- at: proc{ Time.now },
15
- pid: Process.pid,
16
- }
17
-
18
- EX = (raise "FOO" rescue $!)
19
-
20
- Benchmark.ips do |x|
21
- x.report "FakeIO write" do |n|
22
- Lines.use(FakeIO.new, globals)
23
- n.times{ Lines.log EX }
24
- end
25
-
26
- x.report "/dev/null write" do |n|
27
- dev_null = File.open('/dev/null', 'w')
28
- Lines.use(dev_null, globals)
29
- n.times{ Lines.log EX }
30
- end
31
-
32
- x.report "syslog write" do |n|
33
- Lines.use(Syslog, globals)
34
- n.times{ Lines.log EX }
35
- end
36
-
37
- x.report "real file" do |n|
38
- real_file = File.open('real_file.log', 'w')
39
- Lines.use(real_file, globals)
40
- n.times{ Lines.log EX }
41
- end
42
-
43
- x.report "real file logger" do |n|
44
- n.times{ Lines.logger.info "Ahoi this is a really cool option" }
45
- end
46
- end
@@ -1,190 +0,0 @@
1
- require 'spec_helper'
2
- require 'lines'
3
- require 'stringio'
4
-
5
- NL = "\n"
6
-
7
- describe Lines do
8
- let(:outputter) { StringIO.new }
9
- let(:output) { outputter.string }
10
- before do
11
- Lines.use(outputter)
12
- end
13
-
14
- context ".log" do
15
- it "logs stuff" do
16
- Lines.log(foo: 'bar')
17
- expect(output).to eq('foo=bar' + NL)
18
- end
19
-
20
- it "supports a first msg argument" do
21
- Lines.log("this user is annoying", user: 'bob')
22
- expect(output).to eq("msg='this user is annoying' user=bob" + NL)
23
- end
24
-
25
- it "logs exceptions" do
26
- Lines.log(StandardError.new("error time!"), user: 'bob')
27
- expect(output).to eq("ex=StandardError msg='error time!' user=bob" + NL)
28
- end
29
-
30
- it "logs exception backtraces when available" do
31
- ex = (raise "foo" rescue $!)
32
- #expect(ex).not_to eq(nil)
33
- Lines.log(ex)
34
- expect(output).to match(/ex=RuntimeError msg=foo backtrace=\[[^\]]+\]/)
35
- end
36
-
37
- it "works with anything" do
38
- Lines.log("anything1", "anything2")
39
- expect(output).to eq('msg=anything2' + NL)
40
- end
41
-
42
- it "doesn't convert nil args to msg" do
43
- Lines.log("anything", nil)
44
- expect(output).to eq('msg=anything' + NL)
45
- end
46
- end
47
-
48
- context ".context" do
49
- it "has contextes" do
50
- Lines.context(foo: "bar").log(a: 'b')
51
- expect(output).to eq('a=b foo=bar' + NL)
52
- end
53
-
54
- it "has contextes with blocks" do
55
- Lines.context(foo: "bar") do |ctx|
56
- ctx.log(a: 'b')
57
- end
58
- expect(output).to eq('a=b foo=bar' + NL)
59
- end
60
-
61
- it "mixes everything" do
62
- Lines.global[:app] = :self
63
- ctx = Lines.context(foo: "bar")
64
- ctx.log('msg', ahoi: true)
65
- expect(output).to eq('app=self msg=msg ahoi=#t foo=bar' + NL)
66
- end
67
- end
68
-
69
- context ".logger" do
70
- it "is provided for backward-compatibility" do
71
- l = Lines.logger
72
- l.info("hi")
73
- expect(output).to eq('pri=info msg=hi' + NL)
74
- end
75
- end
76
-
77
- context ".global" do
78
- it "prepends data to the line" do
79
- Lines.global["app"] = :self
80
- Lines.log 'hey'
81
- expect(output).to eq('app=self msg=hey' + NL)
82
- end
83
-
84
- it "resolves procs dynamically" do
85
- count = 0
86
- Lines.global[:count] = proc{ count += 1 }
87
- Lines.log 'test1'
88
- Lines.log 'test2'
89
- expect(output).to eq(
90
- 'count=1 msg=test1' + NL +
91
- 'count=2 msg=test2' + NL
92
- )
93
- end
94
-
95
- it "doesn't fail if a proc has an exception" do
96
- Lines.global[:X] = proc{ fail "error" }
97
- Lines.log 'test'
98
- expect(output).to eq("X='#<RuntimeError: error>' msg=test" + NL)
99
- end
100
- end
101
- end
102
-
103
- describe Lines::Dumper do
104
- subject { Lines::Dumper.new }
105
- def expect_dump(obj)
106
- expect(subject.dump obj)
107
- end
108
-
109
- it do
110
- expect_dump(foo: 'bar').to eq('foo=bar')
111
- end
112
-
113
- it "dumps true, false and nil as #t, #f and nil" do
114
- expect_dump(foo: true).to eq('foo=#t')
115
- expect_dump(foo: false).to eq('foo=#f')
116
- expect_dump(foo: nil).to eq('foo=nil')
117
- end
118
-
119
- it "dumps empty strings correclty" do
120
- expect_dump(foo: '').to eq('foo=')
121
- end
122
-
123
- it "dumps a string with spaces surrounded by single quotes" do
124
- expect_dump(foo: 'some" thing').to eq("foo='some\" thing'")
125
- end
126
-
127
- it "dumps a string with spaces and a single quote sourrounded with double quotes" do
128
- expect_dump(foo: "foo ' bar").to eq("foo=\"foo ' bar\"")
129
- end
130
-
131
- it "can dump a basicobject" do
132
- expect_dump(foo: BasicObject.new).to match(/foo='#<BasicObject:0x[0-9a-f]+>'/)
133
- end
134
-
135
- it "can dump IO objects" do
136
- expect_dump(foo: File.open(__FILE__)).to match(/foo='?#<File:[^>]+>'?/)
137
- expect_dump(foo: STDOUT).to match(/^foo='(?:#<IO:<STDOUT>>|#<IO:fd 1>)'$/)
138
- end
139
-
140
- it "dumps time as ISO zulu format" do
141
- expect_dump(foo: Time.at(1337)).to eq('foo=1970-01-01T00:22:17Z')
142
- end
143
-
144
- it "dumps date as ISO date" do
145
- expect_dump(foo: Date.new(1968, 3, 7)).to eq('foo=1968-03-07')
146
- end
147
-
148
- it "dumps symbols as strings" do
149
- expect_dump(foo: :some_symbol).to eq('foo=some_symbol')
150
- expect_dump(foo: :"some symbol").to eq("foo='some symbol'")
151
- end
152
-
153
- it "dumps numbers appropriately" do
154
- expect_dump(foo: 10e3).to eq('foo=10000.0')
155
- expect_dump(foo: 1).to eq('foo=1')
156
- expect_dump(foo: -1).to eq('foo=-1')
157
- # FIXME: don't put all the decimals
158
- #expect_dump(foo: 4.0/3).to eq('foo=1.333')
159
- end
160
-
161
- it "dumps arrays appropriately" do
162
- expect_dump(foo: [1,2,:a]).to eq('foo=[1 2 a]')
163
- end
164
-
165
- it "dumps [number, literal] tuples as numberliteral" do
166
- expect_dump(foo: [3, :ms]).to eq('foo=3:ms')
167
- expect_dump(foo: [54.2, 's']).to eq('foo=54.2:s')
168
- end
169
-
170
- it "knows how to handle circular dependencies" do
171
- x = {}
172
- x[:x] = x
173
- expect_dump(x).to eq('x={x={x={x={...}}}}')
174
- end
175
- end
176
-
177
- describe Lines::UniqueIDs do
178
- include Lines::UniqueIDs
179
-
180
- it "generates a unique ID" do
181
- expect(id.size).to be > 1
182
- end
183
-
184
- it "generates a unique ID on each call" do
185
- id1 = id
186
- id2 = id
187
- expect(id1).to_not eq(id2)
188
- end
189
-
190
- end
@@ -1,26 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- libdir = File.expand_path('../../lib', __FILE__)
4
- $:.unshift(libdir) unless $:.include? libdir
5
-
6
- require 'lines'
7
-
8
- loader = Lines.loader
9
-
10
- start = Time.now
11
- line_count = 0
12
-
13
- $stdin.lines.each do |line|
14
- begin
15
- line_count += 1
16
- loader.load(line)
17
- rescue Lines::Error => ex
18
- # Lines seem to get truncated by syslog when too long
19
- if line.size < 2000
20
- p line
21
- p ex
22
- end
23
- end
24
- end
25
-
26
- puts "Parsed #{line_count / (Time.now - start)} lines per second"