diff --git a/.gitignore b/.gitignore index 5977428..7d1dc03 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,11 @@ res/* media_manager/indexer/indexers/prowlarr.http *.egg-info .env +config +images +data +res + web/cache/ diff --git a/Writerside/mm.tree b/Writerside/mm.tree index dda72df..7c906ec 100644 --- a/Writerside/mm.tree +++ b/Writerside/mm.tree @@ -17,6 +17,7 @@ + diff --git a/Writerside/topics/Logging.md b/Writerside/topics/Logging.md new file mode 100644 index 0000000..9e03cad --- /dev/null +++ b/Writerside/topics/Logging.md @@ -0,0 +1,11 @@ +# Logging + +MediaManager automatically logs events and errors to help with troubleshooting and monitoring. These logs are emitted to +the console (stdout) by default, and to a json-formatted log file. + +## Configuring Logging + +The location of the log file can be configured with the `LOG_FILE` environment variable. By default, the log file is +located at +`/app/config/media_manager.log`. When changing the log file location, ensure that the directory exists, is writable by the +MediaManager container and that it is a full path. \ No newline at end of file diff --git a/media_manager/main.py b/media_manager/main.py index 07a07c3..399afff 100644 --- a/media_manager/main.py +++ b/media_manager/main.py @@ -4,8 +4,16 @@ import sys from logging.config import dictConfig from pythonjsonlogger.json import JsonFormatter from pathlib import Path +from datetime import datetime, timezone +class ISOJsonFormatter(JsonFormatter): + def formatTime(self, record, datefmt=None): + dt = datetime.fromtimestamp(record.created, tz=timezone.utc) + return dt.isoformat(timespec="milliseconds").replace("+00:00", "Z") + + +LOG_FILE = Path(os.getenv("LOG_FILE", "/app/config/media_manager.log")) LOGGING_CONFIG = { "version": 1, "disable_existing_loggers": False, @@ -14,7 +22,13 @@ LOGGING_CONFIG = { "format": "%(asctime)s - %(levelname)s - %(name)s - %(funcName)s(): %(message)s" }, "json": { - "()": JsonFormatter, + "()": ISOJsonFormatter, + "format": "%(asctime)s %(levelname)s %(name)s %(message)s", + "rename_fields": { + "levelname": "level", + "asctime": "timestamp", + "name": "module", + }, }, }, "handlers": { @@ -26,11 +40,16 @@ LOGGING_CONFIG = { "file": { "class": "logging.handlers.RotatingFileHandler", "formatter": "json", - "filename": "./log.txt", + "filename": str(LOG_FILE), "maxBytes": 10485760, "backupCount": 5, + "encoding": "utf-8", }, }, + "root": { + "level": "DEBUG", + "handlers": ["console", "file"], + }, "loggers": { "uvicorn": {"handlers": ["console", "file"], "level": "DEBUG"}, "uvicorn.access": {"handlers": ["console", "file"], "level": "DEBUG"}, @@ -102,7 +121,6 @@ from fastapi import FastAPI, APIRouter # noqa: E402 from fastapi.middleware.cors import CORSMiddleware # noqa: E402 from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware # noqa: E402 from starlette.responses import Response # noqa: E402 -from datetime import datetime # noqa: E402 from contextlib import asynccontextmanager # noqa: E402 from apscheduler.schedulers.background import BackgroundScheduler # noqa: E402 from apscheduler.triggers.cron import CronTrigger # noqa: E402