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 +4 -0
- data/Gemfile +4 -0
- data/LICENSE +1 -0
- data/README.rdoc +54 -0
- data/Rakefile +11 -0
- data/lib/mm_logged_time/decorator_extensions.rb +43 -0
- data/lib/mm_logged_time/mongo_mapper_extensions.rb +16 -0
- data/lib/mm_logged_time/version.rb +3 -0
- data/lib/mm_logged_time.rb +19 -0
- data/mm-logged-time.gemspec +25 -0
- data/test/functional/test_logged_time.rb +120 -0
- data/test/test_helper.rb +10 -0
- metadata +153 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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,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,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
|
data/test/test_helper.rb
ADDED
@@ -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
|