ktlacaelel-plog 0.0.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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ kazu.test
7
+ objects
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kazuyoshi Tlacaelel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,18 @@
1
+ = plog
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 Kazuyoshi Tlacaelel. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "plog"
8
+ gem.summary = %Q{TODO: one-line summary of your gem}
9
+ gem.description = %Q{TODO: longer description of your gem}
10
+ gem.email = "kazu.dev@gmail.com"
11
+ gem.homepage = "http://github.com/ktlacaelel/plog"
12
+ gem.authors = ["Kazuyoshi Tlacaelel"]
13
+ gem.add_development_dependency "thoughtbot-shoulda"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.pattern = 'test/**/*_test.rb'
24
+ test.verbose = true
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+ task :test => :check_dependencies
41
+
42
+ task :default => :test
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ if File.exist?('VERSION')
47
+ version = File.read('VERSION')
48
+ else
49
+ version = ""
50
+ end
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "plog #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
data/bin/plog ADDED
@@ -0,0 +1,22 @@
1
+ #!/home/jognote/ruby/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'plog'
5
+
6
+ banner = '
7
+ ERROR!
8
+ No logs given, I have nothing to do!
9
+
10
+ HELP?
11
+ The "plog" ( production log ) executable receives one option.
12
+ This must be a directory containing one or more production logs.
13
+ Only logs in the first level will be parsed.
14
+ Recursive reading is not allowed
15
+
16
+ USAGE:
17
+ $ plog directory_with_logs/
18
+
19
+ '
20
+
21
+ abort banner if ARGV.size != 1
22
+ Plog::Cli.new(ARGV[0]).run!
data/lib/cli.rb ADDED
@@ -0,0 +1,112 @@
1
+ module Plog
2
+
3
+ class Cli
4
+
5
+ attr_reader :directory, :log_files
6
+
7
+ LOG_FILE = 'log_statistics.txt'
8
+
9
+ # ==========================================================================
10
+ # CLIENT INTERFACE
11
+ # ==========================================================================
12
+
13
+ def initialize(directory)
14
+ @directory = directory
15
+ @log_files = []
16
+ validate!
17
+ load_log_files!
18
+ end
19
+
20
+ def run!
21
+ stdout count_of_logs_banner(@log_files.size)
22
+ stdout notice_banner
23
+ create_object_files
24
+ destroy_old_log_file
25
+ append_headers_to_log_file
26
+ parse_object_files
27
+ end
28
+
29
+ # ==========================================================================
30
+ # INTERNAL INTERFACE
31
+ # ==========================================================================
32
+
33
+ protected
34
+
35
+ def trim(string)
36
+ return '' unless string.is_a? String
37
+ string.gsub(/^\s+/, '').gsub(/\s+$/, '')
38
+ end
39
+
40
+ def create_object_files
41
+ @log_files.each do |log_file|
42
+ stdout parsing_log_file_banner(log_file.name)
43
+ log_file.parse_completed_lines!
44
+ end
45
+ end
46
+
47
+ def parse_object_files
48
+ Dir.glob('objects/*').each do |object_file|
49
+ file = File.new(LOG_FILE, 'a+')
50
+ file.puts trim(ObjectFile.new(object_file).export)
51
+ file.close
52
+ end
53
+ end
54
+
55
+ def destroy_old_log_file
56
+ FileUtils.touch LOG_FILE
57
+ FileUtils.rm LOG_FILE
58
+ end
59
+
60
+ def append_headers_to_log_file
61
+ file = File.new(LOG_FILE, 'a+')
62
+ file.puts trim(ObjectFile.formated_headers)
63
+ file.close
64
+ end
65
+
66
+ def validate!
67
+ abort directory_not_found_banner unless File.exist? @directory
68
+ end
69
+
70
+ def load_log_files!
71
+ Dir.glob(File.join(@directory, '*.log')).each do |log_file|
72
+ @log_files << LogFile.new(log_file)
73
+ stdout loading_log_file_banner(log_file)
74
+ end
75
+ end
76
+
77
+ def stdout(string)
78
+ puts ' ** ' + string
79
+ end
80
+
81
+ # ==========================================================================
82
+ # BANNERS
83
+ # ==========================================================================
84
+
85
+ def notice_banner
86
+ '
87
+ NOTICE:
88
+
89
+ Parsing logs, this may take a logn-while go get yourself a coffe!
90
+ While I hanlde this stuff for you.
91
+ '
92
+ end
93
+
94
+ def count_of_logs_banner(size)
95
+ 'Count of loaded logs : %s ' % size
96
+ end
97
+
98
+ def parsing_log_file_banner(file)
99
+ 'Parsing log located at : %s ' % file
100
+ end
101
+
102
+ def loading_log_file_banner(file)
103
+ 'Initializing log file: %s' % file
104
+ end
105
+
106
+ def directory_not_found_banner
107
+ 'No such dir: %s' % @directory
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,110 @@
1
+ module Plog
2
+
3
+ class CompletedLine
4
+
5
+ TOTAL_TIME_REGEX = /^(Completed in )(\d+)ms/ # \2
6
+ VIEW_TIME_REGEX = /([^\(]+)([^V]+)(View: )(\d+)(.*)/ # \4
7
+ DB_TIME_REGEX = /([^\(]+)([^D]+)(DB: )(\d+)(.*)/ # \4
8
+ URL_REGEX = /([^\[]+)(\[)([^\]]+)(.*)/
9
+ STATUS_REGEX = /(\s)(\d+)(\s)(\w+)(\s)(\[)(.*)/ # \2, \4
10
+ COMPLETED_TIME_REGEX = /^Completed/
11
+
12
+ def self.url
13
+ URL.new(@url)
14
+ end
15
+
16
+ def self.valid?
17
+ completed_line?
18
+ end
19
+
20
+ def self.completed_line?
21
+ return false unless @line.is_a? String
22
+ return false unless COMPLETED_TIME_REGEX =~ @line
23
+ return false unless DB_TIME_REGEX =~ @line
24
+ return false if @line.size < 10
25
+ true
26
+ end
27
+
28
+ def self.read!(string_line)
29
+ @line = string_line
30
+ validate
31
+ end
32
+
33
+ def self.db_time
34
+ @db_time
35
+ end
36
+
37
+ def self.view_time
38
+ @view_time
39
+ end
40
+
41
+ def self.total_time
42
+ @total_time
43
+ end
44
+
45
+ def self.status_string
46
+ @status_string
47
+ end
48
+
49
+ def self.status_number
50
+ @status_number
51
+ end
52
+
53
+ def self.to_csv
54
+ [total_time, view_time, db_time, url.simplify].join(',')
55
+ end
56
+
57
+ def self.merge(view, db)
58
+ @view_time += view.to_i
59
+ @db_time += db.to_i
60
+ @total_time = (@view_time + @db_time)
61
+ end
62
+
63
+ protected
64
+
65
+ def self.validate
66
+ return unless completed_line?
67
+ fragmentize!
68
+ extract_time!
69
+ extract_url!
70
+ end
71
+
72
+ def self.fragmentize!
73
+ @first_fragment, @second_fragment = @line.split('|')
74
+ end
75
+
76
+ def self.extract_time!
77
+ @total_time = extract_total_time
78
+ @view_time = extract_view_time
79
+ @db_time = extract_db_time
80
+ @status_number, @status_string = extract_status_number_and_string
81
+ nil
82
+ end
83
+
84
+ def self.extract_total_time
85
+ return 0 unless TOTAL_TIME_REGEX =~ @first_fragment
86
+ @first_fragment.gsub(TOTAL_TIME_REGEX, '\2').to_i
87
+ end
88
+
89
+ def self.extract_db_time
90
+ return 0 unless DB_TIME_REGEX =~ @first_fragment
91
+ @first_fragment.gsub(DB_TIME_REGEX, '\4').to_i
92
+ end
93
+
94
+ def self.extract_view_time
95
+ return 0 unless VIEW_TIME_REGEX =~ @first_fragment
96
+ @first_fragment.gsub(VIEW_TIME_REGEX, '\4').to_i
97
+ end
98
+
99
+ def self.extract_status_number_and_string
100
+ return 0 unless STATUS_REGEX =~ @second_fragment
101
+ @second_fragment.gsub(STATUS_REGEX, '\2,\4').split(',')
102
+ end
103
+
104
+ def self.extract_url!
105
+ @url = @second_fragment.gsub(URL_REGEX, '\3')
106
+ end
107
+
108
+ end
109
+
110
+ end
data/lib/log_file.rb ADDED
@@ -0,0 +1,46 @@
1
+ module Plog
2
+
3
+ class LogFile < File
4
+
5
+ DUMP_DIR = 'objects'
6
+
7
+ attr_accessor :name
8
+
9
+ def initialize(file)
10
+ unless File.exist? DUMP_DIR
11
+ Dir.mkdir DUMP_DIR
12
+ end
13
+ super(file, 'r')
14
+ @name = file
15
+ end
16
+
17
+ def validate(file)
18
+ abort 'File not found: ' + file.inspect unless File.exist? file
19
+ end
20
+
21
+ def parse_completed_lines!
22
+ each_line do |line|
23
+ CompletedLine.read! line
24
+ parse_completed_line
25
+ end
26
+ end
27
+
28
+ def parse_completed_line
29
+ return unless CompletedLine.valid?
30
+ of = ObjectFile.new(object_path, 'w+')
31
+ of.simplified_url = CompletedLine.url.simplify
32
+ of.append_total_time CompletedLine.total_time
33
+ of.append_db_time CompletedLine.db_time
34
+ of.append_view_time CompletedLine.view_time
35
+ of.append_hits 1
36
+ of.save_changes!
37
+ of.close
38
+ end
39
+
40
+ def object_path
41
+ File.join(DUMP_DIR, CompletedLine.url.hashify)
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,153 @@
1
+ module Plog
2
+
3
+ class ObjectFile < File
4
+
5
+ DEFAULT_VALUES = {
6
+ :@total_hits => 0,
7
+ :@total_time => 0,
8
+ :@view_time => 0,
9
+ :@db_time => 0,
10
+ :@simplified_url => 'default'
11
+ }
12
+
13
+ KEY_ORDER = [
14
+ :@total_hits,
15
+ :@total_time,
16
+ :@view_time,
17
+ :@db_time,
18
+ :@simplified_url
19
+ ]
20
+
21
+ attr_accessor :simplified_url
22
+ attr_reader :view_time, :total_time, :db_time, :total_hits
23
+
24
+ def initialize(*args)
25
+ raw_data(args.first)
26
+ super(*args)
27
+ setup!
28
+ end
29
+
30
+ def setup!
31
+ unpack_default_values if ObjectFile.zero? path
32
+ load_changes!
33
+ end
34
+
35
+ def unpack_default_values
36
+ DEFAULT_VALUES.each do |k, v|
37
+ instance_variable_set k, v
38
+ end
39
+ end
40
+
41
+ def append_view_time(value)
42
+ @view_time += value.to_i
43
+ end
44
+
45
+ def append_db_time(value)
46
+ @db_time += value.to_i
47
+ end
48
+
49
+ def append_total_time(value)
50
+ @total_time += value
51
+ end
52
+
53
+ def append_hits(value)
54
+ @total_hits += value
55
+ end
56
+
57
+ def save_changes!
58
+ puts serialize_changes
59
+ end
60
+
61
+ def serialize_changes
62
+ KEY_ORDER.collect { |key| instance_variable_get key }.join(',')
63
+ end
64
+
65
+ def load_changes!
66
+ return if @raw_data == ''
67
+ @total_hits, @total_time, @view_time, @db_time, @simplified_url = @raw_data.split(',')
68
+ intify!
69
+ end
70
+
71
+ def intify!
72
+ @total_hits = @total_hits.to_i
73
+ @total_time = @total_time.to_i
74
+ @db_time = @db_time.to_i
75
+ @view_time = @view_time.to_i
76
+ end
77
+
78
+ def raw_data(some_string)
79
+ if File.exist? some_string
80
+ @raw_data = File.new(some_string).read
81
+ else
82
+ @raw_data = ''
83
+ end
84
+ end
85
+
86
+ def export_settings
87
+ [
88
+ [@total_hits, [:left, 10]],
89
+ [@total_time, [:left, 10]],
90
+ [avg_total_time, [:left, 10]],
91
+ [@db_time, [:left, 10]],
92
+ [avg_db_time, [:left, 10]],
93
+ [@view_time, [:left, 10]],
94
+ [avg_view_time, [:left, 10]],
95
+ [simplified_url, [:left, 40]],
96
+ ]
97
+ end
98
+
99
+ def self.export_header_settings
100
+ [
101
+ ['Hits', [:left, 10]],
102
+ ['Time', [:left, 10]],
103
+ ['Avg-Time', [:left, 10]],
104
+ ['DbTime', [:left, 10]],
105
+ ['Avg-DB', [:left, 10]],
106
+ ['View', [:left, 10]],
107
+ ['Avg-View', [:left, 10]],
108
+ ['Url', [:left, 40]],
109
+ ]
110
+ end
111
+
112
+ def self.formated_headers
113
+ export_header_settings.collect do |value, setting|
114
+ if setting.first == :left
115
+ value.to_s.ljust(setting[1])
116
+ else
117
+ value.to_s.rjust(setting[1])
118
+ end
119
+ end.join('') + "\n"
120
+ end
121
+
122
+ def export_headers
123
+ export_header_settings.collect { |header| header.ljust(20) }.join('')
124
+ end
125
+
126
+ def export
127
+ export_settings.collect do |value, setting|
128
+ if setting.first == :left
129
+ value.to_s.ljust(setting[1])
130
+ else
131
+ value.to_s.rjust(setting[1])
132
+ end
133
+ end.join('')
134
+ end
135
+
136
+ def avg_total_time
137
+ return 0 if @total_time == 0
138
+ (@total_time / @total_hits / 1000.0)
139
+ end
140
+
141
+ def avg_view_time
142
+ return 0 if @view_time == 0
143
+ (@view_time / @total_hits / 1000.0)
144
+ end
145
+
146
+ def avg_db_time
147
+ return 0 if @db_time == 0
148
+ (@db_time / @total_hits / 1000.0)
149
+ end
150
+
151
+ end
152
+
153
+ end
data/lib/plog.rb ADDED
@@ -0,0 +1,13 @@
1
+
2
+ # required external libraries
3
+ require 'fileutils'
4
+ require 'md5'
5
+ require 'uri'
6
+
7
+ # required internal libraries
8
+ require 'lib/cli'
9
+ require 'lib/completed_line'
10
+ require 'lib/log_file'
11
+ require 'lib/object_file'
12
+ require 'lib/url'
13
+
data/lib/url.rb ADDED
@@ -0,0 +1,36 @@
1
+ module Plog
2
+
3
+ class URL
4
+
5
+ def initialize(url)
6
+ @url = url
7
+ @obj = URI.parse URI.escape(url)
8
+ end
9
+
10
+ def to_s
11
+ @url
12
+ end
13
+
14
+ def simplify
15
+ simplify_url = @url.dup
16
+ simplifiers.each { |k, v| simplify_url.gsub!(k, v) if k =~ simplify_url }
17
+ simplify_url
18
+ end
19
+
20
+ def hashify
21
+ ::MD5.hexdigest simplify
22
+ end
23
+
24
+ protected
25
+
26
+ def simplifiers
27
+ {
28
+ /\?.*/ => '?',
29
+ /\d+/ => '[0-9]',
30
+ /http:..[^\/]+/ => ''
31
+ }
32
+ end
33
+
34
+ end
35
+
36
+ end
data/plog.gemspec ADDED
@@ -0,0 +1,70 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{plog}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kazuyoshi Tlacaelel"]
12
+ s.date = %q{2009-09-07}
13
+ s.default_executable = %q{plog}
14
+ s.description = %q{TODO: longer description of your gem}
15
+ s.email = %q{kazu.dev@gmail.com}
16
+ s.executables = ["plog"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/plog",
29
+ "lib/cli.rb",
30
+ "lib/completed_line.rb",
31
+ "lib/log_file.rb",
32
+ "lib/object_file.rb",
33
+ "lib/plog.rb",
34
+ "lib/url.rb",
35
+ "plog.gemspec",
36
+ "test/completed_line_test.rb",
37
+ "test/data/example.log",
38
+ "test/log_file_test.rb",
39
+ "test/object_file_test.rb",
40
+ "test/plog_test.rb",
41
+ "test/test_helper.rb",
42
+ "test/url_test.rb"
43
+ ]
44
+ s.homepage = %q{http://github.com/ktlacaelel/plog}
45
+ s.rdoc_options = ["--charset=UTF-8"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = %q{1.3.3}
48
+ s.summary = %q{TODO: one-line summary of your gem}
49
+ s.test_files = [
50
+ "test/completed_line_test.rb",
51
+ "test/log_file_test.rb",
52
+ "test/object_file_test.rb",
53
+ "test/plog_test.rb",
54
+ "test/test_helper.rb",
55
+ "test/url_test.rb"
56
+ ]
57
+
58
+ if s.respond_to? :specification_version then
59
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
60
+ s.specification_version = 3
61
+
62
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
63
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
64
+ else
65
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
69
+ end
70
+ end
@@ -0,0 +1,156 @@
1
+ require 'test_helper'
2
+
3
+ class CompletedLineTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @valid_first_fragment = 'Completed in 5ms (View: 4, DB: 1) '
7
+ @valid_line = 'Completed in 5ms (View: 4, DB: 1) | 200 OK [http://www.example.com/users/12972]'
8
+ @valid_line_no_view = 'Completed in 5ms (DB: 5) | 200 OK [http://www.example.com/users/12972]'
9
+ @valid_second_fragment = ' 200 OK [http://www.example.com/users/12972]'
10
+
11
+ @valid_db_time = 1
12
+ @valid_view_time = 4
13
+ @valid_total_time = 5
14
+
15
+ @valid_db_time_no_view = 5
16
+ @valid_view_time_no_view = 0
17
+ @valid_total_time_no_view = 5
18
+
19
+ @valid_csv_line = '5,4,1,/users/[0-9]'
20
+ @valid_status_string = 'OK'
21
+ @valid_status_number = '200'
22
+ end
23
+
24
+ # ============================================================================
25
+ # READ
26
+ # ============================================================================
27
+
28
+ should 'read a valid completed line (standard)' do
29
+ Plog::CompletedLine.read! @valid_line
30
+ assert_equal @valid_view_time, Plog::CompletedLine.view_time
31
+ assert_equal @valid_db_time, Plog::CompletedLine.db_time
32
+ assert_equal @valid_total_time, Plog::CompletedLine.total_time
33
+ end
34
+
35
+ should 'read valid completed line (without view time)' do
36
+ Plog::CompletedLine.read! @valid_line_no_view
37
+ assert_equal 5, Plog::CompletedLine.total_time
38
+ assert_equal 0, Plog::CompletedLine.view_time
39
+ assert_equal 5, Plog::CompletedLine.db_time
40
+ end
41
+
42
+ # ============================================================================
43
+ # RECALCULATION
44
+ # ============================================================================
45
+
46
+ should 'recalculate acurately!' do
47
+ Plog::CompletedLine.read! @valid_line
48
+ Plog::CompletedLine.merge(1, 1)
49
+ assert_equal (@valid_view_time + 1), Plog::CompletedLine.view_time
50
+ assert_equal (@valid_db_time + 1), Plog::CompletedLine.db_time
51
+ assert_equal (@valid_total_time + 2), Plog::CompletedLine.total_time
52
+ end
53
+
54
+ # ============================================================================
55
+ # FRAGMENTATION
56
+ # ============================================================================
57
+
58
+ should 'fragmentize correctly' do
59
+ Plog::CompletedLine.read! @valid_line
60
+ first, second = Plog::CompletedLine.fragmentize!
61
+ assert_equal @valid_first_fragment, first
62
+ assert_equal @valid_second_fragment, second
63
+ end
64
+
65
+ # ============================================================================
66
+ # TIME RETRIVAL ( when view & db are *both* present )
67
+ # ============================================================================
68
+
69
+ should 'retrive correct total time (view + db)' do
70
+ Plog::CompletedLine.read! @valid_line
71
+ assert_equal @valid_total_time, Plog::CompletedLine.total_time
72
+ end
73
+
74
+ should 'retrive correct view time (view + db)' do
75
+ Plog::CompletedLine.read! @valid_line
76
+ assert_equal @valid_view_time, Plog::CompletedLine.view_time
77
+ end
78
+
79
+ should 'retrive correct db time (view + db)' do
80
+ Plog::CompletedLine.read! @valid_line
81
+ assert_equal @valid_db_time, Plog::CompletedLine.db_time
82
+ end
83
+
84
+ # ============================================================================
85
+ # TIME RETRIVAL ( when only db time is present )
86
+ # ============================================================================
87
+
88
+ should 'retrive correct total time (only db)' do
89
+ Plog::CompletedLine.read! @valid_line_no_view
90
+ assert_equal @valid_total_time_no_view, Plog::CompletedLine.total_time
91
+ end
92
+
93
+ should 'retrive correct view time (only db)' do
94
+ Plog::CompletedLine.read! @valid_line_no_view
95
+ assert_equal @valid_view_time_no_view, Plog::CompletedLine.view_time
96
+ end
97
+
98
+ should 'retrive correct db time (only db)' do
99
+ Plog::CompletedLine.read! @valid_line_no_view
100
+ assert_equal @valid_db_time_no_view, Plog::CompletedLine.db_time
101
+ end
102
+
103
+ # ============================================================================
104
+ # CSV COMPILATION
105
+ # ============================================================================
106
+
107
+ should 'export to csv' do
108
+ Plog::CompletedLine.read! @valid_line
109
+ assert_equal @valid_csv_line, Plog::CompletedLine.to_csv
110
+ end
111
+
112
+ # ============================================================================
113
+ # COMPLETED LINE DETECTION
114
+ # ============================================================================
115
+
116
+ should 'ignore *NON* completed lines' do
117
+ Plog::CompletedLine.read! 'completed'
118
+ assert_equal false, Plog::CompletedLine.completed_line?
119
+
120
+ Plog::CompletedLine.read! 'Completed'
121
+ assert_equal false, Plog::CompletedLine.completed_line?
122
+
123
+ Plog::CompletedLine.read! 'Completed Completed Completed Completed'
124
+ assert_equal false, Plog::CompletedLine.completed_line?
125
+
126
+ Plog::CompletedLine.read! 'aalsdjflasdjflsa dflksjdflkasjdf lfCompleted'
127
+ assert_equal false, Plog::CompletedLine.completed_line?
128
+
129
+ Plog::CompletedLine.read! nil
130
+ assert_equal false, Plog::CompletedLine.completed_line?
131
+
132
+ Plog::CompletedLine.read! false
133
+ assert_equal false, Plog::CompletedLine.completed_line?
134
+
135
+ Plog::CompletedLine.read! 0
136
+ assert_equal false, Plog::CompletedLine.completed_line?
137
+
138
+ Plog::CompletedLine.read! ''
139
+ assert_equal false, Plog::CompletedLine.completed_line?
140
+ end
141
+
142
+ # ============================================================================
143
+ # STATUS EXTRACTION
144
+ # ============================================================================
145
+
146
+ should 'extract status string' do
147
+ Plog::CompletedLine.read! @valid_line
148
+ assert_equal @valid_status_string, Plog::CompletedLine.status_string
149
+ end
150
+
151
+ should 'extract status number' do
152
+ Plog::CompletedLine.read! @valid_line
153
+ assert_equal @valid_status_number, Plog::CompletedLine.status_number
154
+ end
155
+
156
+ end
@@ -0,0 +1,10 @@
1
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
2
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
3
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
4
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
5
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
6
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
7
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
8
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
9
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
10
+ Completed in 7ms (View: 4, DB: 3) | 200 OK [http://www.example.com/users/12972]
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class LogFileTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @log_file = 'test/data/example.log'
7
+ @file = Plog::LogFile.new(@log_file)
8
+ @object_hash = 'a1e0e00d04e82bdf0f1ac151de03591c'
9
+ @object_path = 'objects/' + @object_hash
10
+ @final_csv_result = '10,70,40,30,/users/[0-9]'
11
+ @default_object_path = 'objects/2a5565416b0c92c6c5081342322bf945'
12
+ end
13
+
14
+ def teardown
15
+ @file.close
16
+ end
17
+
18
+ should 'generate an appropriate object_path' do
19
+ assert_equal @default_object_path, @file.object_path
20
+ end
21
+
22
+ def whipe_out_objects_dir
23
+ Dir.glob('./objects/*').each do |file|
24
+ FileUtils.rm_r(file, :force => true)
25
+ end
26
+ FileUtils.rmdir './objects'
27
+ end
28
+
29
+ should 'parse data appropriately' do
30
+ whipe_out_objects_dir
31
+ @file = Plog::LogFile.new(@log_file)
32
+ @file.parse_completed_lines!
33
+ assert_equal @final_csv_result, File.new(@object_path).read.chomp
34
+ end
35
+
36
+ end
@@ -0,0 +1,115 @@
1
+ require 'test_helper'
2
+
3
+ class ObjectFileTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @testing_filename = 'kazu.test'
7
+ @file = Plog::ObjectFile.new(@testing_filename, 'w+')
8
+ @default_serialized_data = '0,0,0,0,default'
9
+
10
+ @changed_hits = 1
11
+ @changed_total_time = 2
12
+ @changed_view_time = 3
13
+ @changed_db_time = 4
14
+ @changed_simplified_url = 'http://example.com'
15
+ @changed_serialized_data = '1,2,3,4,http://example.com'
16
+ @changed_serialized_data_twice = '2,4,6,8,http://example.com'
17
+
18
+ @export_data = '1 2 0.002 4 0.004 3 0.003 http://example.com '
19
+ end
20
+
21
+ def teardown
22
+ @file.close unless @skip_close
23
+ end
24
+
25
+ should 'load default values on initialization' do
26
+ assert_equal 'default', @file.simplified_url
27
+ assert_equal 0, @file.view_time
28
+ assert_equal 0, @file.db_time
29
+ assert_equal 0, @file.total_time
30
+ assert_equal 0, @file.total_hits
31
+ end
32
+
33
+ should 'serialize changes correctly' do
34
+ assert_equal @default_serialized_data, @file.serialize_changes
35
+ end
36
+
37
+ # ============================================================================
38
+ # DATA APPENDING
39
+ # ============================================================================
40
+
41
+ should 'increment view time correctly' do
42
+ @file.append_view_time 500
43
+ assert_equal 500, @file.view_time
44
+ @file.append_view_time 500
45
+ assert_equal 1000, @file.view_time
46
+ end
47
+
48
+ should 'increment db time correctly' do
49
+ @file.append_db_time 500
50
+ assert_equal 500, @file.db_time
51
+ @file.append_db_time 500
52
+ assert_equal 1000, @file.db_time
53
+ end
54
+
55
+ should 'increment total time correctly' do
56
+ @file.append_total_time 500
57
+ assert_equal 500, @file.total_time
58
+ @file.append_total_time 500
59
+ assert_equal 1000, @file.total_time
60
+ end
61
+
62
+ should 'increment hits count correctly' do
63
+ @file.append_hits 500
64
+ assert_equal 500, @file.total_hits
65
+ @file.append_hits 500
66
+ assert_equal 1000, @file.total_hits
67
+ end
68
+
69
+ # ============================================================================
70
+ # DATA STORAGE
71
+ # ============================================================================
72
+
73
+ should 'store default data correctly if nothing is given' do
74
+ @file.save_changes!
75
+ @file.close
76
+ @skip_close = true
77
+ stored_data = File.new(@testing_filename).read.chomp
78
+ assert_equal @default_serialized_data, stored_data
79
+ end
80
+
81
+ def alter_data
82
+ @file.append_hits @changed_hits
83
+ @file.append_db_time @changed_db_time
84
+ @file.append_view_time @changed_view_time
85
+ @file.append_total_time @changed_total_time
86
+ @file.simplified_url = @changed_simplified_url
87
+ end
88
+
89
+ # ============================================================================
90
+ # DATA LOADING
91
+ # ============================================================================
92
+
93
+ should 'store altered data & retrive correctly' do
94
+ alter_data
95
+ @file.save_changes!
96
+ @file.close
97
+ @skip_close = true
98
+
99
+ @file = Plog::ObjectFile.new(@testing_filename, 'w+')
100
+ assert_equal @changed_total_time, @file.total_time, 'total'
101
+ assert_equal @changed_view_time, @file.view_time, 'view'
102
+ assert_equal @changed_db_time, @file.db_time, 'db'
103
+ assert_equal @changed_hits, @file.total_hits, 'hits'
104
+ end
105
+
106
+ # ============================================================================
107
+ # DATA EXPORTS
108
+ # ============================================================================
109
+
110
+ should 'export data correctly' do
111
+ alter_data
112
+ assert_equal @export_data, @file.export
113
+ end
114
+
115
+ end
data/test/plog_test.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class PlogTest < Test::Unit::TestCase
4
+
5
+ should 'do notin' do
6
+ end
7
+
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'plog'
8
+
9
+ class Test::Unit::TestCase
10
+ end
data/test/url_test.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class URLTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @valid_line = 'Completed in 5ms (View: 4, DB: 1) | 200 OK [http://www.example.com/users/12972]'
7
+ @valid_url = 'http://www.example.com/users/12972'
8
+ @url = Plog::URL.new(@valid_url)
9
+ end
10
+
11
+ should 'return a valid url object when instantiated' do
12
+ assert_equal @valid_url, @url.to_s
13
+ end
14
+
15
+ should 'simplify correctly' do
16
+ assert_equal '/users/[0-9]', @url.simplify
17
+ end
18
+
19
+ should 'simplify removing arguments' do
20
+ @url = Plog::URL.new('http://www.example.com/users/1234?key1=val1&key2=val2')
21
+ assert_equal '/users/[0-9]?', @url.simplify
22
+ end
23
+
24
+ should 'hashify correctly' do
25
+ assert_equal '2a5565416b0c92c6c5081342322bf945', @url.hashify
26
+ end
27
+
28
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ktlacaelel-plog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kazuyoshi Tlacaelel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-07 00:00:00 -07:00
13
+ default_executable: plog
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: "TODO: longer description of your gem"
26
+ email: kazu.dev@gmail.com
27
+ executables:
28
+ - plog
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - bin/plog
42
+ - lib/cli.rb
43
+ - lib/completed_line.rb
44
+ - lib/log_file.rb
45
+ - lib/object_file.rb
46
+ - lib/plog.rb
47
+ - lib/url.rb
48
+ - plog.gemspec
49
+ - test/completed_line_test.rb
50
+ - test/data/example.log
51
+ - test/log_file_test.rb
52
+ - test/object_file_test.rb
53
+ - test/plog_test.rb
54
+ - test/test_helper.rb
55
+ - test/url_test.rb
56
+ has_rdoc: false
57
+ homepage: http://github.com/ktlacaelel/plog
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --charset=UTF-8
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project:
78
+ rubygems_version: 1.2.0
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: "TODO: one-line summary of your gem"
82
+ test_files:
83
+ - test/completed_line_test.rb
84
+ - test/log_file_test.rb
85
+ - test/object_file_test.rb
86
+ - test/plog_test.rb
87
+ - test/test_helper.rb
88
+ - test/url_test.rb