lines 0.2.0 → 0.9.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.
@@ -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"