Skip to content

Commit

Permalink
[IMPROVEMENT]: Added namespace and auto deletion based on backup_count
Browse files Browse the repository at this point in the history
  • Loading branch information
amadolid committed Oct 7, 2024
1 parent ed1e7a3 commit 4e3cef6
Showing 1 changed file with 66 additions and 43 deletions.
109 changes: 66 additions & 43 deletions jac-cloud/jac_cloud/jaseci/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
from datetime import time as dtime
from enum import IntEnum
from io import text_encoding
from logging import FileHandler, LogRecord, getLogger
from itertools import chain
from logging import LogRecord, getLogger
from logging.handlers import (
BaseRotatingHandler,
RotatingFileHandler,
TimedRotatingFileHandler,
)
from os import getenv, remove, rename, stat
from os.path import exists, isfile
from os import getenv, remove, stat
from os.path import exists, getmtime, isfile
from pathlib import Path
from re import ASCII, compile
from re import ASCII, compile, escape
from stat import ST_MTIME
from time import gmtime, localtime, strftime, time as ttime
from typing import Any

from ecs_logging import StdlibFormatter

DEFAULT_PART = [0]


class MixedTimedRotatingFileHandler(TimedRotatingFileHandler, RotatingFileHandler):
"""Merge TimedRotatingFileHandler and RotatingFileHandler."""
Expand Down Expand Up @@ -57,22 +60,26 @@ def __init__(
self.backupCount = backup_count
self.utc = utc
self.atTime = at_time

re_suffix = escape(self.file_name) + r"-[0-9]+" + escape(self.file_ext) + "$"
if self.when == "S":
self.interval = 1
self.suffix = "%Y-%m-%d-%H-%M-%S"
ext_match = r"(?<!\d)\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(?!\d)"
ext_match = (
r"^(?<!\d)\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}(?!\d)-" + re_suffix
)
elif self.when == "M":
self.interval = 60
self.suffix = "%Y-%m-%d-%H-%M"
ext_match = r"(?<!\d)\d{4}-\d{2}-\d{2}_\d{2}-\d{2}(?!\d)"
ext_match = r"^(?<!\d)\d{4}-\d{2}-\d{2}-\d{2}-\d{2}(?!\d)-" + re_suffix
elif self.when == "H":
self.interval = 60 * 60
self.suffix = "%Y-%m-%d-%H"
ext_match = r"(?<!\d)\d{4}-\d{2}-\d{2}_\d{2}(?!\d)"
ext_match = r"^(?<!\d)\d{4}-\d{2}-\d{2}-\d{2}(?!\d)-" + re_suffix
elif self.when == "D" or self.when == "MIDNIGHT":
self.interval = 60 * 60 * 24
self.suffix = "%Y-%m-%d"
ext_match = r"(?<!\d)\d{4}-\d{2}-\d{2}(?!\d)"
ext_match = r"^(?<!\d)\d{4}-\d{2}-\d{2}(?!\d)-" + re_suffix
elif self.when.startswith("W"):
self.interval = 60 * 60 * 24 * 7
if len(self.when) != 2:
Expand All @@ -85,7 +92,7 @@ def __init__(
)
self.dayOfWeek = int(self.when[1])
self.suffix = "%Y-%m-%d"
ext_match = r"(?<!\d)\d{4}-\d{2}-\d{2}(?!\d)"
ext_match = r"^(?<!\d)\d{4}-\d{2}-\d{2}(?!\d)-" + re_suffix
else:
raise ValueError(f"Invalid rollover interval specified: {self.when}")

Expand All @@ -98,15 +105,53 @@ def __init__(
t = ttime()
self.rolloverAt = self.computeRollover(int(t))

def build_file_name(self, prefix: str, part: int) -> str:
def build_file_name(self, prefix: str) -> str:
"""Override rotation_filename."""
part_extractor = compile(
r"^"
+ escape(f"{prefix}-{self.file_name}-")
+ r"([0-9]+)"
+ escape(self.file_ext)
+ r"$"
)

part = (
max(
chain(
(
int(match.group(1))
for path in self.file_folder.iterdir()
if (match := part_extractor.match(path.name))
),
DEFAULT_PART,
)
)
+ 1
)

name = f"{self.file_folder}/{prefix}-{self.file_name}-{part}{self.file_ext}"

if not callable(self.namer):
return name
else:
return self.namer(name)

def remove_old_backup(self) -> None:
"""Remove old backup files."""
if self.backupCount > 0:
backups = sorted(
(
path
for path in self.file_folder.iterdir()
if self.extMatch.match(path.name)
),
key=getmtime,
)

if self.backupCount < (backup_count := len(backups)):
for backup in backups[0 : backup_count - self.backupCount]:
remove(backup)

def doRollover(self) -> None: # noqa: N802
"""Override doRollover."""
current_time = int(ttime())
Expand All @@ -128,26 +173,9 @@ def doRollover(self) -> None: # noqa: N802
if self.stream:
self.stream.close()
self.stream = None # type: ignore[assignment]
if self.backupCount > 0:
for i in range(self.backupCount - 1, 0, -1):
sfn = self.build_file_name(prefix, i)
dfn = self.build_file_name(prefix, i + 1)
if exists(sfn):
if exists(dfn):
remove(dfn)
rename(sfn, dfn)
dfn = self.build_file_name(prefix, 1)
if exists(dfn):
remove(dfn)
self.rotate(self.baseFilename, dfn)
else:
part = 1
while True:
dfn = self.build_file_name(prefix, part)
if not exists(dfn):
self.rotate(self.baseFilename, dfn)
break
part += 1

self.rotate(self.baseFilename, self.build_file_name(prefix))
self.remove_old_backup()

if not self.delay:
self.stream = self._open()
Expand Down Expand Up @@ -187,19 +215,14 @@ class Level(IntEnum):
logger = getLogger(getenv("LOGGER_NAME", "app"))
logger.setLevel(Level[getenv("LOGGER_LEVEL", "DEBUG")].value)

if getenv("ELASTIC_LOGGER") == "true":
handler = FileHandler(getenv("LOGGER_FILE_PATH", "elastic-log.json"))
handler.setFormatter(StdlibFormatter())
logger.addHandler(handler)
else:
handler = MixedTimedRotatingFileHandler(
getenv("LOGGER_FILE_PATH", "jac-cloud.log"),
when="d",
backup_count=int(getenv("LOGGER_DAILY_MAX_FILE", "-1")),
max_bytes=int(getenv("LOGGER_MAX_FILE_SIZE", "10000000")),
)
handler.setFormatter(StdlibFormatter())
logger.addHandler(handler)
handler = MixedTimedRotatingFileHandler(
getenv("LOGGER_FILE_NAMESPACE", "") + getenv("LOGGER_FILE_PATH", "jac-cloud.log"),
when=getenv("LOGGER_TIME_INTERVAL", "d"),
backup_count=int(getenv("LOGGER_MAX_BACKUP", "5")),
max_bytes=int(getenv("LOGGER_MAX_FILE_SIZE", "1000")),
)
handler.setFormatter(StdlibFormatter())
logger.addHandler(handler)


def log_entry(
Expand Down

0 comments on commit 4e3cef6

Please sign in to comment.