Advanced topics¶
Admin UI¶
The admin UI is designed for browsing logger health first and raw entries second.
- The landing page shows one card per logger.
- Each card shows total errors, total warnings, recent issues from the last hour, and a timeline strip.
- Available ranges come from
LOG_PANEL["RANGES"]. - Clicking a logger opens a paginated table view.
- The table view supports level filtering and free-text message search.
- Timestamps are rendered in Django's configured default timezone.
Admin URL:
Writing logs¶
Any standard Python logger can write into log_panel as long as your Django logging configuration routes records into the active log_panel handler.
import logging
logger = logging.getLogger(__name__)
logger.info("Info log")
logger.warning("Warning log")
logger.error("Error log")
logger.critical("Critical log")
Named loggers work the same way:
import logging
sql_logger = logging.getLogger("myapp.sql")
sql_logger.debug("Manual SQL diagnostic message")
Threshold alerts¶
django-log-panel emits the Django signal log_panel.signals.log_threshold_reached when a logger crosses a configured count threshold.
How it works¶
After each record is written, the handler counts how many records at the configured level the same logger has emitted in the last rolling hour. The signal is dispatched only when the count exactly reaches the configured threshold.
Configure thresholds per log level through LOG_PANEL["THRESHOLDS"]:
ThresholdAlertEvent¶
| Field | Type | Description |
|---|---|---|
logger_name |
str |
Logger that crossed the threshold. |
threshold_level |
LogLevel |
Configured level that was evaluated. |
record_level |
LogLevel |
Level of the triggering record. |
threshold |
int |
Configured threshold value. |
matching_count |
int |
Count within the rolling window. |
timestamp |
datetime |
Timestamp of the triggering record. |
window_start |
datetime |
Inclusive start of the rolling one-hour window. |
window_end |
datetime |
End of the rolling one-hour window. |
message |
str |
Triggering record message. |
module |
str |
Module where the record was emitted. |
pathname |
str |
Source file path. |
line_number |
int |
Source line number. |
Receiver example¶
from django.dispatch import receiver
from log_panel.signals import ThresholdAlertEvent, log_threshold_reached
@receiver(log_threshold_reached)
def on_threshold_reached(sender, event: ThresholdAlertEvent, **kwargs):
...
Notes¶
- The signal uses
send_robust, so exceptions in receivers do not break log writing. - When you wrap a
log_panelhandler inlogging.handlers.MemoryHandler, the signal fires when the buffered record is flushed into the real handler.
High-volume logging¶
By default DatabaseHandler writes each record immediately — one database round-trip per log call. That is the safest option but can become a bottleneck when LOG_LEVEL is DEBUG or request volume is high.
BufferedDatabaseHandler¶
BufferedDatabaseHandler accumulates records in memory and writes them in a single bulk_create call. Enable it by setting BUFFER_SIZE in your LOG_PANEL configuration:
When ATTACH_ROOT_HANDLER is True (the default), the auto-attached handler is automatically upgraded to BufferedDatabaseHandler when BUFFER_SIZE is set. You can also attach it manually through Django's LOGGING configuration:
LOGGING = {
"handlers": {
"log_panel": {
"class": "log_panel.handlers.BufferedDatabaseHandler",
},
},
"root": {
"handlers": ["log_panel"],
"level": "INFO",
},
}
Flushes happen when any of these conditions are met:
| Trigger | Controlled by |
|---|---|
Buffer reaches BUFFER_SIZE records |
LOG_PANEL['BUFFER_SIZE'] |
A record at or above BUFFER_FLUSH_LEVEL is emitted |
LOG_PANEL['BUFFER_FLUSH_LEVEL'] |
| A later log arrives after the flush interval elapsed | LOG_PANEL['BUFFER_FLUSH_INTERVAL'] |
flush() or close() is called explicitly |
— |
close() is called automatically during normal Django / uvicorn shutdown, so buffered records are not lost on a graceful stop. Only abrupt termination (SIGKILL, OOM) can drop records that have not been flushed yet.
Threshold signals (log_threshold_reached) still fire per-record, but only after the batch is committed. Records at or above BUFFER_FLUSH_LEVEL (default WARNING) bypass buffering and flush immediately, so alerts for important levels are never delayed.
Retention cleanup¶
The delete_old_logs management command deletes Panel rows older than the retention window. It works with both SQL and MongoDB backends.
| Option | Default | Description |
|---|---|---|
--days |
LOG_PANEL["RETENTION_DAYS"] |
Override the retention window for this run. |
--batch-size |
1000 |
Number of rows to delete per batch. Smaller batches reduce lock and I/O spikes. |
--dry-run |
not set | Print how many rows would be deleted without deleting them. |