logfile_interval 1.1.1 → 1.1.2
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 +4 -4
- data/.travis.yml +1 -0
- data/Gemfile.lock +4 -4
- data/README.md +3 -6
- data/docs/design.rb +118 -36
- data/lib/logfile_interval/aggregator/average.rb +14 -0
- data/lib/logfile_interval/aggregator/base.rb +52 -0
- data/lib/logfile_interval/aggregator/count.rb +9 -0
- data/lib/logfile_interval/aggregator/delta.rb +22 -0
- data/lib/logfile_interval/aggregator/group_and_count.rb +14 -0
- data/lib/logfile_interval/aggregator/sum.rb +9 -0
- data/lib/logfile_interval/aggregator.rb +24 -0
- data/lib/logfile_interval/interval.rb +9 -0
- data/lib/logfile_interval/interval_builder.rb +2 -0
- data/lib/logfile_interval/logfile.rb +4 -1
- data/lib/logfile_interval/logfile_set.rb +4 -0
- data/lib/logfile_interval/{line_parser → util}/counter.rb +1 -1
- data/lib/logfile_interval/util/file_backward.rb +51 -0
- data/lib/logfile_interval/version.rb +1 -1
- data/lib/logfile_interval.rb +3 -3
- data/spec/lib/aggregator_spec.rb +208 -0
- data/spec/lib/{line_parser/counter_spec.rb → counter_spec.rb} +1 -1
- data/spec/lib/interval_builder_spec.rb +8 -0
- data/spec/lib/interval_spec.rb +31 -7
- data/spec/lib/logfile_set_spec.rb +39 -14
- data/spec/lib/logfile_spec.rb +43 -18
- metadata +15 -12
- data/docs/design2.rb +0 -77
- data/docs/design3.rb +0 -177
- data/lib/logfile_interval/file_backward.rb +0 -49
- data/lib/logfile_interval/interval_length.rb +0 -47
- data/lib/logfile_interval/line_parser/aggregator.rb +0 -117
- data/spec/lib/line_parser/aggregator_spec.rb +0 -211
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LogfileInterval
|
4
|
+
module Aggregator
|
5
|
+
describe Aggregator do
|
6
|
+
it 'finds the aggregator class' do
|
7
|
+
Aggregator.klass(:sum).should == Sum
|
8
|
+
Aggregator.klass(:average).should == Average
|
9
|
+
Aggregator.klass(:count).should == Count
|
10
|
+
Aggregator.klass(:group_and_count).should == GroupAndCount
|
11
|
+
Aggregator.klass(:delta).should == Delta
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
shared_examples 'an aggregator' do
|
16
|
+
let(:aggregator) { described_class.new }
|
17
|
+
|
18
|
+
[ :add, :value, :values ].each do |method|
|
19
|
+
it "responds to #{method}" do
|
20
|
+
aggregator.should respond_to(method)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'values' do
|
25
|
+
context 'with one group' do
|
26
|
+
before :each do
|
27
|
+
aggregator.add(5, :key1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns a hash' do
|
31
|
+
aggregator.values.should be_a(Hash) unless aggregator.is_a?(Delta)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with several groups' do
|
36
|
+
before :each do
|
37
|
+
aggregator.add(5, :key1)
|
38
|
+
aggregator.add(3, :key2)
|
39
|
+
aggregator.add(3, :key1)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns a hash' do
|
43
|
+
aggregator.values.should be_a(Hash)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with no group' do
|
48
|
+
before :each do
|
49
|
+
aggregator.add(5)
|
50
|
+
aggregator.add(3)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns a numeric' do
|
54
|
+
aggregator.values.should be_a(Numeric) unless aggregator.is_a?(Count)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
[ Count, Sum, Average, Delta ]. each do |klass|
|
61
|
+
describe klass do
|
62
|
+
it_behaves_like 'an aggregator'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe 'without group_by key' do
|
68
|
+
describe Sum do
|
69
|
+
it 'sums up values' do
|
70
|
+
sum = Sum.new
|
71
|
+
sum.add(3)
|
72
|
+
sum.add(5)
|
73
|
+
sum.value.should == 8
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Average do
|
78
|
+
it 'averages values' do
|
79
|
+
avg = Average.new
|
80
|
+
avg.add(3)
|
81
|
+
avg.add(5)
|
82
|
+
avg.value.should == 4
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe Delta do
|
87
|
+
it 'averages delta values' do
|
88
|
+
d = Delta.new
|
89
|
+
d.add(1.4)
|
90
|
+
d.add(1.1)
|
91
|
+
d.add(1.0)
|
92
|
+
d.value.round(5).should == 0.2
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe Count do
|
97
|
+
it 'groups values and increment counters' do
|
98
|
+
g = Count.new
|
99
|
+
g.add('200')
|
100
|
+
g.add('500')
|
101
|
+
g.add('301')
|
102
|
+
g.add('200')
|
103
|
+
g.value.should == 4
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'with group_by key' do
|
109
|
+
|
110
|
+
describe Sum do
|
111
|
+
it 'sums up values by key' do
|
112
|
+
sum = Sum.new
|
113
|
+
sum.add(3, :key1)
|
114
|
+
sum.add(5, :key2)
|
115
|
+
sum.add(5, :key1)
|
116
|
+
sum.values.should be_a(Hash)
|
117
|
+
sum.values.size.should == 2
|
118
|
+
sum.value(:key1).should == 8
|
119
|
+
sum.values[:key1].should == 8
|
120
|
+
sum.value(:key2).should == 5
|
121
|
+
sum.values[:key2].should == 5
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
describe Average do
|
127
|
+
it 'averages values by key' do
|
128
|
+
avg = Average.new
|
129
|
+
avg.add(3, :key1)
|
130
|
+
avg.add(5, :key2)
|
131
|
+
avg.add(5, :key1)
|
132
|
+
avg.values.should be_a(Hash)
|
133
|
+
avg.values.size.should == 2
|
134
|
+
avg.value(:key1).should == 4
|
135
|
+
avg.values[:key1].should == 4
|
136
|
+
avg.value(:key2).should == 5
|
137
|
+
avg.values[:key2].should == 5
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe Count do
|
142
|
+
it 'groups values and increment counters' do
|
143
|
+
g = Count.new
|
144
|
+
g.add('200', '200')
|
145
|
+
g.add('500', '500')
|
146
|
+
g.add('301', '301')
|
147
|
+
g.add('200', '200')
|
148
|
+
g.values.should be_a(Hash)
|
149
|
+
g.values.should include({'200' => 2})
|
150
|
+
g.values.should include({'301' => 1})
|
151
|
+
g.values.should include({'500' => 1})
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe GroupAndCount do
|
156
|
+
it 'each yields a key and a hash' do
|
157
|
+
gac = GroupAndCount.new
|
158
|
+
gac.add :key1, :subkey1
|
159
|
+
gac.first.should be_an(Array)
|
160
|
+
gac.first.size.should == 2
|
161
|
+
gac.first[1].should be_a(Hash)
|
162
|
+
end
|
163
|
+
|
164
|
+
context :add do
|
165
|
+
before :each do
|
166
|
+
@gac = GroupAndCount.new
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'requires a group_by argument' do
|
170
|
+
lambda { @gac.add('foo') }.should raise_error ArgumentError
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'counts number of occurence of subkey for key' do
|
174
|
+
@gac.add :key1, :subkey1
|
175
|
+
@gac.add :key1, :subkey2
|
176
|
+
@gac.add :key2, :subkey1
|
177
|
+
@gac.add :key2, :subkey1
|
178
|
+
@gac.add :key2, :subkey3
|
179
|
+
|
180
|
+
@gac.values[:key1][:subkey1].should == 1
|
181
|
+
@gac.values[:key1][:subkey2].should == 1
|
182
|
+
@gac.values[:key2][:subkey1].should == 2
|
183
|
+
@gac.values[:key2][:subkey2].should == 0
|
184
|
+
@gac.values[:key2][:subkey3].should == 1
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe Delta do
|
190
|
+
it 'averages deltas by key' do
|
191
|
+
d = Delta.new
|
192
|
+
d.add(9, :key1)
|
193
|
+
d.add(10, :key2)
|
194
|
+
d.add(5, :key1)
|
195
|
+
d.add(8, :key2)
|
196
|
+
d.add(3, :key1)
|
197
|
+
d.add(5, :key2)
|
198
|
+
d.values.should be_a(Hash)
|
199
|
+
d.values.size.should == 2
|
200
|
+
d.value(:key1).should == 3
|
201
|
+
d.values[:key1].should == 3
|
202
|
+
d.value(:key2).should == 2.5
|
203
|
+
d.values[:key2].should == 2.5
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -47,6 +47,14 @@ module LogfileInterval
|
|
47
47
|
@intervals.last[:action].should == 2
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
context 'without a block' do
|
52
|
+
it 'should return an iterator' do
|
53
|
+
e = @builder.each_interval
|
54
|
+
e.should be_an(Enumerator)
|
55
|
+
e.next.end_time.should == Time.new(2013,12,01,16,0,0,'-08:00')
|
56
|
+
end
|
57
|
+
end
|
50
58
|
end
|
51
59
|
|
52
60
|
context :last_interval do
|
data/spec/lib/interval_spec.rb
CHANGED
@@ -5,9 +5,13 @@ module LogfileInterval
|
|
5
5
|
data_dir = File.join(File.dirname(__FILE__), '..', 'support/logfiles')
|
6
6
|
|
7
7
|
describe Interval do
|
8
|
+
before :each do
|
9
|
+
@end_time = Time.new(2013, 12, 01, 16, 00, 00, '-08:00')
|
10
|
+
@length = 300
|
11
|
+
end
|
12
|
+
|
8
13
|
it 'gets instantiated with empty data' do
|
9
|
-
|
10
|
-
interval = Interval.new(end_time, 300, LineParser::TimingLog)
|
14
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
11
15
|
interval.size.should == 0
|
12
16
|
interval[:total_time].should == 0
|
13
17
|
interval[:num_bytes].should == 0
|
@@ -15,12 +19,32 @@ module LogfileInterval
|
|
15
19
|
interval[:ip].should == 0
|
16
20
|
end
|
17
21
|
|
18
|
-
context :
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
context :to_hash do
|
23
|
+
it 'returns a hash' do
|
24
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
25
|
+
interval.to_hash.should be_a(Hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has a key for all columns' do
|
29
|
+
record = LineParser::TimingLog.create_record('1385942400, 192.168.0.5, posts#index, 100, 2000, 53.0')
|
30
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
31
|
+
interval.add_record(record)
|
32
|
+
hinterval = interval.to_hash
|
33
|
+
hinterval.keys.should include(:ip, :total_time, :action, :num_bytes, :rss)
|
22
34
|
end
|
23
35
|
|
36
|
+
it 'with no data, should have keys with 0 values' do
|
37
|
+
interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
38
|
+
hinterval = interval.to_hash
|
39
|
+
hinterval[:ip].should == 0
|
40
|
+
hinterval[:action].should == 0
|
41
|
+
hinterval[:total_time].should == 0
|
42
|
+
hinterval[:num_bytes].should == 0
|
43
|
+
hinterval[:rss].should == 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context :add_record do
|
24
48
|
context 'basics' do
|
25
49
|
before :each do
|
26
50
|
@interval = Interval.new(@end_time, @length, LineParser::TimingLog)
|
@@ -50,7 +74,7 @@ module LogfileInterval
|
|
50
74
|
|
51
75
|
context 'with count and group by options' do
|
52
76
|
it 'creates an aggregator of type GroupAndCount' do
|
53
|
-
expect(
|
77
|
+
expect(Aggregator::GroupAndCount).to receive(:new)
|
54
78
|
interval = Interval.new(@end_time, @length, LineParser::TimingLogWithGrouping)
|
55
79
|
end
|
56
80
|
|
@@ -8,32 +8,57 @@ module LogfileInterval
|
|
8
8
|
before :each do
|
9
9
|
@logfiles = ["#{data_dir}/access.log.2", "#{data_dir}/access.log.1"]
|
10
10
|
@set = LogfileSet.new(@logfiles, LineParser::AccessLog)
|
11
|
+
@first_line = '66.249.67.176 - - [23/Jun/2013:17:00:01 -0800] "GET /package/core/raring/universe/proposed/openldap HTTP/1.1" 200 185 "-" "Google"'
|
12
|
+
@second_line = '12.24.48.96 - - [23/Jun/2013:16:59:00 -0800] "GET /package/core/raring/universe/proposed/openldap HTTP/1.1" 200 4555 "-" "Bing)"'
|
13
|
+
@last_line = '12.24.48.96 - - [23/Jun/2013:16:49:00 -0800] "GET /package/core/raring/universe/proposed/bash HTTP/1.1" 200 4555 "-" "Bing)"'
|
11
14
|
end
|
12
15
|
|
13
16
|
it 'ordered_filenames should return the most recent file first' do
|
14
17
|
@set.ordered_filenames.should == @logfiles.reverse
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
describe :each_line do
|
21
|
+
it 'should enumerate each line in file backwards' do
|
22
|
+
lines = []
|
23
|
+
@set.each_line do |line|
|
24
|
+
lines << line
|
25
|
+
end
|
26
|
+
|
27
|
+
lines.first.should == @first_line
|
28
|
+
lines.last.should == @last_line
|
21
29
|
end
|
22
30
|
|
23
|
-
|
24
|
-
|
31
|
+
context 'without a block' do
|
32
|
+
it 'should return an enumerator' do
|
33
|
+
e = @set.each_line
|
34
|
+
e.should be_a(Enumerator)
|
35
|
+
e.first.should == @first_line
|
36
|
+
e.next.should == @first_line
|
37
|
+
e.next.should == @second_line
|
38
|
+
end
|
39
|
+
end
|
25
40
|
end
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
describe :each_parsed_line do
|
43
|
+
it 'should enumerate each line backwards' do
|
44
|
+
records = []
|
45
|
+
@set.each_parsed_line do |record|
|
46
|
+
records << record
|
47
|
+
end
|
48
|
+
|
49
|
+
records.first.time.should == Time.new(2013, 06, 23, 17, 00, 01, '-08:00')
|
50
|
+
records.first.code.should == '200'
|
51
|
+
records.last.time.should == Time.new(2013, 06, 23, 16, 49, 00, '-08:00')
|
52
|
+
records.last.code.should == '200'
|
31
53
|
end
|
32
54
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
55
|
+
context 'without a block' do
|
56
|
+
it 'should return an enumerator' do
|
57
|
+
e = @set.each_parsed_line
|
58
|
+
e.should be_a(Enumerator)
|
59
|
+
e.next.time.should == Time.new(2013, 06, 23, 17, 00, 01, '-08:00')
|
60
|
+
end
|
61
|
+
end
|
37
62
|
end
|
38
63
|
end
|
39
64
|
end
|
data/spec/lib/logfile_spec.rb
CHANGED
@@ -7,6 +7,9 @@ module LogfileInterval
|
|
7
7
|
describe Logfile do
|
8
8
|
before :each do
|
9
9
|
@alf = Logfile.new("#{data_dir}/access.log", LineParser::AccessLog)
|
10
|
+
@first_line = '78.54.172.146 - - [01/Jan/2012:16:30:51 -0800] "GET /package/core/oneiric/main/base/abrowser-6.0 HTTP/1.1" 200 6801 "http://www.google.com/url?sa=t&rct=j&q=abrowser 6.0&esrc=s&source=web&cd=4&sqi=2&ved=0CDYQFjAD&url=http%3A%2F%2Fwww.ubuntuupdates.org%2Fpackages%2Fshow%2F268762&ei=s-QlT8vJFon1sgb54unBDg&usg=AFQjCNHCHC0bxTf6aXAfUwT6Erjta6WLaQ&sig2=ceCi1odtaB8Vcf6IWg2a3w" "Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"'
|
11
|
+
@second_line = '78.54.172.146 - - [01/Jan/2012:16:30:51 -0800] "GET /package/show/2 HTTP/1.1" 302 6801 "http://www.google.com/url?sa=t&rct=j&q=abrowser 6.0&esrc=s&source=web&cd=4&sqi=2&ved=0CDYQFjAD&url=http%3A%2F%2Fwww.ubuntuupdates.org%2Fpackages%2Fshow%2F268762&ei=s-QlT8vJFon1sgb54unBDg&usg=AFQjCNHCHC0bxTf6aXAfUwT6Erjta6WLaQ&sig2=ceCi1odtaB8Vcf6IWg2a3w" "Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1"'
|
12
|
+
@last_line = '66.249.67.176 - - [01/Jan/2012:00:57:47 -0800] "GET /packages/show/1 HTTP/1.1" 301 185 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"'
|
10
13
|
end
|
11
14
|
|
12
15
|
it 'first_timestamp returns time of first line in file' do
|
@@ -14,30 +17,52 @@ module LogfileInterval
|
|
14
17
|
@alf.first_timestamp.should == Time.new(2012, 01, 01, 00, 57, 47, '-08:00')
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
describe :each_line do
|
21
|
+
it 'should enumerate each line in file backwards' do
|
22
|
+
lines = []
|
23
|
+
@alf.each_line do |line|
|
24
|
+
lines << line
|
25
|
+
end
|
26
|
+
|
27
|
+
lines.first.should == @first_line
|
28
|
+
lines.last.should == @last_line
|
21
29
|
end
|
22
30
|
|
23
|
-
|
24
|
-
|
31
|
+
context 'without a block' do
|
32
|
+
it 'should return an enumerator' do
|
33
|
+
e = @alf.each_line
|
34
|
+
e.should be_a(Enumerator)
|
35
|
+
e.first.should == @first_line
|
36
|
+
e.next.should == @first_line
|
37
|
+
e.next.should == @second_line
|
38
|
+
end
|
39
|
+
end
|
25
40
|
end
|
26
41
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
describe :each_parsed_line do
|
43
|
+
it 'should enumerate each line backwards' do
|
44
|
+
records = []
|
45
|
+
@alf.each_parsed_line do |record|
|
46
|
+
records << record
|
47
|
+
end
|
48
|
+
|
49
|
+
records.first.time.should == Time.new(2012, 01, 01, 16, 30, 51, '-08:00')
|
50
|
+
records.first.code.should == '200'
|
51
|
+
records.first.length.should == 6801
|
52
|
+
records.first.length_by_ip.should == 6801
|
53
|
+
records.last.time.should == Time.new(2012, 01, 01, 00, 57, 47, '-08:00')
|
54
|
+
records.last.code.should == '301'
|
55
|
+
records.last.length.should == 185
|
56
|
+
records.last.length_by_ip.should == 185
|
31
57
|
end
|
32
58
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
records.last.length_by_ip.should == 185
|
59
|
+
context 'without a block' do
|
60
|
+
it 'should return an enumerator' do
|
61
|
+
e = @alf.each_parsed_line
|
62
|
+
e.should be_a(Enumerator)
|
63
|
+
e.next.time.should == Time.new(2012, 01, 01, 16, 30, 51, '-08:00')
|
64
|
+
end
|
65
|
+
end
|
41
66
|
end
|
42
67
|
end
|
43
68
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logfile_interval
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Philippe Le Rohellec
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -99,25 +99,28 @@ files:
|
|
99
99
|
- bin/aggregate_access_log.rb
|
100
100
|
- bin/readme.rb
|
101
101
|
- docs/design.rb
|
102
|
-
- docs/design2.rb
|
103
|
-
- docs/design3.rb
|
104
102
|
- lib/logfile_interval.rb
|
105
|
-
- lib/logfile_interval/
|
103
|
+
- lib/logfile_interval/aggregator.rb
|
104
|
+
- lib/logfile_interval/aggregator/average.rb
|
105
|
+
- lib/logfile_interval/aggregator/base.rb
|
106
|
+
- lib/logfile_interval/aggregator/count.rb
|
107
|
+
- lib/logfile_interval/aggregator/delta.rb
|
108
|
+
- lib/logfile_interval/aggregator/group_and_count.rb
|
109
|
+
- lib/logfile_interval/aggregator/sum.rb
|
106
110
|
- lib/logfile_interval/interval.rb
|
107
111
|
- lib/logfile_interval/interval_builder.rb
|
108
|
-
- lib/logfile_interval/interval_length.rb
|
109
|
-
- lib/logfile_interval/line_parser/aggregator.rb
|
110
112
|
- lib/logfile_interval/line_parser/base.rb
|
111
|
-
- lib/logfile_interval/line_parser/counter.rb
|
112
113
|
- lib/logfile_interval/logfile.rb
|
113
114
|
- lib/logfile_interval/logfile_set.rb
|
115
|
+
- lib/logfile_interval/util/counter.rb
|
116
|
+
- lib/logfile_interval/util/file_backward.rb
|
114
117
|
- lib/logfile_interval/version.rb
|
115
118
|
- logfile_interval.gemspec
|
119
|
+
- spec/lib/aggregator_spec.rb
|
120
|
+
- spec/lib/counter_spec.rb
|
116
121
|
- spec/lib/interval_builder_spec.rb
|
117
122
|
- spec/lib/interval_spec.rb
|
118
|
-
- spec/lib/line_parser/aggregator_spec.rb
|
119
123
|
- spec/lib/line_parser/base_spec.rb
|
120
|
-
- spec/lib/line_parser/counter_spec.rb
|
121
124
|
- spec/lib/logfile_set_spec.rb
|
122
125
|
- spec/lib/logfile_spec.rb
|
123
126
|
- spec/spec_helper.rb
|
@@ -154,11 +157,11 @@ signing_key:
|
|
154
157
|
specification_version: 4
|
155
158
|
summary: Aggregate logfile data into intervals
|
156
159
|
test_files:
|
160
|
+
- spec/lib/aggregator_spec.rb
|
161
|
+
- spec/lib/counter_spec.rb
|
157
162
|
- spec/lib/interval_builder_spec.rb
|
158
163
|
- spec/lib/interval_spec.rb
|
159
|
-
- spec/lib/line_parser/aggregator_spec.rb
|
160
164
|
- spec/lib/line_parser/base_spec.rb
|
161
|
-
- spec/lib/line_parser/counter_spec.rb
|
162
165
|
- spec/lib/logfile_set_spec.rb
|
163
166
|
- spec/lib/logfile_spec.rb
|
164
167
|
- spec/spec_helper.rb
|
data/docs/design2.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module LogfileInterval
|
2
|
-
class Logfile
|
3
|
-
end
|
4
|
-
|
5
|
-
class LogfileSet
|
6
|
-
end
|
7
|
-
|
8
|
-
class Interval
|
9
|
-
end
|
10
|
-
|
11
|
-
class LineParser
|
12
|
-
def initialize(regex, columns)
|
13
|
-
end
|
14
|
-
|
15
|
-
def parse(line)
|
16
|
-
@data = {}
|
17
|
-
|
18
|
-
match_data = regex.match(line)
|
19
|
-
columns.each do |name, options|
|
20
|
-
val = match_data[options[:pos]]
|
21
|
-
@data[name] = convert(val, options[:conversion])
|
22
|
-
end
|
23
|
-
@data
|
24
|
-
end
|
25
|
-
|
26
|
-
def convert(val, conversion)
|
27
|
-
case options[:conversion]
|
28
|
-
when :integer then val.to_i
|
29
|
-
else val
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Record
|
35
|
-
def initialize(parser, line)
|
36
|
-
@parser = parser
|
37
|
-
@data = parser.parse(line)
|
38
|
-
end
|
39
|
-
|
40
|
-
def valid_columns
|
41
|
-
@parser.columns.keys
|
42
|
-
end
|
43
|
-
|
44
|
-
def method_missing(meth, *args)
|
45
|
-
if valid_columns.include?(meth) && args.none
|
46
|
-
self[meth]
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
logfiles = [ 'access.log', 'access.log.1', 'access.log.2' ]
|
55
|
-
logfile = logfiles.first
|
56
|
-
parser = LineParser.new(/blah/, [ { :name=>:ip , :pos => 1 }, ...])
|
57
|
-
|
58
|
-
logfile_iterator = LogfileInterval::Logfile.new(parser, logfile)
|
59
|
-
|
60
|
-
logfile_iterator.each_line do |line|
|
61
|
-
puts line
|
62
|
-
end
|
63
|
-
|
64
|
-
logfile_iterator.each_parsed_line do |record|
|
65
|
-
puts record.ip
|
66
|
-
puts record.time
|
67
|
-
end
|
68
|
-
|
69
|
-
interval_builder = LogfileInterval::Interval.new(parser, logfiles)
|
70
|
-
|
71
|
-
interval_builder.each_interval do |interval|
|
72
|
-
puts interval.start_time
|
73
|
-
puts interval.length
|
74
|
-
interval[:ip].each do |ip, count|
|
75
|
-
puts "#{ip}, #{count}"
|
76
|
-
end
|
77
|
-
end
|