feat: add loguru-based logging with file rotation and stdout output

This commit is contained in:
Esa Kataja
2025-05-14 11:50:40 +03:00
parent f719ad5d80
commit cce8efa0f4
6 changed files with 53 additions and 10 deletions
+1
View File
@@ -10,3 +10,4 @@ wheels/
.venv
.vscode
*.log
+1
View File
@@ -8,4 +8,5 @@ dependencies = [
"pydantic>=2.11.4",
"typer==0.9.0",
"click==8.1.3",
"loguru>=0.7.3",
]
+4 -2
View File
@@ -1,6 +1,7 @@
import typer
import os
from helpers import get_targets, run_backup, ask_repokey
from logger import logger
app = typer.Typer()
@@ -13,10 +14,11 @@ def backup():
for target in targets:
if not target.enabled:
print(f"Skipping disabled target: {target.path}")
logger.info(f"Skipping disabled target: {target.path}")
continue
result_info = run_backup(target)
print(result_info.model_dump_json(indent=2))
logger.info(f"Backup completed for {target.path}")
logger.debug(result_info.model_dump_json(indent=2))
if __name__ == "__main__":
+11 -7
View File
@@ -6,6 +6,7 @@ from subprocess import run
import os
import typer
from typing import Optional
from logger import logger
# Constants
JSON_TARGETS = Path(__file__).parent / "targets.json"
@@ -73,6 +74,7 @@ def get_targets() -> list[BackupItem]:
targets = json.load(f)
return [BackupItem(**target) for target in targets]
except (json.JSONDecodeError, FileNotFoundError) as e:
logger.error(f"Error loading targets: {e}")
typer.echo(f"Error loading targets: {e}")
return []
@@ -98,6 +100,7 @@ def add_target(target: BackupItem) -> bool:
write_targets(targets)
return True
except Exception as e:
logger.error(f"Error adding target: {e}")
typer.echo(f"Error adding target: {e}")
return False
@@ -122,6 +125,7 @@ def write_targets(targets: list[BackupItem]) -> bool:
)
return True
except Exception as e:
logger.error(f"Error writing targets: {e}")
typer.echo(f"Error writing targets: {e}")
return False
@@ -162,7 +166,7 @@ def prune_backups(targets: list[BackupItem], daily: int = 1, weekly: int = 2,
"--keep-yearly", str(yearly),
target.target,
]
print("Pruning target:", target.path)
logger.info(f"Pruning target: {target.path}")
prune_result = run(cmd, capture_output=True, text=True)
if prune_result.returncode != 0:
@@ -170,8 +174,8 @@ def prune_backups(targets: list[BackupItem], daily: int = 1, weekly: int = 2,
results.append(result)
continue
print("Pruned target:", target.path)
print("Compacting cache")
logger.info(f"Pruned target: {target.path}")
logger.info("Compacting cache")
compact_result = run(["borg", "compact", target.target], capture_output=True, text=True)
if compact_result.returncode != 0:
@@ -179,7 +183,7 @@ def prune_backups(targets: list[BackupItem], daily: int = 1, weekly: int = 2,
results.append(result)
continue
print("Compacted cache")
logger.info("Compacted cache")
result["success"] = True
result["message"] = "Pruned and compacted successfully"
@@ -226,11 +230,11 @@ def run_backup(target: BackupItem) -> Optional[ResultInfo]:
cmd.insert(3, "--exclude")
cmd.insert(4, ",".join(target.excludes))
print("Running target:", target.path)
logger.info(f"Running target: {target.path}")
result = run(cmd, capture_output=True)
if result.returncode != 0:
print("Result:", result.stderr.decode("utf-8"))
logger.error(f"Backup error: {result.stderr.decode('utf-8')}")
raise Exception(result.stderr.decode("utf-8"))
result_info = ResultInfo(**json.loads(result.stdout.decode("utf-8")))
@@ -239,5 +243,5 @@ def run_backup(target: BackupItem) -> Optional[ResultInfo]:
return result_info
except Exception as e:
print(f"Backup failed: {str(e)}")
logger.error(f"Backup failed: {str(e)}")
return None
+11
View File
@@ -0,0 +1,11 @@
from loguru import logger
from pathlib import Path
from sys import stdout
LOGS_DIR = Path(__file__).parent / "logs"
if not LOGS_DIR.exists():
LOGS_DIR.mkdir(parents=True)
logger.remove()
logger.add(LOGS_DIR / "backupper.log", level="INFO", rotation="1 day", compression="gz")
logger.add(stdout, level="INFO", format="<level>{message}</level>")
Generated
+24
View File
@@ -17,6 +17,7 @@ version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "click" },
{ name = "loguru" },
{ name = "pydantic" },
{ name = "typer" },
]
@@ -24,6 +25,7 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "click", specifier = "==8.1.3" },
{ name = "loguru", specifier = ">=0.7.3" },
{ name = "pydantic", specifier = ">=2.11.4" },
{ name = "typer", specifier = "==0.9.0" },
]
@@ -49,6 +51,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
[[package]]
name = "loguru"
version = "0.7.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "win32-setctime", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6", size = 63559, upload-time = "2024-12-06T11:20:56.608Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c", size = 61595, upload-time = "2024-12-06T11:20:54.538Z" },
]
[[package]]
name = "pydantic"
version = "2.11.4"
@@ -139,3 +154,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846
wheels = [
{ url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" },
]
[[package]]
name = "win32-setctime"
version = "1.2.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b3/8f/705086c9d734d3b663af0e9bb3d4de6578d08f46b1b101c2442fd9aecaa2/win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0", size = 4867, upload-time = "2024-12-07T15:28:28.314Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e1/07/c6fe3ad3e685340704d314d765b7912993bcb8dc198f0e7a89382d37974b/win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390", size = 4083, upload-time = "2024-12-07T15:28:26.465Z" },
]