Query_counter context manager to get the number of queries. This works by updating the `profiling_level` of the database so that all queries get logged, resetting the db.system.profile collection at the beginning of the context and counting the new entries. This was designed for debuggi
| 191 | |
| 192 | |
| 193 | class query_counter: |
| 194 | """Query_counter context manager to get the number of queries. |
| 195 | This works by updating the `profiling_level` of the database so that all queries get logged, |
| 196 | resetting the db.system.profile collection at the beginning of the context and counting the new entries. |
| 197 | |
| 198 | This was designed for debugging purpose. In fact it is a global counter so queries issued by other threads/processes |
| 199 | can interfere with it |
| 200 | |
| 201 | Usage: |
| 202 | |
| 203 | .. code-block:: python |
| 204 | |
| 205 | class User(Document): |
| 206 | name = StringField() |
| 207 | |
| 208 | with query_counter() as q: |
| 209 | user = User(name='Bob') |
| 210 | assert q == 0 # no query fired yet |
| 211 | user.save() |
| 212 | assert q == 1 # 1 query was fired, an 'insert' |
| 213 | user_bis = User.objects().first() |
| 214 | assert q == 2 # a 2nd query was fired, a 'find_one' |
| 215 | |
| 216 | Be aware that: |
| 217 | |
| 218 | - Iterating over large amount of documents (>101) makes pymongo issue `getmore` queries to fetch the next batch of documents (https://www.mongodb.com/docs/manual/tutorial/iterate-a-cursor/#cursor-batches) |
| 219 | - Some queries are ignored by default by the counter (killcursors, db.system.indexes) |
| 220 | """ |
| 221 | |
| 222 | def __init__(self, alias=DEFAULT_CONNECTION_NAME): |
| 223 | self.db = get_db(alias=alias) |
| 224 | self.initial_profiling_level = None |
| 225 | self._ctx_query_counter = 0 # number of queries issued by the context |
| 226 | |
| 227 | self._ignored_query = { |
| 228 | "ns": {"$ne": "%s.system.indexes" % self.db.name}, |
| 229 | "op": {"$ne": "killcursors"}, # MONGODB < 3.2 |
| 230 | "command.killCursors": {"$exists": False}, # MONGODB >= 3.2 |
| 231 | } |
| 232 | |
| 233 | def _turn_on_profiling(self): |
| 234 | profile_update_res = self.db.command({"profile": 0}) |
| 235 | self.initial_profiling_level = profile_update_res["was"] |
| 236 | |
| 237 | self.db.system.profile.drop() |
| 238 | self.db.command({"profile": 2}) |
| 239 | |
| 240 | def _resets_profiling(self): |
| 241 | self.db.command({"profile": self.initial_profiling_level}) |
| 242 | |
| 243 | def __enter__(self): |
| 244 | self._turn_on_profiling() |
| 245 | return self |
| 246 | |
| 247 | def __exit__(self, t, value, traceback): |
| 248 | self._resets_profiling() |
| 249 | |
| 250 | def __eq__(self, value): |
no outgoing calls