plog 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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