Backend setup¶
Use this guide when you want the full setup details for MongoDB or SQL storage, including manual LOGGING configuration.
Backend resolution¶
The admin UI reads log data through log_panel.conf.get_backend(). Resolution order is:
LOG_PANEL["BACKEND"]if you provide a custom backend class path.- ORM backend when
LOG_PANEL["DATABASE_ALIAS"]is set. - No backend, and the admin shows an unconfigured state.
LOG_PANEL controls how the admin reads logs. Handlers in Django LOGGING control where records are written.
Shared capture behavior¶
By default, log_panel attaches a DatabaseHandler to the root logger during app startup:
ATTACH_ROOT_HANDLER = Trueenables automatic setup.LOG_LEVELsets the level for the auto-attached handler and the root logger.- If a
DatabaseHandleris already attached to the root logger, auto-attach is skipped and a warning is emitted. - Stored fields come directly from the log record.
LOGGINGformatters do not change the structured fields written bylog_panel. - Exception tracebacks are appended automatically when
exc_infois present. - Messages are stored in full by default. Large messages keep an inline preview on the log row and store the complete text in ordered chunks.
- Recursive log-storage writes are skipped by the handler's recursion guard.
Set ATTACH_ROOT_HANDLER = False when you want to manage handlers yourself in Django LOGGING.
MongoDB backend¶
Use MongoDB when you want append-only logging with flexible document storage.
This backend requires two things:
- the
django-mongodb-backendpackage is installed - a running, reachable MongoDB instance
Minimal config¶
You can pass a full MongoDB connection URI in HOST:
DATABASES["logs"] = {
"ENGINE": "django_mongodb_backend",
"HOST": "mongodb://localhost:27017",
"NAME": "myapp_logs",
}
DATABASE_ROUTERS = [
"log_panel.routers.LogsRouter",
]
LOG_PANEL = {
"DATABASE_ALIAS": "logs",
"RETENTION_DAYS": 90,
}
Connection options¶
HOST accepts any standard MongoDB connection string, including mongodb+srv:// URIs, authentication credentials, and replica set addresses:
DATABASES["logs"] = {
"ENGINE": "django_mongodb_backend",
"HOST": "mongodb+srv://cluster0.example.mongodb.net",
"NAME": "myapp_logs",
"USER": "log_writer",
"PASSWORD": "...",
"PORT": 27017,
"OPTIONS": {
"retryWrites": "true",
"w": "majority",
"tls": "true",
},
}
HOST— connection URI. Omit or set"localhost"for a local instance.USER/PASSWORD— required when authentication is enabled.PORT— optional, defaults to27017.OPTIONS— passed directly to PyMongo'sMongoClient.
If you provide credentials or options in the HOST URI and as separate keys, the separate keys take precedence.
For a replica set or sharded cluster, include all hosts in HOST:
Migration¶
LogsRouter keeps the Log model on the configured logging database, but Django still targets default unless you tell it otherwise:
The router reserves the logging alias for log_panel models, so Django's system checks do not validate unrelated project apps such as auth or admin against MongoDB.
If your logging alias is default, the normal migration flow is enough.
Notes¶
- Install the package with the
mongodbextra sodjango-mongodb-backendis available. - The package does not start MongoDB for you. The
HOSTinDATABASESmust point at a real MongoDB server or cluster. django-mongodb-backendversion must match your Django version (e.g. 5.2.x for Django 5.2, 6.0.x for Django 6.0). Themongodbextra allows any compatible release.- MongoDB cleanup is not automatic. Use the
delete_old_logsmanagement command on a schedule. LogsRouteris required whenDATABASE_ALIASis set.LogPanelConfig.ready()raisesImproperlyConfiguredif it is missing.- Logs are stored through the
Panelmodel via the Django ORM — the same model and handler used by the SQL backend. - Compound indexes on
(timestamp, logger_name, level)and(logger_name, -timestamp)are created via the model Meta for query performance.
Manual LOGGING example¶
LOG_PANEL = {
"DATABASE_ALIAS": "logs",
"ATTACH_ROOT_HANDLER": False,
}
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"log_panel": {
"class": "log_panel.handlers.DatabaseHandler",
},
},
"root": {
"handlers": ["log_panel"],
"level": "INFO",
},
}
SQL backend¶
Use SQL when logs need to live in a relational database that Django can manage.
Minimal config¶
DATABASES["logs"] = {
"ENGINE": "django.db.backends.postgresql",
"NAME": "myapp_logs",
"USER": "...",
"PASSWORD": "...",
"HOST": "...",
"PORT": "...",
}
DATABASE_ROUTERS = [
"log_panel.routers.LogsRouter",
]
LOG_PANEL = {
"DATABASE_ALIAS": "logs",
"RETENTION_DAYS": 90,
}
Migration¶
LogsRouter keeps the Panel model on the configured logging database, but Django still targets default unless you tell it otherwise:
If your logging alias is default, the normal migration flow is enough.
Notes¶
LogsRouteris required whenDATABASE_ALIASis set.LogPanelConfig.ready()raisesImproperlyConfiguredif it is missing.- Logs are stored through the
Panelmodel in the configured database alias. - SQL retention cleanup is not automatic. Use the
delete_old_logscommand on a schedule.
Manual LOGGING example¶
LOG_PANEL = {
"DATABASE_ALIAS": "logs",
"ATTACH_ROOT_HANDLER": False,
}
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"log_panel": {
"class": "log_panel.handlers.DatabaseHandler",
},
},
"root": {
"handlers": ["log_panel"],
"level": "INFO",
},
}
Custom backend¶
To build your own backend, subclass log_panel.backends.base.LogsBackend and implement the abstract methods:
from log_panel.backends.base import LogsBackend
class MyBackend(LogsBackend):
def get_logger_cards(self, now_utc, range_config, app_timezone):
...
def query_logs(self, logger_names, levels, search, offset, limit, app_timezone, **kwargs):
...
def count_logs(self, logger_names, levels, search, **kwargs):
...
def get_log_table(self, logger_name, level, search, page, page_size, app_timezone, **kwargs):
...
Then point LOG_PANEL["BACKEND"] at your class:
The get_local_now_and_slot_delta helper on LogsBackend is available for timeline slot calculations if your backend needs them.