model_observer 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ec8feeb3833a59b988c7d230d4495e688bb23daa
4
+ data.tar.gz: 7a5ea18696fc7397111ab8047a00a0c6931d80a3
5
+ SHA512:
6
+ metadata.gz: c52ca71ef43463cedee183431c8c1e9cfb577c25869934cf4c66bca74628be653ba05bdb9e8a98e85ecec7a89f538fc0329b2a48f377979f9f20321f06f36555
7
+ data.tar.gz: e33777e428926ea72981bac2dfe9f97b81fe27a66f8953af896422c60fa19c9ceb17c63bc213f45ba63d9d0c87a87b76fc26b86ad1c22ad49fbde74c9e8491f0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Weihu Chen
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.md ADDED
@@ -0,0 +1,33 @@
1
+ # ModelObserver
2
+
3
+ A rails plugin to count the model object creations between each request, and help to find out the duplication.
4
+
5
+ [![Build Status](https://travis-ci.org/cctiger36/model_observer.png?branch=master)](https://travis-ci.org/cctiger36/model_observer) [![Code Climate](https://codeclimate.com/github/cctiger36/model_observer.png)](https://codeclimate.com/github/cctiger36/model_observer)
6
+
7
+ ## Installation
8
+
9
+ Add to your Gemfile
10
+
11
+ group :development do
12
+ gem 'model_observer'
13
+ end
14
+
15
+ and bundle
16
+
17
+ bundle
18
+
19
+ ## Log
20
+
21
+ The ModelObserver log will look like:
22
+
23
+ ===== Model Observer Start =====
24
+ Author: 1 sum(10ms) avg(10ms)
25
+ Book: 36 sum(13ms) avg(0ms)
26
+ id(20): 2
27
+ id(50): 9
28
+ id(61): 4
29
+ id(68): 2
30
+ id(111): 2
31
+ id(123): 3
32
+ id(124): 3
33
+ ===== Model Observer End =====
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ desc 'Default: run specs'
5
+ task :default => :spec
6
+
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.pattern = "spec/**/*_spec.rb"
10
+ end
11
+
12
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,17 @@
1
+ module ModelObserver
2
+ module ActiveRecord
3
+ def self.enable
4
+ require 'active_record'
5
+ ::ActiveRecord::Inheritance::ClassMethods.class_eval do
6
+ alias_method :origin_instantiate, :instantiate
7
+
8
+ def instantiate(record)
9
+ started_at = Time.now
10
+ instance = origin_instantiate(record)
11
+ ModelObserver::Collector.add_metric(ModelObserver::Metric.new(instance, started_at, Time.now))
12
+ instance
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module ModelObserver
2
+ class Analyser
3
+ class << self
4
+ def result
5
+ text = ""
6
+ Collector.metrics_hash.each do |key, value|
7
+ sum_duration = value.map(&:duration).sum
8
+ average_duration = sum_duration / value.count
9
+ text << "#{key}: #{value.count} sum(#{sum_duration}ms) avg(#{average_duration}ms)\n"
10
+ text << analyse_single_class(value)
11
+ end
12
+ text.sub!(/\n$/, '')
13
+ text
14
+ end
15
+
16
+ def analyse_single_class(metrics)
17
+ return if metrics.empty?
18
+ primary_key = metrics.first.model_class.primary_key
19
+ hash = {}
20
+ metrics.each do |m|
21
+ hash[m.model_id] ||= 0
22
+ hash[m.model_id] += 1
23
+ end
24
+ hash
25
+ text = ""
26
+ hash.sort_by{|key, value| key}.each do |key, value|
27
+ text << " #{primary_key}(#{key}): #{value}\n" if value > 1
28
+ end
29
+ text
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,26 @@
1
+ module ModelObserver
2
+ class Collector
3
+ class << self
4
+ def metrics
5
+ @@metrics ||= []
6
+ end
7
+
8
+ def add_metric(metric)
9
+ metrics << metric
10
+ end
11
+
12
+ def clear
13
+ @@metrics = nil
14
+ end
15
+
16
+ def metrics_hash
17
+ hash = {}
18
+ metrics.each do |m|
19
+ hash[m.model_class.name] ||= []
20
+ hash[m.model_class.name] << m
21
+ end
22
+ hash
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ module ModelObserver
2
+ module Dependency
3
+ def active_record?
4
+ @active_record ||= begin
5
+ require 'active_record'
6
+ true
7
+ rescue LoadError
8
+ false
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ module ModelObserver
2
+ class Metric
3
+ attr_accessor :model_class, :model_id, :started_at, :ended_at
4
+
5
+ def initialize(model, started_at, ended_at)
6
+ @model_class = model.class
7
+ @model_id = model.__send__(model.class.primary_key)
8
+ @started_at = started_at
9
+ @ended_at = ended_at
10
+ end
11
+
12
+ def duration
13
+ ((ended_at.to_f - started_at.to_f) * 1000).to_i
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module ModelObserver
2
+ class Rack
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ ModelObserver.start_request
9
+ response = @app.call(env)
10
+ ModelObserver.write_to_rails_log
11
+ ModelObserver.end_request
12
+ response
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module ModelObserver
2
+ class Railtie < Rails::Railtie
3
+ initializer "model_observer.configure_rails_initialization" do |app|
4
+ app.middleware.use ModelObserver::Rack
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module ModelObserver
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ require 'model_observer/dependency'
2
+ require 'model_observer/railtie'
3
+
4
+ module ModelObserver
5
+ extend Dependency
6
+
7
+ autoload :Metric, 'model_observer/metric'
8
+ autoload :Collector, 'model_observer/collector'
9
+ autoload :Analyser, 'model_observer/analyser'
10
+ autoload :Rack, 'model_observer/rack'
11
+
12
+ if active_record?
13
+ autoload :ActiveRecord, 'model_observer/active_record'
14
+ ModelObserver::ActiveRecord.enable
15
+ end
16
+
17
+ class << self
18
+ def start_request
19
+ end
20
+
21
+ def end_request
22
+ Collector.clear
23
+ end
24
+
25
+ def write_to_rails_log
26
+ Rails.logger.warn "===== Model Observer Start ====="
27
+ Rails.logger.warn Analyser.result
28
+ Rails.logger.warn "===== Model Observer End ====="
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :model_observer do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: model_observer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Weihu Chen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A rails plugin to count the model object creations between each request,
56
+ and help to find out the duplication.
57
+ email:
58
+ - cctiger36@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - lib/model_observer/active_record.rb
64
+ - lib/model_observer/analyser.rb
65
+ - lib/model_observer/collector.rb
66
+ - lib/model_observer/dependency.rb
67
+ - lib/model_observer/metric.rb
68
+ - lib/model_observer/rack.rb
69
+ - lib/model_observer/railtie.rb
70
+ - lib/model_observer/version.rb
71
+ - lib/model_observer.rb
72
+ - lib/tasks/model_observer_tasks.rake
73
+ - MIT-LICENSE
74
+ - Rakefile
75
+ - README.md
76
+ homepage: https://github.com/cctiger36/model_observer
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.0.6
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Help to find out duplicated model object creations.
100
+ test_files: []