feat: add loguru-based logging with file rotation and stdout output
This commit is contained in:
@@ -10,3 +10,4 @@ wheels/
|
||||
.venv
|
||||
|
||||
.vscode
|
||||
*.log
|
||||
@@ -8,4 +8,5 @@ dependencies = [
|
||||
"pydantic>=2.11.4",
|
||||
"typer==0.9.0",
|
||||
"click==8.1.3",
|
||||
"loguru>=0.7.3",
|
||||
]
|
||||
|
||||
+4
-2
@@ -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
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
@@ -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" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user