Source code for flexget.utils.log
"""Logging utilities."""
from __future__ import annotations
import hashlib
from datetime import datetime, timedelta
from typing import TYPE_CHECKING
from loguru import logger
from sqlalchemy import Column, DateTime, Index, Integer, String
from flexget import db_schema
from flexget.event import event
from flexget.utils.database import with_session
from flexget.utils.sqlalchemy_utils import table_schema
logger = logger.bind(name='util.log')
if TYPE_CHECKING:
import loguru
from sqlalchemy.orm import Session
Base = object
else:
Base = db_schema.versioned_base('log_once', 0)
@db_schema.upgrade('log_once')
def upgrade(ver: int | None, session: Session):
if ver is None:
logger.info('Adding index to md5sum column of log_once table.')
table = table_schema('log_once', session)
Index('log_once_md5sum', table.c.md5sum, unique=True).create(bind=session.bind)
ver = 0
return ver
[docs]
class LogMessage(Base):
"""Declarative."""
__tablename__ = 'log_once'
id = Column(Integer, primary_key=True)
md5sum = Column(String, unique=True)
added = Column(DateTime, default=datetime.now())
def __init__(self, md5sum: str) -> None:
self.md5sum = md5sum
def __repr__(self) -> str:
return f"<LogMessage('{self.md5sum}')>"
[docs]
@event('manager.db_cleanup')
def purge(manager, session: Session) -> None:
"""Purge old messages from database."""
old = datetime.now() - timedelta(days=365)
result = session.query(LogMessage).filter(LogMessage.added < old).delete()
if result:
logger.verbose('Purged {} entries from log_once table.', result)
@with_session
def log_once(
message: str,
logger: loguru.Logger | None = None,
once_level: str = 'INFO',
suppressed_level: str = 'VERBOSE',
session: Session = None,
) -> bool | None:
"""Log message only once using given logger`.
Return False if suppressed logging.
When suppressed, `suppressed_level` level is still logged.
"""
if logger is None:
logger = globals()['logger'].bind(name='log_once')
# If there is no active manager, don't access the db
from flexget.manager import manager
if not manager:
logger.warning('DB not initialized. log_once will not work properly.')
logger.log(once_level, message)
return None
digest = hashlib.md5()
digest.update(message.encode('latin1', 'replace'))
md5sum = digest.hexdigest()
# abort if this has already been logged
if session.query(LogMessage).filter_by(md5sum=md5sum).first():
logger.log(suppressed_level, message)
return False
row = LogMessage(md5sum)
session.add(row)
session.flush()
logger.log(once_level, message)
return True