logmerge 1.0.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.
- data/LICENSE +28 -0
- data/Manifest.txt +14 -0
- data/README +35 -0
- data/Rakefile +63 -0
- data/bin/ip2name +8 -0
- data/bin/logmerge +6 -0
- data/lib/logmerge/merger.rb +74 -0
- data/lib/logmerge/resolv.rb +1892 -0
- data/lib/logmerge/resolver.rb +162 -0
- data/lib/logmerge.rb +13 -0
- data/resolv_test +26 -0
- data/test/access.log +10 -0
- data/test/test_merger.rb +86 -0
- data/test/test_resolver.rb +234 -0
- metadata +59 -0
data/LICENSE
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
All original code copyright 2005 Eric Hodel, The Robot Co-op. All rights
|
2
|
+
reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
|
8
|
+
1. Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
3. Neither the names of the authors nor the names of their contributors
|
14
|
+
may be used to endorse or promote products derived from this software
|
15
|
+
without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
18
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
19
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
21
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
22
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
23
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
24
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
25
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
26
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
27
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
data/Manifest.txt
ADDED
data/README
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
= logmerge
|
2
|
+
|
3
|
+
Rubyforge Project:
|
4
|
+
|
5
|
+
http://rubyforge.org/projects/rctools/
|
6
|
+
|
7
|
+
== About
|
8
|
+
|
9
|
+
Logmerge contains two utilities logmerge and ip2name. logmerge merges Apache
|
10
|
+
access logs into one log ordered by date. ip2name performs DNS lookups on
|
11
|
+
Apache access logs using multiple threads and Ruby's DNS resolver library to
|
12
|
+
speed through log files.
|
13
|
+
|
14
|
+
== Using logmerge
|
15
|
+
|
16
|
+
Simply pass in all the logs you want to merge on the command line. logmerge
|
17
|
+
gives you the merged log on STDOUT.
|
18
|
+
|
19
|
+
logmerge hal/access.log nestor/access.log herbie/access.log > merged.log
|
20
|
+
|
21
|
+
Note that logmerge expects the input log files to be ordered by date.
|
22
|
+
|
23
|
+
== Using ip2name
|
24
|
+
|
25
|
+
Simply pass in the log files you want to perform DNS lookups on the command
|
26
|
+
line or via STDIN. ip2name gives you the looked-up log lines on STDOUT.
|
27
|
+
|
28
|
+
ip2name < merged.log > resolved.log
|
29
|
+
|
30
|
+
ip2name merged.log > resolved.log
|
31
|
+
|
32
|
+
In order to speed DNS lookups, ip2name creates a .name_cache file in the
|
33
|
+
current directory. ip2name uses double the DNS record TTL value so
|
34
|
+
rapidly-changing names may not be correctly resolved.
|
35
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
$VERBOSE = nil
|
7
|
+
|
8
|
+
spec = Gem::Specification.new do |s|
|
9
|
+
s.name = 'logmerge'
|
10
|
+
s.version = '1.0.0'
|
11
|
+
s.summary = 'Resolves IP addresses and merges Apache access logs.'
|
12
|
+
s.author = 'Eric Hodel'
|
13
|
+
s.email = 'eric@robotcoop.com'
|
14
|
+
|
15
|
+
s.files = File.read('Manifest.txt').split($/)
|
16
|
+
s.require_path = 'lib'
|
17
|
+
|
18
|
+
s.executables = %w[ip2name logmerge]
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Run tests'
|
22
|
+
task :default => [ :test ]
|
23
|
+
|
24
|
+
Rake::TestTask.new('test') do |t|
|
25
|
+
t.libs << 'test'
|
26
|
+
t.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Update Manifest.txt'
|
30
|
+
task :update_manifest do
|
31
|
+
sh "find . -type f | sed -e 's%./%%' | egrep -v 'svn|swp|~' | egrep -v '^(doc|pkg)/' | sort > Manifest.txt"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc 'Generate RDoc'
|
35
|
+
Rake::RDocTask.new :rdoc do |rd|
|
36
|
+
rd.rdoc_dir = 'doc'
|
37
|
+
rd.rdoc_files.add 'lib', 'README', 'LICENSE'
|
38
|
+
rd.rdoc_files.exclude '*/resolv.rb' # WTF doesn't this work?
|
39
|
+
rd.main = 'README'
|
40
|
+
rd.options << '-d' if `which dot` =~ /\/dot/
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'Generate RDoc for dev.robotcoop.com'
|
44
|
+
Rake::RDocTask.new :dev_rdoc do |rd|
|
45
|
+
rd.rdoc_dir = '../../../www/trunk/dev/html/Tools/logmerge'
|
46
|
+
rd.rdoc_files.add 'lib', 'README', 'LICENSE'
|
47
|
+
rd.main = 'README'
|
48
|
+
rd.options << '-d' if `which dot` =~ /\/dot/
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'Build Gem'
|
52
|
+
Rake::GemPackageTask.new spec do |pkg|
|
53
|
+
pkg.need_tar = true
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Clean up'
|
57
|
+
task :clean => [ :clobber_rdoc, :clobber_package ]
|
58
|
+
|
59
|
+
desc 'Clean up'
|
60
|
+
task :clobber => [ :clean ]
|
61
|
+
|
62
|
+
# vim: syntax=Ruby
|
63
|
+
|
data/bin/ip2name
ADDED
data/bin/logmerge
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
$TESTING = defined? $TESTING
|
2
|
+
|
3
|
+
require 'logmerge'
|
4
|
+
|
5
|
+
##
|
6
|
+
# Merges multiple Apache log files by date.
|
7
|
+
|
8
|
+
class LogMerge::Merger
|
9
|
+
|
10
|
+
##
|
11
|
+
# Merges +files+ into +output+. If +files+ is nil, ARGV is used.
|
12
|
+
|
13
|
+
def self.merge(output = STDOUT, *files)
|
14
|
+
files = ARGV if files.empty?
|
15
|
+
merger = LogMerge::Merger.new files.map { |file| File.open file }
|
16
|
+
merger.merge output
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Creates a new Merger that will operate on an array of IO-like objects
|
21
|
+
# +streams+.
|
22
|
+
|
23
|
+
def initialize(streams)
|
24
|
+
@streams = streams
|
25
|
+
@buf = []
|
26
|
+
|
27
|
+
@streams.each_index { |slot| buf_fill slot }
|
28
|
+
|
29
|
+
@all_closed = @streams.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Are all the streams closed?
|
34
|
+
|
35
|
+
def all_closed?
|
36
|
+
@all_closed
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Adds a line to the buffer from input strem +slot+.
|
41
|
+
|
42
|
+
def buf_fill(slot)
|
43
|
+
line = @streams[slot].gets
|
44
|
+
|
45
|
+
if line.nil? and @streams[slot].eof? then
|
46
|
+
@streams.delete_at slot
|
47
|
+
@buf.delete_at slot
|
48
|
+
elsif line.nil? then
|
49
|
+
raise "WTF? line.nil? and not eof?"
|
50
|
+
else
|
51
|
+
line =~ / \[(.+?)\] /
|
52
|
+
time = Time.parse($1.sub(':', ' ').gsub('/', '-')).to_i
|
53
|
+
@buf[slot] = [time, line]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Merges streams into +out_stream+.
|
59
|
+
|
60
|
+
def merge(out_stream)
|
61
|
+
index, min, line = nil
|
62
|
+
|
63
|
+
until @streams.empty? do
|
64
|
+
min = @buf.min { |a,b| a.first <=> b.first}
|
65
|
+
slot = @buf.index min
|
66
|
+
buf_fill slot
|
67
|
+
out_stream.puts min.last
|
68
|
+
end
|
69
|
+
|
70
|
+
@all_closed = true
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|