awesome_explain 0.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d14b9a43988b0efc8466fe97d9965a54a7282212
4
+ data.tar.gz: 9a7238a42460d51e72cf15fffdec97439de8adcd
5
+ SHA512:
6
+ metadata.gz: 8a2204580bbf2207f3cec4b922b8cd91f066d847a64f018a83df469ac599dd7a3121048e2629a75f3fb9e6025b59742371d254d0a01154dc14a41bfa8ad944cc
7
+ data.tar.gz: c3650a11afcb33eb926e77ccbf6e4be5e9776719235f3352e08ac2f9eb56da428043e7c9be875a8aeaf3db37d6d940b15bc05338d6077ecfd29c80a32ca9db14
@@ -0,0 +1,20 @@
1
+ version: "2"
2
+ plugins:
3
+ flog:
4
+ enabled: true
5
+ config:
6
+ score_threshold: 20.0
7
+ rubocop:
8
+ enabled: true
9
+ reek:
10
+ enabled: true
11
+ duplication:
12
+ enabled: true
13
+ config:
14
+ languages:
15
+ ruby:
16
+ mass_threshold: 35
17
+ exclude_patterns:
18
+ - coverage/
19
+ - docs/
20
+ - spec/
@@ -0,0 +1,204 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+
14
+ # Created by https://www.gitignore.io/api/vim,osx,windows,rubymine,sublimetext,visualstudiocode
15
+
16
+ ### OSX ###
17
+ # General
18
+ .DS_Store
19
+ .AppleDouble
20
+ .LSOverride
21
+
22
+ # Icon must end with two \r
23
+ Icon
24
+
25
+ # Thumbnails
26
+ ._*
27
+
28
+ # Files that might appear in the root of a volume
29
+ .DocumentRevisions-V100
30
+ .fseventsd
31
+ .Spotlight-V100
32
+ .TemporaryItems
33
+ .Trashes
34
+ .VolumeIcon.icns
35
+ .com.apple.timemachine.donotpresent
36
+
37
+ # Directories potentially created on remote AFP share
38
+ .AppleDB
39
+ .AppleDesktop
40
+ Network Trash Folder
41
+ Temporary Items
42
+ .apdisk
43
+
44
+ ### RubyMine ###
45
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
46
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
47
+
48
+ # User-specific stuff
49
+ .idea/**/workspace.xml
50
+ .idea/**/tasks.xml
51
+ .idea/**/usage.statistics.xml
52
+ .idea/**/dictionaries
53
+ .idea/**/shelf
54
+
55
+ # Generated files
56
+ .idea/**/contentModel.xml
57
+
58
+ # Sensitive or high-churn files
59
+ .idea/**/dataSources/
60
+ .idea/**/dataSources.ids
61
+ .idea/**/dataSources.local.xml
62
+ .idea/**/sqlDataSources.xml
63
+ .idea/**/dynamic.xml
64
+ .idea/**/uiDesigner.xml
65
+ .idea/**/dbnavigator.xml
66
+
67
+ # Gradle
68
+ .idea/**/gradle.xml
69
+ .idea/**/libraries
70
+
71
+ # Gradle and Maven with auto-import
72
+ # When using Gradle or Maven with auto-import, you should exclude module files,
73
+ # since they will be recreated, and may cause churn. Uncomment if using
74
+ # auto-import.
75
+ # .idea/modules.xml
76
+ # .idea/*.iml
77
+ # .idea/modules
78
+
79
+ # CMake
80
+ cmake-build-*/
81
+
82
+ # Mongo Explorer plugin
83
+ .idea/**/mongoSettings.xml
84
+
85
+ # File-based project format
86
+ *.iws
87
+
88
+ # IntelliJ
89
+ out/
90
+
91
+ # mpeltonen/sbt-idea plugin
92
+ .idea_modules/
93
+
94
+ # JIRA plugin
95
+ atlassian-ide-plugin.xml
96
+
97
+ # Cursive Clojure plugin
98
+ .idea/replstate.xml
99
+
100
+ # Crashlytics plugin (for Android Studio and IntelliJ)
101
+ com_crashlytics_export_strings.xml
102
+ crashlytics.properties
103
+ crashlytics-build.properties
104
+ fabric.properties
105
+
106
+ # Editor-based Rest Client
107
+ .idea/httpRequests
108
+
109
+ ### RubyMine Patch ###
110
+ # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
111
+
112
+ # *.iml
113
+ # modules.xml
114
+ # .idea/misc.xml
115
+ # *.ipr
116
+
117
+ # Sonarlint plugin
118
+ .idea/sonarlint
119
+
120
+ ### SublimeText ###
121
+ # Cache files for Sublime Text
122
+ *.tmlanguage.cache
123
+ *.tmPreferences.cache
124
+ *.stTheme.cache
125
+
126
+ # Workspace files are user-specific
127
+ *.sublime-workspace
128
+
129
+ # Project files should be checked into the repository, unless a significant
130
+ # proportion of contributors will probably not be using Sublime Text
131
+ # *.sublime-project
132
+
133
+ # SFTP configuration file
134
+ sftp-config.json
135
+
136
+ # Package control specific files
137
+ Package Control.last-run
138
+ Package Control.ca-list
139
+ Package Control.ca-bundle
140
+ Package Control.system-ca-bundle
141
+ Package Control.cache/
142
+ Package Control.ca-certs/
143
+ Package Control.merged-ca-bundle
144
+ Package Control.user-ca-bundle
145
+ oscrypto-ca-bundle.crt
146
+ bh_unicode_properties.cache
147
+
148
+ # Sublime-github package stores a github token in this file
149
+ # https://packagecontrol.io/packages/sublime-github
150
+ GitHub.sublime-settings
151
+
152
+ ### Vim ###
153
+ # Swap
154
+ [._]*.s[a-v][a-z]
155
+ [._]*.sw[a-p]
156
+ [._]s[a-rt-v][a-z]
157
+ [._]ss[a-gi-z]
158
+ [._]sw[a-p]
159
+
160
+ # Session
161
+ Session.vim
162
+
163
+ # Temporary
164
+ .netrwhist
165
+ *~
166
+ # Auto-generated tag files
167
+ tags
168
+ # Persistent undo
169
+ [._]*.un~
170
+
171
+ ### VisualStudioCode ###
172
+ .vscode/*
173
+ !.vscode/settings.json
174
+ !.vscode/tasks.json
175
+ !.vscode/launch.json
176
+ !.vscode/extensions.json
177
+
178
+ ### Windows ###
179
+ # Windows thumbnail cache files
180
+ Thumbs.db
181
+ ehthumbs.db
182
+ ehthumbs_vista.db
183
+
184
+ # Dump file
185
+ *.stackdump
186
+
187
+ # Folder config file
188
+ [Dd]esktop.ini
189
+
190
+ # Recycle Bin used on file shares
191
+ $RECYCLE.BIN/
192
+
193
+ # Windows Installer files
194
+ *.cab
195
+ *.msi
196
+ *.msix
197
+ *.msm
198
+ *.msp
199
+
200
+ # Windows shortcuts
201
+ *.lnk
202
+
203
+
204
+ # End of https://www.gitignore.io/api/vim,osx,windows,rubymine,sublimetext,visualstudiocode
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,19 @@
1
+ addons:
2
+ code_climate:
3
+ repo_token:
4
+ secure: "iLix2/7jYzbxfOe4hGvikPIfDL/xhIz5h0z6h0aZg1UMagnAue5UStYcvk5u1UtyTBW/aAW8WIgGVZG09a4J2Ker6+PaLskt94FytqTwQzAN6jONAdIlpreCdfFM5KbFVA7v9VszfkEcuYmAde4n1GbN4Hle84WeHAGI9dPd9sgvrbmIwAxcYSlYrDhqnMCzi0Z4Fqpbw0pLP6ZYWgoV1DywlFvCKjOcWaY1M0QoPZnJT/AGA9BGiJk42KfXCwY3b80VnixGFXtIgRqfFU1b0ZGptdtjETnDNeG2CA63sQoyAxOAStKxpTRKXRG/sI8fxuDdLDeqMOdrSpc19zqbr4hvUCn2+ukJMe3r4iKt5m4VjffcJVEXI8h7e16bbsBFvsgLQcxjBWcH5p9vOAl8aEHttUnaGvjtwza5MGTg2yI1CnIG+zMgb/MaR04zhI6YbKiZ88E5QXlyKBfA7DaT8ojRlpIIBFWhF7WpXBgCIxMB6afG8DaUTCCyFsa3xmvU+DR31xbgvKIYsv7etcCOqqmpbx+sQDIXUK6t4iF+d+ZWzj+CL1DtSw0I4Qkfmvj4nl4Zy3MRNZdr8vJbJf39bf2JTGqjd1qfCW/q1XV+2Bqtjp4wIOP/LWGlmcQYVnZ2q+13mP7wKyE6JVzX8khqkiggvtK255C8ETXc1BVBx6E="
5
+ sudo: false
6
+ language: ruby
7
+ cache: bundler
8
+ rvm:
9
+ - 2.3.4
10
+ before_install: gem install bundler -v 1.16.0
11
+ notifications: false
12
+ before_script:
13
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
14
+ - chmod +x ./cc-test-reporter
15
+ - ./cc-test-reporter before-build
16
+ script:
17
+ - bundle exec rspec
18
+ after_script:
19
+ - ./cc-test-reporter after-build -t simplecov -p /home/travis/build/sandboxws/awesome_explain
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at aelhussaini@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in awesome_explain.gemspec
6
+ gemspec
@@ -0,0 +1,77 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ awesome_explain (0.3.0)
5
+ awesome_print (~> 1.0)
6
+ terminal-table (~> 1.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (5.2.1)
12
+ activesupport (= 5.2.1)
13
+ activesupport (5.2.1)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ ansi (1.5.0)
19
+ awesome_print (1.8.0)
20
+ bson (4.3.0)
21
+ concurrent-ruby (1.0.5)
22
+ diff-lcs (1.3)
23
+ docile (1.3.1)
24
+ hirb (0.7.3)
25
+ i18n (1.1.0)
26
+ concurrent-ruby (~> 1.0)
27
+ json (2.1.0)
28
+ minitest (5.11.3)
29
+ mongo (2.6.2)
30
+ bson (>= 4.3.0, < 5.0.0)
31
+ mongoid (7.0.1)
32
+ activemodel (>= 5.1, < 6.0.0)
33
+ mongo (>= 2.5.1, < 3.0.0)
34
+ rake (10.5.0)
35
+ rspec (3.7.0)
36
+ rspec-core (~> 3.7.0)
37
+ rspec-expectations (~> 3.7.0)
38
+ rspec-mocks (~> 3.7.0)
39
+ rspec-core (3.7.1)
40
+ rspec-support (~> 3.7.0)
41
+ rspec-expectations (3.7.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.7.0)
44
+ rspec-mocks (3.7.0)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.7.0)
47
+ rspec-support (3.7.1)
48
+ simplecov (0.16.1)
49
+ docile (~> 1.1)
50
+ json (>= 1.8, < 3)
51
+ simplecov-html (~> 0.10.0)
52
+ simplecov-console (0.4.2)
53
+ ansi
54
+ hirb
55
+ simplecov
56
+ simplecov-html (0.10.2)
57
+ terminal-table (1.8.0)
58
+ unicode-display_width (~> 1.1, >= 1.1.1)
59
+ thread_safe (0.3.6)
60
+ tzinfo (1.2.5)
61
+ thread_safe (~> 0.1)
62
+ unicode-display_width (1.4.0)
63
+
64
+ PLATFORMS
65
+ ruby
66
+
67
+ DEPENDENCIES
68
+ awesome_explain!
69
+ bundler (~> 1.16)
70
+ mongoid (>= 5)
71
+ rake (~> 10.0)
72
+ rspec (~> 3.0)
73
+ simplecov (~> 0.16.1)
74
+ simplecov-console (~> 0.4.2)
75
+
76
+ BUNDLED WITH
77
+ 1.16.3
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Ahmed El.Hussaini
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,74 @@
1
+ # AwesomeExplain
2
+
3
+ Awesome explain is a simple global method that provides quick insights into mongodb's query plan and execution stats.
4
+ Currently the explain functionality only supports `Mongo::Collection::View::Aggregation` & ``Mongoid::Criteria`.
5
+
6
+ [![Build Status](https://travis-ci.com/sandboxws/awesome_explain.svg?branch=master)](https://travis-ci.com/sandboxws/awesome_explain)
7
+ [![Maintainability](https://api.codeclimate.com/v1/badges/75e1a5cb4b6a5c1ba4c8/maintainability)](https://codeclimate.com/github/sandboxws/awesome_explain/maintainability)
8
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/75e1a5cb4b6a5c1ba4c8/test_coverage)](https://codeclimate.com/github/sandboxws/awesome_explain/test_coverage)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
+
11
+ ## Installation
12
+
13
+ Add the following line to your application's Gemfile:
14
+
15
+ `gem 'awesome_explain', require: true`
16
+
17
+ ## Usage
18
+
19
+ `ae Article.where(author_id: '5b9ec484d5cc2e697189d7c9')`
20
+
21
+ ```
22
+ +--------------------+-----------------------------+
23
+ | Winning Plan | FETCH (7 / 7) -> IXSCAN (7) |
24
+ +--------------------+-----------------------------+
25
+ | Used Indexes | author_id_1 (forward) |
26
+ +--------------------+-----------------------------+
27
+ | Rejected Plans | 0 |
28
+ +--------------------+-----------------------------+
29
+ | Documents Returned | 7 |
30
+ +--------------------+-----------------------------+
31
+ | Documents Examined | 7 |
32
+ +--------------------+-----------------------------+
33
+ | Keys Examined | 7 |
34
+ +--------------------+-----------------------------+
35
+ | Execution time(ms) | 0 |
36
+ +--------------------+-----------------------------+
37
+ | Execution time(s) | 0.0 |
38
+ +--------------------+-----------------------------+
39
+ ```
40
+
41
+ `ae Article.or([{author_id: '5b9ec484d5cc2e697189d7c9', state: 'published'}, {created_at: 3.days.ago}])`
42
+
43
+ ```
44
+
45
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
46
+ | Winning Plan | SORT (20) -> SORT_KEY_GENERATOR (20) -> FETCH (24 / 20) -> OR (24) -> [ FETCH (24 / 24) -> IXSCAN (24) , FETCH (0 / 0) -> IXSCAN (0) ] |
47
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
48
+ | Used Indexes | state_1 (forward), author_id_1 (forward) |
49
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
50
+ | Rejected Plans | 18 |
51
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
52
+ | Documents Returned | 20 |
53
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
54
+ | Documents Examined | 48 |
55
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
56
+ | Keys Examined | 24 |
57
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
58
+ | Execution time(ms) | 37 |
59
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
60
+ | Execution time(s) | 0.037 |
61
+ +--------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
62
+ ```
63
+
64
+ ## Winning Plan Examples
65
+
66
+ `FETCH (7 / 7) -> IXSCAN (7)`
67
+
68
+ Below is a breakdown of the above winning plan:
69
+
70
+ - First stage is a `FETCH` stage. 7 documents were examined, and 7 were returned.
71
+ - Second stage was an `IXSCAN` stage were 7 documents were returned.
72
+
73
+ For information about MongoDB's explain output, please refer to the official MongoDB Explain documentation:
74
+ https://docs.mongodb.com/manual/reference/explain-results/
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'awesome_explain/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'awesome_explain'
9
+ spec.version = AwesomeExplain::VERSION
10
+ spec.authors = ['Ahmed El.Hussaini']
11
+ spec.email = ['aelhussaini@gmail.com']
12
+
13
+ spec.summary = 'Awesome and simple approach to explain Mongoid queries'
14
+ spec.description = 'An awesome and simple approach to explain Mongoid queries that provides winning plan stages and overall statistics'
15
+ spec.homepage = 'https://github.com/sandboxws/awesome_explain'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'awesome_print', '~> 1.0'
24
+ spec.add_dependency 'terminal-table', '~> 1.0'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.16'
27
+ spec.add_development_dependency 'mongoid', '>= 5'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.0'
30
+ spec.add_development_dependency 'simplecov-console', '~> 0.4.2'
31
+ spec.add_development_dependency 'simplecov', '~> 0.16.1'
32
+ end
@@ -0,0 +1,7 @@
1
+ require 'awesome_explain/version'
2
+ require 'terminal-table'
3
+ require 'awesome_explain/renderers/mongoid'
4
+ require 'awesome_explain/kernel'
5
+
6
+ module AwesomeExplain
7
+ end
@@ -0,0 +1,14 @@
1
+ module Kernel
2
+ def ae(query)
3
+ return AwesomeExplain::Renderers::Mongoid.new(query).print if mongoid_query?(query)
4
+ query
5
+ end
6
+
7
+ private
8
+
9
+ def mongoid_query?(query)
10
+ defined?(Mongo::Collection::View::Aggregation) &&
11
+ defined?(Mongoid::Criteria) &&
12
+ (query.is_a?(Mongo::Collection::View::Aggregation) || query.is_a?(Mongoid::Criteria))
13
+ end
14
+ end
@@ -0,0 +1,135 @@
1
+ module AwesomeExplain
2
+ module Renderers
3
+ class Mongoid
4
+ attr_reader :result, :query
5
+
6
+ COLOR_ESCAPES = {
7
+ none: 0, bright: 1, black: 30,
8
+ red: 31, green: 32, yellow: 33,
9
+ blue: 34, magenta: 35, cyan: 36,
10
+ white: 37, default: 39
11
+ }
12
+
13
+ def initialize(query)
14
+ @query = query
15
+ end
16
+
17
+ def print
18
+ @result = query.explain
19
+
20
+ print_general_info
21
+ end
22
+
23
+ # Text foreground color
24
+ def fg_color(clr, text = nil)
25
+ "\x1B[" + (COLOR_ESCAPES[clr] || 0).to_s + 'm' + (text ? text + "\x1B[0m" : '')
26
+ end
27
+
28
+ # Text background color
29
+ def bg_color(clr, text = nil)
30
+ "\x1B[" + ((COLOR_ESCAPES[clr] || 0) + 10).to_s + 'm' + (text ? text + "\x1B[0m" : '')
31
+ end
32
+
33
+ def print_general_info
34
+ ap result, indent: -2
35
+ table = Terminal::Table.new do |t|
36
+ winning_plan_label = 'Winning Plan'
37
+ plan_data = winning_plan_data
38
+ winning_plan_str = plan_data[0]
39
+ used_indexes = plan_data[1]
40
+ winning_plan_label = fg_color :red, winning_plan_label if winning_plan_str =~ /COLLSCAN/
41
+ t << [winning_plan_label, winning_plan_str]
42
+ t << :separator
43
+ t << ['Used Indexes', used_indexes.join(', ')]
44
+ if execution_stats
45
+ t << :separator
46
+ t << ['Rejected Plans', rejected_plans.size]
47
+ t << :separator
48
+ t << ['Documents Returned', execution_stats.dig('nReturned')]
49
+ t << :separator
50
+ t << ['Documents Examined', execution_stats.dig('totalDocsExamined')]
51
+ t << :separator
52
+ t << ['Keys Examined', execution_stats.dig('totalKeysExamined')]
53
+ t << :separator
54
+
55
+ # Execution Time
56
+ exec_time = execution_stats.dig('executionTimeMillis').to_f/1000
57
+ exec_time_ms = execution_stats.dig('executionTimeMillis')
58
+ exec_label = 'Execution time(s)'
59
+ exec_label_ms = 'Execution time(ms)'
60
+
61
+ if exec_time > 10
62
+ exec_label = fg_color :red, exec_label
63
+ exec_label_ms = fg_color :red, exec_label_ms
64
+ end
65
+ t << [exec_label_ms, exec_time_ms]
66
+ t << :separator
67
+ t << [exec_label, exec_time]
68
+ end
69
+ end
70
+
71
+ puts
72
+ puts table
73
+ puts
74
+ end
75
+
76
+ def winning_plan_data
77
+ used_indexes = []
78
+ plan = winning_plan
79
+ plan_str = stage_label_and_stats(plan)
80
+ plan_str = dig_input_stages(plan.dig('inputStage'), plan_str, used_indexes) if plan['inputStage']
81
+
82
+ [plan_str, used_indexes]
83
+ end
84
+
85
+ def root
86
+ result.dig('$cursor') || result
87
+ end
88
+
89
+ def winning_plan
90
+ root.dig('executionStats', 'executionStages') || root.dig('queryPlanner', 'winningPlan')
91
+ end
92
+
93
+ def rejected_plans
94
+ root.dig('queryPlanner', 'rejectedPlans')
95
+ end
96
+
97
+ def execution_stats
98
+ root.dig('executionStats')
99
+ end
100
+
101
+ def dig_input_stages(stage, str, used_indexes, input_stages = false)
102
+ used_indexes << "#{stage.dig('indexName')} (#{stage.dig('direction')})" if stage.dig('indexName').present?
103
+ if stage.dig('inputStage').nil? && stage.dig('inputStages').nil?
104
+ str += ' -> ' + stage_label_and_stats(stage)
105
+ end
106
+ if stage.dig('inputStage').present?
107
+ str += ' ->' if !input_stages
108
+ str += ' ' + stage_label_and_stats(stage)
109
+ str = dig_input_stages(stage.dig('inputStage'), str, used_indexes, input_stages)
110
+ end
111
+
112
+ if stage.dig('inputStages').present?
113
+ str += ' -> ' + stage_label_and_stats(stage) + ' ->'
114
+ str += ' [ '
115
+ stage.dig('inputStages').each_with_index do |s, idx|
116
+ str = dig_input_stages(s, str, used_indexes, true)
117
+ str += ' , ' if idx < stage.dig('inputStages').size - 1
118
+ end
119
+ str += ' ] '
120
+ end
121
+
122
+ str
123
+ end
124
+
125
+ def stage_label_and_stats(stage)
126
+ str = "#{stage.dig('stage')} ("
127
+ str += "#{stage.dig('docsExamined')} / " if stage.dig('docsExamined').present?
128
+ str += stage.dig('nReturned').to_s if stage.dig('nReturned').present?
129
+ str += ')'
130
+
131
+ str.gsub(' ()', '')
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,3 @@
1
+ module AwesomeExplain
2
+ VERSION = '0.3.0'
3
+ end
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awesome_explain
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Ahmed El.Hussaini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: awesome_print
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '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: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: terminal-table
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.16'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mongoid
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov-console
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.4.2
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.4.2
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.16.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.16.1
125
+ description: An awesome and simple approach to explain Mongoid queries that provides
126
+ winning plan stages and overall statistics
127
+ email:
128
+ - aelhussaini@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".codeclimate.yml"
134
+ - ".gitignore"
135
+ - ".rspec"
136
+ - ".travis.yml"
137
+ - CODE_OF_CONDUCT.md
138
+ - Gemfile
139
+ - Gemfile.lock
140
+ - LICENSE.txt
141
+ - README.md
142
+ - Rakefile
143
+ - awesome_explain.gemspec
144
+ - lib/awesome_explain.rb
145
+ - lib/awesome_explain/kernel.rb
146
+ - lib/awesome_explain/renderers/mongoid.rb
147
+ - lib/awesome_explain/version.rb
148
+ homepage: https://github.com/sandboxws/awesome_explain
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 2.6.14
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: Awesome and simple approach to explain Mongoid queries
172
+ test_files: []