plog 0.5.0 → 0.6.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.
@@ -1,148 +1,9 @@
1
1
  = Plog
2
2
 
3
- Ruby on Rails production log statistics generator.
3
+ Production log parser.
4
4
 
5
- by Kazuyoshi Tlacaelel.
6
5
 
7
- $ plog my_directory_with_production_logs/
8
- $ ls plog/
9
- objects statistics.txt
10
-
11
-
12
- == Copyright
13
-
14
- Copyright (c) 2009 Kazuyoshi Tlacaelel. See LICENSE for details.
15
-
16
- == Comming soon!
17
-
18
- comming soon to a terminal near you!
19
-
20
- * sorting:
21
- * more statistics
22
- (hits, number of hits per response type like 200, 302 etc)
23
-
24
- May be... but don't expect any of these to become a reality
25
- I love programming and tons of ideas flow in my head with posibilities
26
- but I do not have the time! :(
27
-
28
- * Different export drivers?
29
- (should be another plugin)
30
-
31
- * cli options abstracted into classes so they can be aggregated with ease
32
- (this might be cool)
33
-
34
- * google charts integration
35
- (is too much for this api)
36
- (may be as a different plugin)
37
-
38
- == Dependancies:
39
-
40
- * FileUtils
41
- * MD5
42
- * File
43
- * Dir
44
- * URI
45
- * rubygems 1.3.3
46
-
47
- == Features:
48
-
49
- Compiles statistics in a easy to read manner
50
-
51
-
52
- Hits Time Avg-Time DbTime Avg-DB View Avg-View Url
53
- 93 18057 0.194 5775 0.062 10437 0.112 /users/[0-9]
54
- 12 277 0.023 193 0.016 0 0 /user_themes/update
55
- 1 290 0.29 107 0.107 175 0.175 /posts
56
- 3 99 0.033 57 0.019 0 0 /comments
57
- 82 11922 0.145 5969 0.072 4979 0.06 /user/[0-9]/comments
58
- 1868 1301006 0.696 623246 0.333 491474 0.263 /user/[0-9]/posts?
59
- 1 72 0.072 39 0.039 0 0 /confirm_destroy_account/[0-9]?
60
- 797 971882 1.219 414829 0.52 423130 0.53 /user/[0-9]/articles/friends?
61
- 122 20830 0.17 7081 0.058 10291 0.084 /user/[0-9]/topics?
62
-
63
- == Improvized twicks:
64
-
65
- You can improvize some quick sorting using the command line like:
66
-
67
- cat plog/statistics.txt | head -n1 > some_file.txt
68
- cat plog/statistics.txt | sort -nr >> some_file.txt
69
-
70
- This will create a new file with sorted results by hits for you!
71
-
72
- Hits Time Avg-Time DbTime Avg-DB View Avg-View Url
73
- 1868 1301006 0.696 623246 0.333 491474 0.263 /user/[0-9]/posts?
74
- 797 971882 1.219 414829 0.52 423130 0.53 /user/[0-9]/articles/friends?
75
- 122 20830 0.17 7081 0.058 10291 0.084 /user/[0-9]/topics?
76
- 93 18057 0.194 5775 0.062 10437 0.112 /users/[0-9]
77
- 82 11922 0.145 5969 0.072 4979 0.06 /user/[0-9]/comments
78
- 12 277 0.023 193 0.016 0 0 /user_themes/update
79
- 3 99 0.033 57 0.019 0 0 /comments
80
- 1 72 0.072 39 0.039 0 0 /confirm_destroy_account/[0-9]?
81
- 1 290 0.29 107 0.107 175 0.175 /posts
82
-
83
- == Installation
84
-
85
- $ gem sources -a http://gems.github.com
86
- $ gem install ktlacaelel-plog
87
-
88
- == Known bugs:
89
- none, so far..
90
-
91
- == License:
92
- MIT. See the "LICENSE" file for details.
93
-
94
- == Participate
95
-
96
- * Send me a brief message
97
- * Fork the project.
98
- * Add tests for it. This is important so I don't break it in a
99
- future version unintentionally.
100
- * Make your feature addition or bug fix.
101
- * Commit, do not mess with rakefile, version, or history.
102
- (if you want to have your own version, that is fine but
103
- bump version in a commit by itself I can ignore when I pull)
104
- * Send me a pull request. Bonus points for topic branches.
105
-
106
- == Output:
107
-
108
- All output is packed in a plog directory, from wherever you run
109
- the "plog" executable.
110
-
111
- Inside this directory you'll find a directory called objects.
112
- wich contains many small files called "object-files"
113
- this files contain all the parsed statistics of you log files.
114
-
115
- The information is scattered and can be reused for future compilations
116
- meaning that new compilations data will merge with the existing one.
117
-
118
- all data in these "object-files" is read and summarized into a
119
- statistics.txt file found inside of the plog directory.
120
-
121
- == Tests:
122
-
123
- * 70% tested, with shoulda
124
- * all core areas of the api are tested, and tests pass!
125
- * only the cli part of the api has no tests, but will be implemented soon
126
-
127
- == Usage:
128
-
129
- The "plog" ( production log ) executable receives one option.
130
- This must be a directory containing one or more production logs.
131
- Only logs in the first level will be parsed.
132
- Recursive reading is not allowed
133
-
134
- $ plog directory_with_logs/
135
-
136
- == Works on:
137
-
138
- * OSX Darwin utopia.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
139
- * UBUNTU Linux utopia.local 2.6.28-11-server #42-Ubuntu SMP Fri Apr 17 02:45:36 UTC 2009 x86_64 GNU/Linux
140
-
141
- * OSX ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
142
- * UBUNTU ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]
143
-
144
- * rubygems 1.3.4
145
- * rubygems 1.3.3
6
+ update coming soon!
146
7
 
