mm-logged-time 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'bson_ext'
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ I, Brian Hempel, release this software to the public domain. (2011)
data/README.rdoc ADDED
@@ -0,0 +1,54 @@
1
+ = MM Logged Time
2
+
3
+ Logging of query time and load time for MongoMapper, like so:
4
+
5
+ (0.5ms) all query mm-test-1-8-7.parakeets {:name=>"Bro"}
6
+ (0.1ms) all load mm-test-1-8-7.parakeets {:name=>"Bro"}
7
+
8
+ Load time is logged separately because sometimes MongoMapper, not MongoDB, is the bottleneck:
9
+
10
+ (48.6ms) all query mes-geo.places {:ancestor_ids=>2347581, ... }
11
+ (623.7ms) all load mes-geo.places {:ancestor_ids=>2347581, ... }
12
+
13
+ == Installation
14
+
15
+ Add mm-logged-time to your Gemfile:
16
+
17
+ gem 'mm-logged-time'
18
+
19
+ You may wish to only include it in your development group:
20
+
21
+ group :development do
22
+ gem 'mm-logged-time'
23
+ end
24
+
25
+ Once you have MongoMapper set up with a logger, you can turn on logged time. For example, in mongo_config.rb:
26
+
27
+ MongoMapper.connection = Mongo::Connection.new('localhost', 27017, :logger => Rails.logger)
28
+ MongoMapper.logged_time_level = Logger::DEBUG
29
+
30
+ To turn it off either set the logger to a less verbose level, or:
31
+
32
+ MongoMapper.logged_time_level = nil
33
+
34
+ That's it. Happy logging!
35
+
36
+ == Warning
37
+
38
+ The only want to separate out MongoMappers's load and query was to totally clobber some functions in MM's source. Future updates to MongoMapper could cause this gem to break your app.
39
+
40
+ Of course, gem updates to an app are always fickle in my experience. Please don't be deterred from using mm-logged-time. Gem updates == breakage. Just be aware that mm-logged-time could be the culprit if you update MongoMapper.
41
+
42
+ == Development/Tests
43
+
44
+ gem install bundler
45
+ bundle
46
+ bundle exec rake
47
+
48
+ == Pull Requests
49
+
50
+ Pull requests, bug reports, and feedback are welcome!
51
+
52
+ == License
53
+
54
+ Public domain.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/test_*.rb'
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,43 @@
1
+ module MmLoggedTime
2
+ module DecoratorExtensions
3
+ # if someone can figure out a cleaner way to do this, please let me know
4
+ # can't just 'include' because then super also tries to load the doc
5
+ # undef also handly breaks everything
6
+ # overriden code here: https://github.com/jnunemaker/mongomapper/blob/master/lib/mongo_mapper/plugins/querying/decorator.rb
7
+ INSTANCE_METHODS = <<-BIG_EVAL
8
+ def all(opts={})
9
+ result = nil
10
+ log_time("all query") { result = super }
11
+ log_time("all load ") { result.map { |doc| model.load(doc) } }
12
+ end
13
+
14
+ def first(opts={})
15
+ result = nil
16
+ log_time("first query") { result = super }
17
+ log_time("first load ") { model.load(result) }
18
+ end
19
+
20
+ def last(opts={})
21
+ result = nil
22
+ log_time("last query") { result = super }
23
+ log_time("last load ") { model.load(result) }
24
+ end
25
+
26
+ private
27
+ def log_time(msg)
28
+ logger = model.logger
29
+ result = nil
30
+ if logger && MongoMapper.logged_time_level && logger.level <= MongoMapper.logged_time_level
31
+ time = Benchmark.realtime do
32
+ result = yield
33
+ end
34
+ time_ms = (time*10000).round / 10.0
35
+ logger.add MongoMapper.logged_time_level, "(\#{time_ms}ms) \#{msg} \#{collection.db.name}.\#{collection.name} \#{to_hash.inspect}"
36
+ result
37
+ else
38
+ yield
39
+ end
40
+ end
41
+ BIG_EVAL
42
+ end
43
+ end
@@ -0,0 +1,16 @@
1
+ module MmLoggedTime
2
+ module MongoMapperExtensions
3
+ module ClassMethods
4
+ def logged_time_level=(level)
5
+ unless MmLoggedTime::VALID_LEVELS.include?(level)
6
+ raise "Invalid log level. Valid options are: #{MmLoggedTime::VALID_LEVELS.inspect}"
7
+ end
8
+ @logged_time_level = level
9
+ end
10
+
11
+ def logged_time_level
12
+ @logged_time_level
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module MmLoggedTime
2
+ VERSION = "0.5.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'logger'
2
+ require 'mongo_mapper'
3
+
4
+ module MmLoggedTime
5
+ VALID_LEVELS = [
6
+ nil,
7
+ Logger::FATAL,
8
+ Logger::ERROR,
9
+ Logger::WARN,
10
+ Logger::INFO,
11
+ Logger::DEBUG
12
+ ]
13
+ end
14
+
15
+ require 'mm_logged_time/mongo_mapper_extensions.rb'
16
+ require 'mm_logged_time/decorator_extensions.rb'
17
+
18
+ MongoMapper.extend(MmLoggedTime::MongoMapperExtensions::ClassMethods)
19
+ MongoMapper::Plugins::Querying::Decorator.module_eval(MmLoggedTime::DecoratorExtensions::INSTANCE_METHODS)
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "mm_logged_time/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "mm-logged-time"
7
+ s.version = MmLoggedTime::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Brian Hempel"]
10
+ s.email = ["wezzex@parrett.net"]
11
+ s.homepage = "http://github.com/brianhempel/mm-logged-time"
12
+ s.summary = "Logging of query time and load time for MongoMapper"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'mongo_mapper', '>=0.8.6'
20
+ s.add_dependency 'i18n' # active_support complains without this
21
+
22
+ s.add_development_dependency 'bundler'
23
+ s.add_development_dependency 'jnunemaker-matchy', '~> 0.4.0'
24
+ s.add_development_dependency 'shoulda'
25
+ end
@@ -0,0 +1,120 @@
1
+ require 'test_helper'
2
+ require 'stringio'
3
+
4
+ class Parakeet
5
+ include MongoMapper::Document
6
+ key :name
7
+ end
8
+
9
+ PARAKEET_NAMES = %w{
10
+ Bro
11
+ Sis
12
+ Larry
13
+ Silvester
14
+ Monterray
15
+ }
16
+
17
+ def make_some_parakeets
18
+ PARAKEET_NAMES.each do |name|
19
+ Parakeet.create!(:name => name)
20
+ end
21
+ end
22
+
23
+ class TestLoggedTime < Test::Unit::TestCase
24
+ context "" do
25
+ setup do
26
+ @str_io = StringIO.new
27
+ @logger = Logger.new(@str_io)
28
+ MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017, :logger => @logger)
29
+ make_some_parakeets
30
+ end
31
+
32
+ teardown do
33
+ Parakeet.collection.drop
34
+ end
35
+
36
+ context "timed logging turned on" do
37
+ setup do
38
+ MongoMapper.logged_time_level = Logger::DEBUG
39
+ end
40
+
41
+ should "log calls to #all" do
42
+ Parakeet.all
43
+ @str_io.string.should =~ /all query/
44
+ @str_io.string.should =~ /all load/
45
+ end
46
+
47
+ should "not break all" do
48
+ Parakeet.all.size.should == 5
49
+ end
50
+
51
+ should "log time and database and collection and query" do
52
+ Parakeet.where(:name => "Bro").all
53
+ @str_io.string.should =~ /\(\d+.\dms\) all query #{MongoMapper.database.name}\.parakeets \{:name=>"Bro"\}/
54
+ @str_io.string.should =~ /\(\d+.\dms\) all load #{MongoMapper.database.name}\.parakeets \{:name=>"Bro"\}/
55
+ end
56
+
57
+ should "log calls to #first" do
58
+ Parakeet.first
59
+ @str_io.string.should =~ /first query/
60
+ @str_io.string.should =~ /first load/
61
+ end
62
+
63
+ should "not break first" do
64
+ Parakeet.first.class.should == Parakeet
65
+ end
66
+
67
+ should "log calls to #last" do
68
+ Parakeet.last
69
+ @str_io.string.should =~ /last query/
70
+ @str_io.string.should =~ /last load/
71
+ end
72
+
73
+ should "not break last" do
74
+ Parakeet.last.class.should == Parakeet
75
+ end
76
+ end
77
+
78
+ context "different logger levels" do
79
+ should "not log if logger is set to be less verbose" do
80
+ MongoMapper.logged_time_level = Logger::DEBUG
81
+ @logger.level = Logger::ERROR
82
+ Parakeet.where(:name => "Bro").all
83
+ @str_io.string.should_not =~ /all query|all load/
84
+ end
85
+
86
+ should "log if logger is set to the same verbosity" do
87
+ MongoMapper.logged_time_level = Logger::INFO
88
+ @logger.level = Logger::INFO
89
+ Parakeet.where(:name => "Bro").all
90
+ @str_io.string.should =~ /all query.+all load/m
91
+ end
92
+
93
+ should "log if logger is set to a higher verbosity" do
94
+ MongoMapper.logged_time_level = Logger::WARN
95
+ @logger.level = Logger::INFO
96
+ Parakeet.where(:name => "Bro").all
97
+ @str_io.string.should =~ /all query.+all load/m
98
+ end
99
+ end
100
+
101
+ context "timed logging not turned on" do
102
+ # # not sure how to test this...
103
+ # should "default to off" do
104
+ # Parakeet.all
105
+ # @str_io.string.should_not =~ /all query|all load/
106
+ # end
107
+
108
+ should "allow explicit turning off" do
109
+ MongoMapper.logged_time_level = Logger::DEBUG
110
+ Parakeet.where(:name => "Bro").all
111
+ @str_io.string.should =~ /all query.+all load/m
112
+
113
+ @str_io.string = ""
114
+ MongoMapper.logged_time_level = nil
115
+ Parakeet.where(:name => "Bro").all
116
+ @str_io.string.should_not =~ /all query|all load/
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
5
+ require 'matchy'
6
+ require 'shoulda'
7
+ require 'mongo_mapper'
8
+ require 'mm_logged_time'
9
+
10
+ MongoMapper.database = "mm-test-#{RUBY_VERSION.gsub('.', '-')}"
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mm-logged-time
3
+ version: !ruby/object:Gem::Version
4
+ hash: 11
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
+ platform: ruby
12
+ authors:
13
+ - Brian Hempel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-21 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mongo_mapper
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 51
30
+ segments:
31
+ - 0
32
+ - 8
33
+ - 6
34
+ version: 0.8.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: i18n
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: bundler
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: jnunemaker-matchy
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ~>
72
+ - !ruby/object:Gem::Version
73
+ hash: 15
74
+ segments:
75
+ - 0
76
+ - 4
77
+ - 0
78
+ version: 0.4.0
79
+ type: :development
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ name: shoulda
83
+ prerelease: false
84
+ requirement: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ type: :development
94
+ version_requirements: *id005
95
+ description:
96
+ email:
97
+ - wezzex@parrett.net
98
+ executables: []
99
+
100
+ extensions: []
101
+
102
+ extra_rdoc_files: []
103
+
104
+ files:
105
+ - .gitignore
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.rdoc
109
+ - Rakefile
110
+ - lib/mm_logged_time.rb
111
+ - lib/mm_logged_time/decorator_extensions.rb
112
+ - lib/mm_logged_time/mongo_mapper_extensions.rb
113
+ - lib/mm_logged_time/version.rb
114
+ - mm-logged-time.gemspec
115
+ - test/functional/test_logged_time.rb
116
+ - test/test_helper.rb
117
+ has_rdoc: true
118
+ homepage: http://github.com/brianhempel/mm-logged-time
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ requirements: []
145
+
146
+ rubyforge_project:
147
+ rubygems_version: 1.3.7
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: Logging of query time and load time for MongoMapper
151
+ test_files:
152
+ - test/functional/test_logged_time.rb
153
+ - test/test_helper.rb