logfile_interval 2.0.0 → 2.1.0
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/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/lib/logfile_interval/interval.rb +4 -2
- data/lib/logfile_interval/interval_builder/ascending.rb +1 -1
- data/lib/logfile_interval/interval_builder/descending.rb +1 -1
- data/lib/logfile_interval/interval_builder.rb +15 -7
- data/lib/logfile_interval/logfile_set.rb +9 -3
- data/lib/logfile_interval/version.rb +1 -1
- data/logfile_interval.gemspec +1 -1
- data/spec/lib/interval_builder_spec.rb +50 -0
- data/spec/lib/interval_spec.rb +8 -0
- data/spec/lib/logfile_set_spec.rb +17 -4
- metadata +18 -19
- data/Gemfile.lock +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 704912eefe0f7a801ed450cf303e2fa9ef7fe4d1
|
4
|
+
data.tar.gz: 08108c223fd1d1cbf1069963289a360d5691b302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 318f6ca2c18baf0d3155051d37d1de8a406d8b631bba9ffe50067e31230369178992bd089808899ba96e476f9a76b2373b14feb41eb31717446bee3e36bfe24a
|
7
|
+
data.tar.gz: 88d9243b530a0bf9dbff4ec81dadefe05bce00c14d8e61841c04e6f096be7960b398ed37719ffa61421dff21c91f5c101bb9d6a10129f6743d955fff881d8ccc
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -6,7 +6,6 @@ module LogfileInterval
|
|
6
6
|
class OutOfRange < StandardError; end
|
7
7
|
|
8
8
|
def initialize(end_time, length, parser_columns)
|
9
|
-
raise ArgumentError, 'end_time must be round' unless (end_time.to_i % length.to_i == 0)
|
10
9
|
@end_time = end_time
|
11
10
|
@start_time = end_time - length
|
12
11
|
@length = length
|
@@ -21,7 +20,10 @@ module LogfileInterval
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def to_hash
|
24
|
-
@aggregators.to_hash
|
23
|
+
h = @aggregators.to_hash
|
24
|
+
h[:start_time] = self.start_time
|
25
|
+
h[:end_time] = self.end_time
|
26
|
+
h
|
25
27
|
end
|
26
28
|
|
27
29
|
def add_record(record)
|
@@ -3,7 +3,7 @@ module LogfileInterval
|
|
3
3
|
module Ascending
|
4
4
|
def create_first_interval
|
5
5
|
first_record = parsed_lines_enum.first
|
6
|
-
interval_end_time =
|
6
|
+
interval_end_time = end_boundary_time(first_record.time)
|
7
7
|
Interval.new(interval_end_time, length, parser_columns)
|
8
8
|
end
|
9
9
|
|
@@ -5,11 +5,19 @@ module LogfileInterval
|
|
5
5
|
class IntervalBuilder
|
6
6
|
attr_reader :parsed_lines_enum, :parser_columns, :length
|
7
7
|
|
8
|
-
def initialize(parsed_lines_enum, parser_columns, length)
|
8
|
+
def initialize(parsed_lines_enum, parser_columns, length, options = {})
|
9
9
|
@parsed_lines_enum = parsed_lines_enum
|
10
10
|
@parser_columns = parser_columns
|
11
11
|
@length = length
|
12
12
|
|
13
|
+
raise ArgumentError if options.include?(:boundary_offset) && options.include?(:offset_by_start_time)
|
14
|
+
|
15
|
+
@boundary_offset = options.fetch(:boundary_offset, 0)
|
16
|
+
offset_by_start_time = options.fetch(:offset_by_start_time, nil)
|
17
|
+
if offset_by_start_time
|
18
|
+
@boundary_offset = offset_by_start_time.to_i % length
|
19
|
+
end
|
20
|
+
|
13
21
|
case order
|
14
22
|
when :asc then self.extend Ascending
|
15
23
|
when :desc then self.extend Descending
|
@@ -37,18 +45,18 @@ module LogfileInterval
|
|
37
45
|
each_interval.first
|
38
46
|
end
|
39
47
|
|
40
|
-
|
41
|
-
|
42
|
-
def lower_boundary_time(t)
|
43
|
-
secs = (t.to_i / length.to_i) * length.to_i
|
48
|
+
def start_boundary_time(t)
|
49
|
+
secs = ((t.to_i - @boundary_offset) / length.to_i) * length.to_i + @boundary_offset
|
44
50
|
Time.at(secs)
|
45
51
|
end
|
46
52
|
|
47
|
-
def
|
48
|
-
secs = (t.to_i / length.to_i + 1) * length.to_i
|
53
|
+
def end_boundary_time(t)
|
54
|
+
secs = ((t.to_i - @boundary_offset)/ length.to_i + 1) * length.to_i + @boundary_offset
|
49
55
|
Time.at(secs)
|
50
56
|
end
|
51
57
|
|
58
|
+
private
|
59
|
+
|
52
60
|
def order
|
53
61
|
return @order if @order
|
54
62
|
num_lines = 0
|
@@ -4,10 +4,11 @@ module LogfileInterval
|
|
4
4
|
|
5
5
|
ORDER_VALID_VALUES = [ :asc, :desc ]
|
6
6
|
|
7
|
-
def initialize(filenames, parser, order = :desc)
|
7
|
+
def initialize(filenames, parser, order = :desc, &file_time_finder_block)
|
8
8
|
@parser = parser
|
9
9
|
@filenames = filenames
|
10
10
|
@order = order
|
11
|
+
@file_time_finder_block = file_time_finder_block if block_given?
|
11
12
|
|
12
13
|
raise ArgumentError, "invalid order value: #{@order}" unless ORDER_VALID_VALUES.include?(@order.to_sym)
|
13
14
|
end
|
@@ -56,8 +57,13 @@ module LogfileInterval
|
|
56
57
|
|
57
58
|
def time_for_files(filenames)
|
58
59
|
filenames.inject({}) do |h, filename|
|
59
|
-
|
60
|
-
|
60
|
+
if @file_time_finder_block
|
61
|
+
t = @file_time_finder_block.call(filename)
|
62
|
+
else
|
63
|
+
file = Logfile.new(filename, parser)
|
64
|
+
t = file.first_timestamp
|
65
|
+
end
|
66
|
+
h[filename] = t
|
61
67
|
h
|
62
68
|
end
|
63
69
|
end
|
data/logfile_interval.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
-
spec.add_development_dependency "
|
22
|
+
spec.add_development_dependency "byebug", [">= 0"] if RUBY_VERSION >= '2.0.0'
|
23
23
|
spec.add_development_dependency "rspec", ["~> 2.14.0"]
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
spec.add_development_dependency "simplecov"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
|
2
3
|
require File.join(File.dirname(__FILE__), '..', 'support/lib/timing_log')
|
3
4
|
|
4
5
|
module LogfileInterval
|
@@ -37,6 +38,55 @@ module LogfileInterval
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
41
|
+
describe :boundary_offset do
|
42
|
+
it 'returns the start of the interval on a round boundary' do
|
43
|
+
set = LogfileSet.new(@logfiles, ParsedLine::TimingLog)
|
44
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 60)
|
45
|
+
expect(builder.start_boundary_time(Time.new(2013,12,01,16,0,1))).to eql(Time.new(2013,12,01,16,0,0))
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'first interval is aligned on round boundary' do
|
49
|
+
Time.stub(:now).and_return(Time.new(2013,12,01,16,0,1,'-08:00'))
|
50
|
+
set = LogfileSet.new(@logfiles, ParsedLine::TimingLog)
|
51
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 3600)
|
52
|
+
builder.first_interval.start_time.should == Time.new(2013,12,01,15,0,0,'-08:00')
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'with offset' do
|
56
|
+
it 'returns the start of the interval on an offset boundary' do
|
57
|
+
set = LogfileSet.new(@logfiles, ParsedLine::TimingLog)
|
58
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 60, boundary_offset: 5)
|
59
|
+
expect(builder.start_boundary_time(Time.new(2013,12,01,16,0,1))).to eql(Time.new(2013,12,01,15,59,05))
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'first interval is aligned on round boundary' do
|
63
|
+
Time.stub(:now).and_return(Time.new(2013,12,01,17,1,1,'-08:00'))
|
64
|
+
set = LogfileSet.new(@logfiles, ParsedLine::TimingLog)
|
65
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 3600, boundary_offset: 300)
|
66
|
+
builder.first_interval.start_time.should == Time.new(2013,12,01,15,05,0,'-08:00')
|
67
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 3600, boundary_offset: 60)
|
68
|
+
builder.first_interval.start_time.should == Time.new(2013,12,01,16,01,0,'-08:00')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe :offset_by_start_time do
|
74
|
+
it 'returns the start of the interval on an offset boundary' do
|
75
|
+
set = LogfileSet.new(@logfiles, ParsedLine::TimingLog)
|
76
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 60, offset_by_start_time: Time.new(2013,12,01,15,59,05))
|
77
|
+
expect(builder.start_boundary_time(Time.new(2013,12,01,16,0,1))).to eql(Time.new(2013,12,01,15,59,05))
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'first interval is aligned on round boundary' do
|
81
|
+
Time.stub(:now).and_return(Time.new(2013,12,01,17,1,1,'-08:00'))
|
82
|
+
set = LogfileSet.new(@logfiles, ParsedLine::TimingLog)
|
83
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 3600, offset_by_start_time: Time.new(2013,12,01,16,05,0))
|
84
|
+
builder.first_interval.start_time.should == Time.new(2013,12,01,15,05,0,'-08:00')
|
85
|
+
builder = IntervalBuilder.new(set, ParsedLine::TimingLog, 3600, offset_by_start_time: Time.new(2013,12,01,15,01,0))
|
86
|
+
builder.first_interval.start_time.should == Time.new(2013,12,01,16,01,0,'-08:00')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
40
90
|
describe :each_interval do
|
41
91
|
context 'without a block' do
|
42
92
|
it 'returns an enumerator' do
|
data/spec/lib/interval_spec.rb
CHANGED
@@ -33,6 +33,14 @@ module LogfileInterval
|
|
33
33
|
hinterval.keys.should include(:ip, :total_time, :action, :num_bytes, :rss)
|
34
34
|
end
|
35
35
|
|
36
|
+
it 'has start_time and end_time keys' do
|
37
|
+
record = ParsedLine::TimingLog.create_record('1385942400, 192.168.0.5, posts#index, 100, 2000, 53.0')
|
38
|
+
interval = Interval.new(@end_time, @length, ParsedLine::TimingLog.columns)
|
39
|
+
interval.add_record(record)
|
40
|
+
hinterval = interval.to_hash
|
41
|
+
hinterval.keys.should include(:start_time, :end_time)
|
42
|
+
end
|
43
|
+
|
36
44
|
it 'with no data, should have keys with 0 values' do
|
37
45
|
interval = Interval.new(@end_time, @length, ParsedLine::TimingLog.columns)
|
38
46
|
hinterval = interval.to_hash
|
@@ -13,10 +13,6 @@ module LogfileInterval
|
|
13
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)"'
|
14
14
|
end
|
15
15
|
|
16
|
-
it 'ordered_filenames should return the most recent file first' do
|
17
|
-
@set.ordered_filenames.should == @logfiles.reverse
|
18
|
-
end
|
19
|
-
|
20
16
|
describe :each_line do
|
21
17
|
it 'should enumerate each line in file backwards' do
|
22
18
|
lines = []
|
@@ -82,5 +78,22 @@ module LogfileInterval
|
|
82
78
|
end
|
83
79
|
end
|
84
80
|
end
|
81
|
+
|
82
|
+
describe :ordered_filenames do
|
83
|
+
it 'returns the most recent file first' do
|
84
|
+
@set.ordered_filenames.should == @logfiles.reverse
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with file_time_finder_block' do
|
88
|
+
it 'sorts the files in the order described in the block' do
|
89
|
+
set = LogfileSet.new(@logfiles, ParsedLine::AccessLog) do |filename|
|
90
|
+
filename.match /(?<num>\d+$)/ do |matchdata|
|
91
|
+
matchdata[:num].to_i
|
92
|
+
end
|
93
|
+
end
|
94
|
+
set.ordered_filenames.should == @logfiles
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
85
98
|
end
|
86
99
|
end
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logfile_interval
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
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-
|
11
|
+
date: 2014-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 2.14.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 2.14.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: simplecov
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: Logfile parser and aggregator
|
@@ -89,10 +89,9 @@ executables:
|
|
89
89
|
extensions: []
|
90
90
|
extra_rdoc_files: []
|
91
91
|
files:
|
92
|
-
- .gitignore
|
93
|
-
- .travis.yml
|
92
|
+
- ".gitignore"
|
93
|
+
- ".travis.yml"
|
94
94
|
- Gemfile
|
95
|
-
- Gemfile.lock
|
96
95
|
- LICENSE.txt
|
97
96
|
- README.md
|
98
97
|
- Rakefile
|
@@ -150,17 +149,17 @@ require_paths:
|
|
150
149
|
- lib
|
151
150
|
required_ruby_version: !ruby/object:Gem::Requirement
|
152
151
|
requirements:
|
153
|
-
- -
|
152
|
+
- - ">="
|
154
153
|
- !ruby/object:Gem::Version
|
155
154
|
version: '0'
|
156
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
156
|
requirements:
|
158
|
-
- -
|
157
|
+
- - ">="
|
159
158
|
- !ruby/object:Gem::Version
|
160
159
|
version: '0'
|
161
160
|
requirements: []
|
162
161
|
rubyforge_project:
|
163
|
-
rubygems_version: 2.
|
162
|
+
rubygems_version: 2.2.2
|
164
163
|
signing_key:
|
165
164
|
specification_version: 4
|
166
165
|
summary: Aggregate logfile data into intervals
|
data/Gemfile.lock
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
logfile_interval (2.0.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
columnize (0.3.6)
|
10
|
-
debugger (1.6.5)
|
11
|
-
columnize (>= 0.3.1)
|
12
|
-
debugger-linecache (~> 1.2.0)
|
13
|
-
debugger-ruby_core_source (~> 1.3.1)
|
14
|
-
debugger-linecache (1.2.0)
|
15
|
-
debugger-ruby_core_source (1.3.1)
|
16
|
-
diff-lcs (1.2.5)
|
17
|
-
docile (1.1.1)
|
18
|
-
multi_json (1.8.2)
|
19
|
-
rake (10.1.0)
|
20
|
-
rspec (2.14.1)
|
21
|
-
rspec-core (~> 2.14.0)
|
22
|
-
rspec-expectations (~> 2.14.0)
|
23
|
-
rspec-mocks (~> 2.14.0)
|
24
|
-
rspec-core (2.14.7)
|
25
|
-
rspec-expectations (2.14.4)
|
26
|
-
diff-lcs (>= 1.1.3, < 2.0)
|
27
|
-
rspec-mocks (2.14.4)
|
28
|
-
simplecov (0.8.2)
|
29
|
-
docile (~> 1.1.0)
|
30
|
-
multi_json
|
31
|
-
simplecov-html (~> 0.8.0)
|
32
|
-
simplecov-html (0.8.0)
|
33
|
-
|
34
|
-
PLATFORMS
|
35
|
-
ruby
|
36
|
-
|
37
|
-
DEPENDENCIES
|
38
|
-
bundler (~> 1.3)
|
39
|
-
debugger
|
40
|
-
logfile_interval!
|
41
|
-
rake
|
42
|
-
rspec (~> 2.14.0)
|
43
|
-
simplecov
|