147
8
  == The end.
148
9
 
data/Rakefile CHANGED
@@ -54,3 +54,9 @@ Rake::RDocTask.new do |rdoc|
54
54
  rdoc.rdoc_files.include('README*')
55
55
  rdoc.rdoc_files.include('lib/**/*.rb')
56
56
  end
57
+
58
+ desc 'Generate code statistics'
59
+ task :stats do
60
+ require 'code_statistics'
61
+ CodeStatistics.new(['Plog', 'lib'], ['Tests', 'test']).to_s
62
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -1,13 +1,8 @@
1
-
2
- # required external libraries
3
- require 'fileutils'
4
- require 'md5'
5
- require 'uri'
6
-
7
- # required internal libraries
8
- require 'cli'
9
- require 'completed_line'
10
- require 'log_file'
11
- require 'object_file'
12
- require 'url'
1
+ require 'yaml'
2
+ require 'rubygems'
3
+ require 'active_record'
4
+ require 'active_support'
5
+ require 'plog/record_abstraction'
6
+ require 'plog/scanner'
7
+ require 'plog/parser'
13
8
 
@@ -0,0 +1,31 @@
1
+ module Plog
2
+
3
+ class Parser
4
+
5
+ class << Parser
6
+
7
+ attr_reader :data
8
+
9
+ def reset
10
+ end
11
+
12
+ def crunch data
13
+ load_data data
14
+ end
15
+
16
+ def load_data(value)
17
+ reset
18
+ @data = value
19
+ self
20
+ end
21
+
22
+ def is_candidate?
23
+ raise 'You must implement a is_candidate? method in your tokenizer class'
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
@@ -0,0 +1,62 @@
1
+ module Plog
2
+
3
+ class RecordAbstraction
4
+
5
+ class << RecordAbstraction
6
+
7
+ def setup(table)
8
+ @table = table
9
+ end
10
+
11
+ def migration_name
12
+ "#{record_name}Migration"
13
+ end
14
+
15
+ def record_name
16
+ "#{@table[:table_name].to_s.camelize}"
17
+ end
18
+
19
+ def record_class
20
+ "
21
+ class ::#{record_name} < ActiveRecord::Base
22
+ set_table_name :#{record_name.underscore}
23
+ end
24
+ "
25
+ end
26
+
27
+ def migration_class
28
+ "
29
+ class ::#{migration_name} < ActiveRecord::Migration
30
+ def self.up
31
+ create_table :#{@table[:table_name]} do |t|
32
+ #{@table[:fields].map { |field, type| 't.' + type.to_s + ' :' + field.to_s } * "\n " }
33
+ t.timestamps
34
+ end
35
+ end
36
+ end
37
+ "
38
+ end
39
+
40
+ def record_constant
41
+ eval(record_class)
42
+ eval('::' + record_name)
43
+ end
44
+
45
+ def migration_constant
46
+ eval(migration_class)
47
+ eval('::' + migration_name)
48
+ end
49
+
50
+ def record_exists?
51
+ ActiveRecord::Base.connection.execute('show tables').each do |record|
52
+ return true if record.first == @table[:table_name].to_s
53
+ end
54
+ false
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
@@ -0,0 +1,33 @@
1
+ module Plog
2
+
3
+ class Scanner
4
+
5
+ class << Scanner
6
+
7
+ def load(io, config, &block)
8
+ @config = config
9
+ @config.each do |table|
10
+ RecordAbstraction.setup(table)
11
+ unless RecordAbstraction.record_exists?
12
+ RecordAbstraction.migration_constant.up
13
+ end
14
+ end
15
+ io.each_line { |line| yield(line, self) }
16
+ end
17
+
18
+ def record table_name
19
+ constant(table_name).new
20
+ end
21
+
22
+ # TODO: optimize
23
+ def constant table_name
24
+ config = @config.find { |hash| hash[:table_name] == table_name }
25
+ RecordAbstraction.setup(config)
26
+ RecordAbstraction.record_constant
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -1,65 +1,53 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{plog}
8
- s.version = "0.2.4"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kazuyoshi Tlacaelel"]
12
- s.date = %q{2009-09-09}
12
+ s.date = %q{2012-05-09}
13
13
  s.default_executable = %q{plog}
