mongo_profiler 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +22 -0
- data/README.md +112 -0
- data/Rakefile +1 -0
- data/assets/mongo_profiler_dashboard_index.png +0 -0
- data/assets/mongo_profiler_group_details.png +0 -0
- data/assets/mongo_profiler_query_details.png +0 -0
- data/assets/mongo_profiler_query_details_backtrace.png +0 -0
- data/config.ru +13 -0
- data/lib/mongo_profiler.rb +108 -0
- data/lib/mongo_profiler/caller.rb +27 -0
- data/lib/mongo_profiler/extensions/mongo/cursor.rb +38 -0
- data/lib/mongo_profiler/payload.rb +33 -0
- data/lib/mongo_profiler/profiler.rb +4 -0
- data/lib/mongo_profiler/stats.rb +25 -0
- data/lib/mongo_profiler/version.rb +3 -0
- data/lib/mongo_profiler/web.rb +85 -0
- data/lib/mongo_profiler/web_helpers.rb +65 -0
- data/mongo_profiler.gemspec +31 -0
- data/spec/mongo_profiler/caller_spec.rb +83 -0
- data/spec/mongo_profiler/extensions/mongo/cursor_spec.rb +42 -0
- data/spec/mongo_profiler/payload_spec.rb +111 -0
- data/spec/mongo_profiler/profiler_spec.rb +8 -0
- data/spec/mongo_profiler/stats_spec.rb +29 -0
- data/spec/mongo_profiler/web_helpers_spec.rb +52 -0
- data/spec/mongo_profiler/web_spec.rb +43 -0
- data/spec/mongo_profiler_spec.rb +113 -0
- data/spec/spec_helper.rb +28 -0
- data/web/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/web/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/web/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/web/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/web/assets/javascripts/bootstrap.js +1951 -0
- data/web/assets/javascripts/bootstrap.min.js +6 -0
- data/web/assets/javascripts/highlight.pack.js +1 -0
- data/web/assets/javascripts/jquery.js +10337 -0
- data/web/assets/stylesheets/application.css +10 -0
- data/web/assets/stylesheets/bootstrap.css +5831 -0
- data/web/assets/stylesheets/bootstrap.min.css +7 -0
- data/web/assets/stylesheets/highlight/default.css +153 -0
- data/web/assets/stylesheets/highlight/github.css +125 -0
- data/web/views/group_id.erb +53 -0
- data/web/views/index.erb +32 -0
- data/web/views/layout.erb +94 -0
- data/web/views/show.erb +83 -0
- metadata +227 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module MongoProfiler
|
2
|
+
class Stats
|
3
|
+
def initialize(stats_client)
|
4
|
+
@stats_client = stats_client
|
5
|
+
end
|
6
|
+
|
7
|
+
def populate(_caller, total_time)
|
8
|
+
file = sanitaze_stat_key _caller.file.split('/').last
|
9
|
+
method = sanitaze_stat_key _caller.method
|
10
|
+
|
11
|
+
stat_name = "mongo_profiler.#{MongoProfiler.application_name}.#{file}.#{method}"
|
12
|
+
|
13
|
+
total_time_ms = total_time * 1000
|
14
|
+
|
15
|
+
@stats_client.increment stat_name
|
16
|
+
@stats_client.timing stat_name, total_time_ms
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def sanitaze_stat_key(key)
|
22
|
+
key.gsub(/\W/, '_')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# https://github.com/mperham/sidekiq/wiki/Monitoring
|
2
|
+
require 'erb'
|
3
|
+
require 'yaml'
|
4
|
+
require 'sinatra/base'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require 'mongo_profiler/web_helpers'
|
8
|
+
|
9
|
+
module MongoProfiler
|
10
|
+
class Web < Sinatra::Base
|
11
|
+
|
12
|
+
set :root, File.expand_path(File.dirname(__FILE__) + "/../../web")
|
13
|
+
set :public_folder, Proc.new { "#{root}/assets" }
|
14
|
+
set :views, Proc.new { "#{root}/views" }
|
15
|
+
|
16
|
+
helpers WebHelpers
|
17
|
+
|
18
|
+
|
19
|
+
get '/' do
|
20
|
+
@profiles = MongoProfiler.collection.
|
21
|
+
group({ key: %i[method file application_name group_id],
|
22
|
+
reduce: 'function(curr, result) { result.total_time += curr.total_time; result.total += 1 }',
|
23
|
+
initial: { total: 0, total_time: 0 } })
|
24
|
+
|
25
|
+
# group profilers by group_id and sort by created_at DESC
|
26
|
+
@grouped_profiles = @profiles.group_by { |profile| profile['group_id'] }.to_a.reverse
|
27
|
+
|
28
|
+
erb :index
|
29
|
+
end
|
30
|
+
|
31
|
+
post '/profiler/enable' do
|
32
|
+
MongoProfiler.enable!
|
33
|
+
|
34
|
+
redirect to('/')
|
35
|
+
end
|
36
|
+
|
37
|
+
post '/profiler/disable' do
|
38
|
+
MongoProfiler.disable!
|
39
|
+
|
40
|
+
redirect to('/')
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/profiler/groups/:group_id' do
|
44
|
+
@group_id = params[:group_id]
|
45
|
+
@profiles = MongoProfiler.collection.find(group_id: @group_id).to_a
|
46
|
+
|
47
|
+
@sample_profile = @profiles.first
|
48
|
+
|
49
|
+
@profiles_count = @profiles.count
|
50
|
+
@profiles_total_time = @profiles.reduce(0) { |sum, p| sum + p['total_time'] }
|
51
|
+
|
52
|
+
@grouped_profiles = @profiles.group_by { |profile| profile['method'] }
|
53
|
+
|
54
|
+
erb :group_id
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/profiler/:_id' do
|
58
|
+
@profile_id = BSON::ObjectId(params[:_id])
|
59
|
+
@profile = MongoProfiler.collection.find_one(_id: @profile_id)
|
60
|
+
@instrument_payload = JSON.parse(@profile['instrument_payload'])
|
61
|
+
|
62
|
+
@collection_name = @instrument_payload['collection']
|
63
|
+
@selector = @instrument_payload['selector']
|
64
|
+
|
65
|
+
begin
|
66
|
+
@selector.each_pair do |key, value|
|
67
|
+
if value.is_a? Hash
|
68
|
+
if value.first[0] == '$oid'
|
69
|
+
@selector[key] = BSON::ObjectId(value.first[1])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
@explain = MongoProfiler.database[@collection_name].find(@selector).explain
|
74
|
+
rescue => e
|
75
|
+
@explain = { error: "Unable to generate explain: #{e.message}" }
|
76
|
+
end
|
77
|
+
|
78
|
+
# http://docs.mongodb.org/manual/core/capped-collections/
|
79
|
+
# You can update documents in a collection after inserting them. However, these updates cannot cause the documents to grow. If the update operation causes the document to grow beyond their original size, the update operation will fail.
|
80
|
+
# If you plan to update documents in a capped collection, create an index so that these update operations do not require a table scan.
|
81
|
+
# MongoRubyProfiler.collection.update({ _id: BSON::ObjectId(params[:_id]) }, '$set' => { explain: explain } )
|
82
|
+
erb :show
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module MongoProfiler
|
4
|
+
module WebHelpers
|
5
|
+
def root_path
|
6
|
+
"#{env['SCRIPT_NAME']}/"
|
7
|
+
end
|
8
|
+
|
9
|
+
def graphite_graph_timers_url(profile, from, size, title)
|
10
|
+
file = profile['file']
|
11
|
+
method = profile['method']
|
12
|
+
application_name = profile['application_name']
|
13
|
+
|
14
|
+
URI.escape(["#{MongoProfiler.graphite_url}/render?",
|
15
|
+
"from=#{from}&",
|
16
|
+
'until=now&width=400&height=250&',
|
17
|
+
"target=#{graphite_timers_target(application_name, file, method, size)}",
|
18
|
+
"&title=#{title}"].join)
|
19
|
+
end
|
20
|
+
|
21
|
+
def graphite_graph_count_url(profile, from, size, title)
|
22
|
+
file = profile['file']
|
23
|
+
method = profile['method']
|
24
|
+
application_name = profile['application_name']
|
25
|
+
|
26
|
+
URI.escape(["#{MongoProfiler.graphite_url}/render?",
|
27
|
+
"from=#{from}&",
|
28
|
+
'until=now&width=400&height=250&',
|
29
|
+
"target=#{graphite_count_target(application_name, file, method, size)}",
|
30
|
+
"&title=#{title}"].join)
|
31
|
+
end
|
32
|
+
|
33
|
+
def print_backtrace_entry(entry)
|
34
|
+
if entry.include?('gem/ruby') || entry.include?('rubies/ruby') || entry.include?('bundle/ruby')
|
35
|
+
entry
|
36
|
+
else
|
37
|
+
%{<span class="btn-info">#{entry}</span>}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def graphite_timers_target(application_name, file, method, size)
|
44
|
+
file = file.split('/').last
|
45
|
+
file_key = sanitaze_stat_key(file)
|
46
|
+
method_key = sanitaze_stat_key(method)
|
47
|
+
|
48
|
+
"alias(summarize(stats.timers.#{MongoProfiler.stats_prefix}mongo_profiler.#{application_name}.#{file_key}.#{method_key}.mean, '#{size}', 'mean'), '#{file}##{method}')"
|
49
|
+
end
|
50
|
+
|
51
|
+
def graphite_count_target(application_name, file, method, size)
|
52
|
+
file = file.split('/').last
|
53
|
+
file_key = sanitaze_stat_key(file)
|
54
|
+
method_key = sanitaze_stat_key(method)
|
55
|
+
|
56
|
+
binding.pry
|
57
|
+
|
58
|
+
"alias(summarize(stats_counts.#{MongoProfiler.stats_prefix}mongo_profiler.#{application_name}.#{file_key}.#{method_key}, '#{size}', 'sum'), '#{file}##{method}')"
|
59
|
+
end
|
60
|
+
|
61
|
+
def sanitaze_stat_key(key)
|
62
|
+
key.gsub(/\W/, '_')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mongo_profiler/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mongo_profiler"
|
8
|
+
spec.version = MongoProfiler::VERSION
|
9
|
+
spec.authors = ["Pablo Cantero"]
|
10
|
+
spec.email = ["pablo@pablocantero.com"]
|
11
|
+
spec.summary = %q{Ruby profiling tool for MongoDB}
|
12
|
+
spec.description = %q{A Ruby profiling tool for MongoDB}
|
13
|
+
spec.homepage = "https://github.com/phstc/mongo_profiler"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport"
|
22
|
+
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "mongo", "1.9.2"
|
25
|
+
spec.add_development_dependency "bson_ext"
|
26
|
+
spec.add_development_dependency "rspec", "~> 2.14.1"
|
27
|
+
spec.add_development_dependency "pry-byebug"
|
28
|
+
spec.add_development_dependency "sinatra"
|
29
|
+
spec.add_development_dependency "shotgun"
|
30
|
+
spec.add_development_dependency "rack-test"
|
31
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module MongoProfiler
|
4
|
+
describe Caller do
|
5
|
+
subject { described_class.new(_caller) }
|
6
|
+
|
7
|
+
let(:_caller) {
|
8
|
+
[
|
9
|
+
"/Users/pablo/workspace/project/spec/mongo_profiler_spec.rb:7:in `new'",
|
10
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
11
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `fetch'",
|
12
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block in let'"
|
13
|
+
]
|
14
|
+
}
|
15
|
+
|
16
|
+
its(:file) { should end_with('project/spec/mongo_profiler_spec.rb') }
|
17
|
+
its(:line) { should eq 7 }
|
18
|
+
its(:method) { should eq 'new' }
|
19
|
+
its(:_caller) { should eq _caller }
|
20
|
+
|
21
|
+
context 'when stacktrace starts with bundle or gem' do
|
22
|
+
let(:_caller) {
|
23
|
+
[
|
24
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
25
|
+
"/Users/pablo/bundle/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
26
|
+
"/Users/pablo/workspace/project/spec/mongo_profiler_spec.rb:7:in `new'",
|
27
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `fetch'",
|
28
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block in let'"
|
29
|
+
]
|
30
|
+
}
|
31
|
+
|
32
|
+
its(:file) { should end_with('project/spec/mongo_profiler_spec.rb') }
|
33
|
+
its(:line) { should eq 7 }
|
34
|
+
its(:method) { should eq 'new' }
|
35
|
+
its(:_caller) { should eq _caller }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#mongo_profiler_caller' do
|
39
|
+
|
40
|
+
context 'when mongo_profiler' do
|
41
|
+
let(:_caller) {
|
42
|
+
[
|
43
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
44
|
+
"/Users/pablo/bundle/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
45
|
+
"/Users/pablo/workspace/project/spec/mongo_profiler.rb:7:in `new'",
|
46
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `fetch'",
|
47
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block in let'"
|
48
|
+
]
|
49
|
+
}
|
50
|
+
|
51
|
+
its(:mongo_profiler_caller?) { should be_true }
|
52
|
+
|
53
|
+
context 'when _spec' do
|
54
|
+
let(:_caller) {
|
55
|
+
[
|
56
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
57
|
+
"/Users/pablo/bundle/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
58
|
+
"/Users/pablo/workspace/project/spec/mongo_profiler_spec.rb:7:in `new'",
|
59
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `fetch'",
|
60
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block in let'"
|
61
|
+
]
|
62
|
+
}
|
63
|
+
|
64
|
+
its(:mongo_profiler_caller?) { should be_false }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when external' do
|
69
|
+
let(:_caller) {
|
70
|
+
[
|
71
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
72
|
+
"/Users/pablo/bundle/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block (2 levels) in let'",
|
73
|
+
"/Users/pablo/workspace/project/file.rb:7:in `new'",
|
74
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `fetch'",
|
75
|
+
"/Users/pablo/.gem/ruby/2.0.0/gems/rspec-core-2.14.4/lib/rspec/core/memoized_helpers.rb:199:in `block in let'"
|
76
|
+
]
|
77
|
+
}
|
78
|
+
|
79
|
+
its(:mongo_profiler_caller?) { should be_false }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Mongo::Cursor' do
|
4
|
+
let(:collection) { COLL }
|
5
|
+
|
6
|
+
describe '#send_initial_query' do
|
7
|
+
context 'when enabled' do
|
8
|
+
let(:stats_client) { double('StatsD client').as_null_object }
|
9
|
+
|
10
|
+
before do
|
11
|
+
MongoProfiler.enable!
|
12
|
+
|
13
|
+
MongoProfiler.stats_client = stats_client
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'populate stats' do
|
17
|
+
expect(stats_client).to receive(:increment).with(any_args)
|
18
|
+
expect(stats_client).to receive(:timing).with(any_args)
|
19
|
+
|
20
|
+
collection.find_one
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'creates a profiler entry' do
|
24
|
+
expect {
|
25
|
+
collection.insert(test: 'test')
|
26
|
+
expect(collection.find_one['test']).to eq 'test'
|
27
|
+
}.to change { MongoProfiler.collection.count }.by(1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when disabled' do
|
32
|
+
before { MongoProfiler.disable! }
|
33
|
+
|
34
|
+
it 'skips profiler entry' do
|
35
|
+
expect {
|
36
|
+
collection.insert(test: 'test')
|
37
|
+
expect(collection.find_one['test']).to eq 'test'
|
38
|
+
}.to_not change { MongoProfiler.collection.count }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module MongoProfiler
|
4
|
+
describe Payload do
|
5
|
+
subject { described_class.new(payload) }
|
6
|
+
|
7
|
+
describe '#system_database?' do
|
8
|
+
context 'when admin' do
|
9
|
+
let(:payload) { { database: 'admin' } }
|
10
|
+
|
11
|
+
its(:system_database?) { should be_true }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when system' do
|
15
|
+
let(:payload) { { database: 'system' } }
|
16
|
+
|
17
|
+
its(:system_database?) { should be_true }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when other' do
|
21
|
+
let(:payload) { { database: 'other' } }
|
22
|
+
|
23
|
+
its(:system_database?) { should be_false }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#system_collection?' do
|
28
|
+
context 'when admin' do
|
29
|
+
let(:payload) { { collection: 'mongo_profiler' } }
|
30
|
+
|
31
|
+
its(:system_collection?) { should be_true }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when system' do
|
35
|
+
let(:payload) { { collection: 'system' } }
|
36
|
+
|
37
|
+
its(:system_collection?) { should be_true }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when other' do
|
41
|
+
let(:payload) { { collection: 'other' } }
|
42
|
+
|
43
|
+
its(:system_collection?) { should be_false }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#system_count?' do
|
48
|
+
context 'when admin' do
|
49
|
+
let(:payload) { { selector: { count: 'mongo_profiler' } } }
|
50
|
+
|
51
|
+
its(:system_count?) { should be_true }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when system' do
|
55
|
+
let(:payload) { { selector: { count: 'system' } } }
|
56
|
+
|
57
|
+
its(:system_count?) { should be_true }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when other' do
|
61
|
+
let(:payload) { { selector: { count: 'other' } } }
|
62
|
+
|
63
|
+
its(:system_count?) { should be_false }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#system_distinct?' do
|
68
|
+
context 'when admin' do
|
69
|
+
let(:payload) { { selector: { distinct: 'mongo_profiler' } } }
|
70
|
+
|
71
|
+
its(:system_distinct?) { should be_true }
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when system' do
|
75
|
+
let(:payload) { { selector: { distinct: 'system' } } }
|
76
|
+
|
77
|
+
its(:system_distinct?) { should be_true }
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when other' do
|
81
|
+
let(:payload) { { selector: { distinct: 'other' } } }
|
82
|
+
|
83
|
+
its(:system_distinct?) { should be_false }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#system_command?' do
|
88
|
+
context 'when count' do
|
89
|
+
let(:payload) { { collection: '$cmd', selector: { count: 'something' } } }
|
90
|
+
|
91
|
+
its(:system_command?) { should be_false }
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when distinct' do
|
95
|
+
let(:payload) { { collection: '$cmd', selector: { distinct: 'something' } } }
|
96
|
+
|
97
|
+
its(:system_command?) { should be_false }
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when other' do
|
101
|
+
let(:payload) { { collection: '$cmd', selector: { getnonce: -1 } } }
|
102
|
+
|
103
|
+
its(:system_command?) { should be_true }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#system_any?' do
|
108
|
+
pending
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|