Skip to content

add debug logging for SchemaEditor operations #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions django_mongodb/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .operations import DatabaseOperations
from .query_utils import regex_match
from .schema import DatabaseSchemaEditor
from .utils import CollectionDebugWrapper
from .utils import OperationDebugWrapper


class Cursor:
Expand Down Expand Up @@ -137,9 +137,14 @@ def __init__(self, *args, **kwargs):
def get_collection(self, name, **kwargs):
collection = Collection(self.database, name, **kwargs)
if self.queries_logged:
collection = CollectionDebugWrapper(collection, self)
collection = OperationDebugWrapper(self, collection)
return collection

def get_database(self):
if self.queries_logged:
return OperationDebugWrapper(self)
return self.database

def __getattr__(self, attr):
"""
Connect to the database the first time `connection` or `database` are
Expand Down
18 changes: 12 additions & 6 deletions django_mongodb/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@


class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
def get_collection(self, name):
return self.connection.get_collection(name)

def get_database(self):
return self.connection.get_database()

@wrap_database_errors
def create_model(self, model):
self.connection.database.create_collection(model._meta.db_table)
self.get_database().create_collection(model._meta.db_table)
# Make implicit M2M tables.
for field in model._meta.local_many_to_many:
if field.remote_field.through._meta.auto_created:
Expand All @@ -17,7 +23,7 @@ def delete_model(self, model):
for field in model._meta.local_many_to_many:
if field.remote_field.through._meta.auto_created:
self.delete_model(field.remote_field.through)
self.connection.database[model._meta.db_table].drop()
self.get_collection(model._meta.db_table).drop()

def add_field(self, model, field):
# Create implicit M2M tables.
Expand All @@ -26,7 +32,7 @@ def add_field(self, model, field):
return
# Set default value on existing documents.
if column := field.column:
self.connection.database[model._meta.db_table].update_many(
self.get_collection(model._meta.db_table).update_many(
{}, [{"$set": {column: self.effective_default(field)}}]
)

Expand All @@ -41,7 +47,7 @@ def _alter_field(
new_db_params,
strict=False,
):
collection = self.connection.database[model._meta.db_table]
collection = self.get_collection(model._meta.db_table)
# Have they renamed the column?
if old_field.column != new_field.column:
collection.update_many({}, {"$rename": {old_field.column: new_field.column}})
Expand All @@ -59,7 +65,7 @@ def remove_field(self, model, field):
return
# Unset field on existing documents.
if column := field.column:
self.connection.database[model._meta.db_table].update_many({}, {"$unset": {column: ""}})
self.get_collection(model._meta.db_table).update_many({}, {"$unset": {column: ""}})

def alter_index_together(self, model, old_index_together, new_index_together):
pass
Expand All @@ -85,4 +91,4 @@ def remove_constraint(self, model, constraint):
def alter_db_table(self, model, old_db_table, new_db_table):
if old_db_table == new_db_table:
return
self.connection.database[old_db_table].rename(new_db_table)
self.get_collection(old_db_table).rename(new_db_table)
18 changes: 12 additions & 6 deletions django_mongodb/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ def check_django_compatability():
)


class CollectionDebugWrapper:
def __init__(self, collection, db):
class OperationDebugWrapper:
def __init__(self, db, collection=None):
self.collection = collection
self.db = db
use_collection = collection is not None
self.collection_name = f"{collection.name}." if use_collection else ""
self.wrapped = self.collection if use_collection else self.db.database

def __getattr__(self, attr):
return getattr(self.collection, attr)
return getattr(self.wrapped, attr)

def profile_call(self, func, args=(), kwargs=None):
start = time.monotonic()
Expand All @@ -43,8 +46,8 @@ def log(self, op, duration, args, kwargs=None):
# If kwargs are used by any operations in the future, they must be
# added to this logging.
msg = "(%.3f) %s"
args = ", ".join(str(arg) for arg in args)
operation = f"{self.collection.name}.{op}({args})"
args = ", ".join(repr(arg) for arg in args)
operation = f"db.{self.collection_name}{op}({args})"
if len(settings.DATABASES) > 1:
msg += f"; alias={self.db.alias}"
self.db.queries_log.append(
Expand All @@ -66,7 +69,7 @@ def log(self, op, duration, args, kwargs=None):

def logging_wrapper(method):
def wrapper(self, *args, **kwargs):
func = getattr(self.collection, method)
func = getattr(self.wrapped, method)
# Collection.insert_many() mutates args (the documents) by adding
# _id. deepcopy() to avoid logging that version.
original_args = copy.deepcopy(args)
Expand All @@ -78,8 +81,11 @@ def wrapper(self, *args, **kwargs):

# These are the operations that this backend uses.
aggregate = logging_wrapper("aggregate")
create_collection = logging_wrapper("create_collection")
drop = logging_wrapper("drop")
insert_many = logging_wrapper("insert_many")
delete_many = logging_wrapper("delete_many")
rename = logging_wrapper("rename")
update_many = logging_wrapper("update_many")

del logging_wrapper