14
14
  s.description = %q{Plog - Ruby on Rails production log statistic generator. by Kazuyoshi Tlacaelel}
15
15
  s.email = %q{kazu.dev@gmail.com}
16
16
  s.executables = ["plog"]
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE",
19
- "README.rdoc"
19
+ "README.rdoc"
20
20
  ]
21
21
  s.files = [
22
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"
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/plog",
28
+ "lib/plog.rb",
29
+ "lib/plog/parser.rb",
30
+ "lib/plog/record_abstraction.rb",
31
+ "lib/plog/scanner.rb",
32
+ "plog.gemspec",
33
+ "test/completed_line_test.rb",
34
+ "test/data/example.log",
35
+ "test/log_file_test.rb",
36
+ "test/object_file_test.rb",
37
+ "test/plog_test.rb",
38
+ "test/test_helper.rb",
39
+ "test/url_test.rb"
43
40
  ]
44
41
  s.homepage = %q{http://github.com/ktlacaelel/plog}
45
- s.rdoc_options = ["--charset=UTF-8"]
46
42
  s.require_paths = ["lib"]
47
- s.rubygems_version = %q{1.3.3}
43
+ s.rubygems_version = %q{1.3.7}
48
44
  s.summary = %q{Plog - Ruby on Rails production log statistic generator. by Kazuyoshi Tlacaelel}
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
45
 
58
46
  if s.respond_to? :specification_version then
59
47
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
60
48
  s.specification_version = 3
61
49
 
62
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
63
51
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
64
52
  else
65
53
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
@@ -68,3 +56,4 @@ Gem::Specification.new do |s|
68
56
  s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
69
57
  end
70
58
  end
59
+
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ hash: 7
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Kazuyoshi Tlacaelel
@@ -9,19 +15,23 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-11-09 00:00:00 +09:00
18
+ date: 2012-05-09 00:00:00 -05:00
13
19
  default_executable: plog
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: thoughtbot-shoulda
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
- version:
33
+ type: :development
34
+ version_requirements: *id001
25
35
  description: Plog - Ruby on Rails production log statistic generator. by Kazuyoshi Tlacaelel
26
36
  email: kazu.dev@gmail.com
27
37
  executables:
@@ -33,18 +43,15 @@ extra_rdoc_files:
33
43
  - README.rdoc
34
44
  files:
35
45
  - .document
36
- - .gitignore
37
46
  - LICENSE
38
47
  - README.rdoc
39
48
  - Rakefile
40
49
  - VERSION
41
50
  - bin/plog
42
- - lib/cli.rb
43
- - lib/completed_line.rb
44
- - lib/log_file.rb
45
- - lib/object_file.rb
46
51
  - lib/plog.rb
47
- - lib/url.rb
52
+ - lib/plog/parser.rb
53
+ - lib/plog/record_abstraction.rb
54
+ - lib/plog/scanner.rb
48
55
  - plog.gemspec
49
56
  - test/completed_line_test.rb
50
57
  - test/data/example.log
@@ -58,33 +65,34 @@ homepage: http://github.com/ktlacaelel/plog
58
65
  licenses: []
59
66
 
60
67
  post_install_message:
61
- rdoc_options:
62
- - --charset=UTF-8
68
+ rdoc_options: []
69
+
63
70
  require_paths:
64
71
  - lib
65
72
  required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
66
74
  requirements:
67
75
  - - ">="
68
76
  - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
69
80
  version: "0"
70
- version:
71
81
  required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
72
83
  requirements:
73
84
  - - ">="
74
85
  - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
75
89
  version: "0"
76
- version:
77
90
  requirements: []
78
91
 
79
92
  rubyforge_project:
80
- rubygems_version: 1.3.5
93
+ rubygems_version: 1.3.7
81
94
  signing_key:
82
95
  specification_version: 3
83
96
  summary: Plog - Ruby on Rails production log statistic generator. by Kazuyoshi Tlacaelel
84
- test_files:
85
- - test/completed_line_test.rb
86
- - test/log_file_test.rb
87
- - test/object_file_test.rb
88
- - test/plog_test.rb
89
- - test/test_helper.rb
90
- - test/url_test.rb
97
+ test_files: []
98
+
data/.gitignore DELETED
@@ -1,7 +0,0 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
4
- rdoc
5
- pkg
6
- kazu.test
7
- objects
data/lib/cli.rb DELETED
@@ -1,119 +0,0 @@
1
- module Plog
2
-
3
- class Cli
4
-
5
- attr_reader :source_directory, :log_files
6
-
7
- STATS_FILE = 'statistics.txt'
8
-
9
- # ==========================================================================
10
- # CLIENT INTERFACE
11
- # ==========================================================================
12
-
13
- def initialize(source_directory, target_directory)
14
- @log_files = []
15
- @source_directory = source_directory
16
- @target_directory = target_directory
17
- check_directory_consistency!
18
- preload_log_files!
19
- end
20
-
21
- def run!
22
- stdout count_of_logs_banner(@log_files.size)
23
- stdout notice_banner
24
- create_object_files
25
- destroy_old_log_file
26
- append_headers_to_log_file
27
- parse_object_files
28
- end
29
-
30
- # ==========================================================================
31
- # INTERNAL INTERFACE
32
- # ==========================================================================
33
-
34
- protected
35
-
36
- def trim(string)
37
- return '' unless string.is_a? String
38
- string.gsub(/^\s+/, '').gsub(/\s+$/, '')
39
- end
40
-
41
- def create_object_files
42
- @log_files.each do |log_file|
43
- stdout parsing_log_file_banner(log_file.name)
44
- log_file.parse_completed_lines!
45
- end
46
- end
47
-
48
- def parse_object_files
49
- Dir.glob(object_file_pattern).each do |object_file|
50
- file = File.new(statistic_file_path, 'a+')
51
- file.puts trim(ObjectFile.new(object_file).export)
52
- file.close
53
- end
54
- end
55
-
56
- def object_file_pattern
57
- File.join(@target_directory, 'objects') + '/*'
58
- end
59
-
60
- def statistic_file_path
61
- File.join(@target_directory, STATS_FILE)
62
- end
63
-
64
- def destroy_old_log_file
65
- FileUtils.touch statistic_file_path
66
- FileUtils.rm statistic_file_path
67
- end
68
-
69
- def append_headers_to_log_file
70
- file = File.new(statistic_file_path, 'a+')
71
- file.puts trim(ObjectFile.formated_headers)
72
- file.close
73
- end
74
-
75
- def check_directory_consistency!
76
- abort directory_not_found_banner unless File.exist? @source_directory
77
- end
78
-
79
- def preload_log_files!
80
- Dir.glob(File.join(@source_directory, '*.log')).each do |log_file|
81
- @log_files << LogFile.new(log_file, @target_directory)
82
- stdout loading_log_file_banner(log_file)
83
- end
84
- end
85
-
86
- def stdout(string)
87
- puts ' ---> ' + string
88
- end
89
-
90
- # ==========================================================================
91
- # BANNERS
92
- # ==========================================================================
93
-
94
- def notice_banner
95
- 'Parsing logs...
96
- This may take a long-while, go get yourself a coffee!
97
- While I hanlde this stuff for you.
98
- '
99
- end
100
-
101
- def count_of_logs_banner(size)
102
- 'Count of loaded logs : %s ' % size
103
- end
104
-
105
- def parsing_log_file_banner(file)
106
- 'Parsing log located at : %s ' % file
107
- end
108
-
109
- def loading_log_file_banner(file)
110
- 'Initializing log file: %s' % file
111
- end
112
-
113
- def directory_not_found_banner
114
- 'No such dir: %s' % @source_directory
115
- end
116
-
117
- end
118
-
119
- end
@@ -1,109 +0,0 @@
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
- @second_fragment.gsub(STATUS_REGEX, '\2,\4').split(',')
101
- end
102
-
103
- def self.extract_url!
104
- @url = @second_fragment.gsub(URL_REGEX, '\3')
105
- end
106
-
107
- end
108
-
109
- end
@@ -1,52 +0,0 @@
1
- module Plog
2
-
3
- class LogFile < File
4
-
5
- attr_accessor :name
6
-
7
- def initialize(file, dump_dir)
8
- @dump_dir = dump_dir
9
- check_dump_dir_consistency!
10
- super(file, 'r')
11
- @name = file
12
- end
13
-
14
- def check_dump_dir_consistency!
15
- unless File.exist? objects_recipient_path
16
- FileUtils.mkdir_p objects_recipient_path
17
- end
18
- end
19
-
20
- def validate(file)
21
- abort 'File not found: ' + file.inspect unless File.exist? file
22
- end
23
-
24
- def parse_completed_lines!
25
- each_line do |line|
26
- CompletedLine.read! line
27
- parse_completed_line if CompletedLine.valid?
28
- end
29
- end
30
-
31
- def parse_completed_line
32
- of = ObjectFile.new(object_path, 'w+')
33
- of.simplified_url = CompletedLine.url.simplify
34
- of.append_total_time CompletedLine.total_time
35
- of.append_db_time CompletedLine.db_time
36
- of.append_view_time CompletedLine.view_time
37
- of.append_hits 1
38
- of.save_changes!
39
- of.close
40
- end
41
-
42
- def object_path
43
- File.join(objects_recipient_path, CompletedLine.url.hashify)
44
- end
45
-
46
- def objects_recipient_path
47
- @objects_recipient_path ||= File.join(@dump_dir, 'objects')
48
- end
49
-
50
- end
51
-
52
- end
@@ -1,165 +0,0 @@
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, 15]],
89
- [total_time_in_secs, [:left, 15]],
90
- [avg_total_time, [:left, 15]],
91
- [db_time_in_secs, [:left, 15]],
92
- [avg_db_time, [:left, 15]],
93
- [view_time_in_secs, [:left, 15]],
94
- [avg_view_time, [:left, 15]],
95
- [simplified_url, [:left, 40]],
96
- ]
97
- end
98
-
99
- def self.export_header_settings
100
- [
101
- ['Hits', [:left, 15]],
102
- ['Time', [:left, 15]],
103
- ['Avg-Time', [:left, 15]],
104
- ['DbTime', [:left, 15]],
105
- ['Avg-DB', [:left, 15]],
106
- ['View', [:left, 15]],
107
- ['Avg-View', [:left, 15]],
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
- def total_time_in_secs
152
- @total_time / 1000.0
153
- end
154
-
155
- def db_time_in_secs
156
- @db_time / 1000.0
157
- end
158
-
159
- def view_time_in_secs
160
- @view_time / 1000.0
161
- end
162
-
163
- end
164
-
165
- end
data/lib/url.rb DELETED
@@ -1,37 +0,0 @@
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
- }
33
- end
34
-
35
- end
36
-
37
- end