Enable logging to Grafana Loki
This commit is contained in:
parent
28f8b9eb13
commit
f9da090705
51
akibabot/logging.py
Normal file
51
akibabot/logging.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import logging.handlers
|
||||||
|
from multiprocessing import Queue
|
||||||
|
|
||||||
|
|
||||||
|
def init_loki_logging(config: dict[str, str]):
|
||||||
|
"""Configures the logging to Loki."""
|
||||||
|
import logging_loki
|
||||||
|
|
||||||
|
queue = Queue(-1)
|
||||||
|
handler = logging.handlers.QueueHandler(queue)
|
||||||
|
handler_loki = logging_loki.LokiHandler(
|
||||||
|
url=config["loki"]["url"],
|
||||||
|
version="1",
|
||||||
|
tags={
|
||||||
|
"application": "akibabot",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
"name=%(name)s level=%(levelname)s time=%(asctime)s %(message)s",
|
||||||
|
datefmt="%Y-%m-%d-%H:%M:%S",
|
||||||
|
)
|
||||||
|
logging.handlers.QueueListener(queue, handler_loki)
|
||||||
|
logging.getLogger().addHandler(handler_loki)
|
||||||
|
|
||||||
|
|
||||||
|
def init_logging(config: dict[str, str]):
|
||||||
|
"""Initialises the logging"""
|
||||||
|
# Check if we should use Loki and configure it, if enabled.
|
||||||
|
log_config = config.get("logging", {})
|
||||||
|
loki = config.get("loki", {})
|
||||||
|
if loki.get("enable", False):
|
||||||
|
init_loki_logging(config)
|
||||||
|
|
||||||
|
# Configure logging to the console, if enabled.
|
||||||
|
logger = logging.getLogger()
|
||||||
|
if log_config.get("console", True):
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||||
|
)
|
||||||
|
console_handler = logging.StreamHandler(stream=sys.stdout)
|
||||||
|
console_handler.setFormatter(formatter)
|
||||||
|
logger.addHandler(console_handler)
|
||||||
|
|
||||||
|
# Set the log level
|
||||||
|
level = {
|
||||||
|
"info": logging.INFO,
|
||||||
|
"debug": logging.DEBUG,
|
||||||
|
}.get(log_config.get("level", "info"))
|
||||||
|
logger.setLevel(level)
|
@ -10,6 +10,7 @@ import toml
|
|||||||
import akibapass_downloader.login
|
import akibapass_downloader.login
|
||||||
import akibapass_downloader.episode
|
import akibapass_downloader.episode
|
||||||
|
|
||||||
|
from akibabot.logging import init_logging
|
||||||
from akibabot.xmpp import send_notification
|
from akibabot.xmpp import send_notification
|
||||||
|
|
||||||
|
|
||||||
@ -69,23 +70,21 @@ def get_episode_numbers(
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def setup_logging():
|
|
||||||
"""Sets up the logging."""
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Setup logging
|
|
||||||
setup_logging()
|
|
||||||
|
|
||||||
# Load config
|
# Load config
|
||||||
config_file = sys.argv[1]
|
config_file = sys.argv[1]
|
||||||
config = toml.load(config_file)
|
config = toml.load(config_file)
|
||||||
|
|
||||||
|
# Load secrets
|
||||||
|
log = logging.getLogger("akibabot")
|
||||||
if (secrets_file := config["general"].get("secrets_file", None)) is not None:
|
if (secrets_file := config["general"].get("secrets_file", None)) is not None:
|
||||||
logging.info("Processing secrets config file...")
|
log.info("Processing secrets config file...")
|
||||||
secrets = toml.load(secrets_file)
|
secrets = toml.load(secrets_file)
|
||||||
config.update(secrets)
|
config.update(secrets)
|
||||||
|
|
||||||
|
# Setup logging
|
||||||
|
init_logging(config)
|
||||||
|
|
||||||
# Sanity checks
|
# Sanity checks
|
||||||
xmpp_from_jid = config["xmpp"]["jid"]
|
xmpp_from_jid = config["xmpp"]["jid"]
|
||||||
xmpp_to_jid = config["xmpp"]["to"]
|
xmpp_to_jid = config["xmpp"]["to"]
|
||||||
@ -95,7 +94,7 @@ def main():
|
|||||||
storage_path = Path(config["general"]["path"])
|
storage_path = Path(config["general"]["path"])
|
||||||
shows: list[Show] = []
|
shows: list[Show] = []
|
||||||
for show in config["shows"]:
|
for show in config["shows"]:
|
||||||
logging.info("Processing %s", show["name"])
|
log.info("Processing %s", show["name"])
|
||||||
max_episodes = show["max_episodes"]
|
max_episodes = show["max_episodes"]
|
||||||
local_episodes = get_episode_numbers(
|
local_episodes = get_episode_numbers(
|
||||||
show["name"],
|
show["name"],
|
||||||
@ -117,9 +116,11 @@ def main():
|
|||||||
|
|
||||||
# Exit early when there is no show left to handle.
|
# Exit early when there is no show left to handle.
|
||||||
if not shows:
|
if not shows:
|
||||||
print("Nothing to do.")
|
log.info("Nothing to do.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
# Load cookies, if available
|
# Load cookies, if available
|
||||||
cookies = {}
|
cookies = {}
|
||||||
cookies_path = Path(config["general"]["cookie_path"])
|
cookies_path = Path(config["general"]["cookie_path"])
|
||||||
@ -140,7 +141,7 @@ def main():
|
|||||||
|
|
||||||
# Iterate over the shows to process and download the new episodes
|
# Iterate over the shows to process and download the new episodes
|
||||||
for show in shows:
|
for show in shows:
|
||||||
logging.debug("Processing %s", show.name)
|
logging.info("Processing %s", show.name)
|
||||||
episodes_path = build_episodes_path(
|
episodes_path = build_episodes_path(
|
||||||
show.name,
|
show.name,
|
||||||
show.year,
|
show.year,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
import aioxmpp
|
import aioxmpp
|
||||||
|
|
||||||
|
|
||||||
@ -7,6 +9,7 @@ async def send_notification(
|
|||||||
"""Sends a notification of a new show download to @to using the account @jid:@password.
|
"""Sends a notification of a new show download to @to using the account @jid:@password.
|
||||||
@show_name is the name of show. @episode is the number of the episode that was just downloaded.
|
@show_name is the name of show. @episode is the number of the episode that was just downloaded.
|
||||||
"""
|
"""
|
||||||
|
logging.getLogger("akibabot.xmpp").debug("Sending notification via XMPP")
|
||||||
client = aioxmpp.PresenceManagedClient(
|
client = aioxmpp.PresenceManagedClient(
|
||||||
aioxmpp.JID.fromstr(jid),
|
aioxmpp.JID.fromstr(jid),
|
||||||
aioxmpp.make_security_layer(password),
|
aioxmpp.make_security_layer(password),
|
||||||
@ -17,5 +20,7 @@ async def send_notification(
|
|||||||
to=aioxmpp.JID.fromstr(to),
|
to=aioxmpp.JID.fromstr(to),
|
||||||
type_=aioxmpp.MessageType.CHAT,
|
type_=aioxmpp.MessageType.CHAT,
|
||||||
)
|
)
|
||||||
msg.body[None] = f"Episode {episode} of {show_name} is now downloaded and available!"
|
msg.body[
|
||||||
|
None
|
||||||
|
] = f"Episode {episode} of {show_name} is now downloaded and available!"
|
||||||
await stream.send(msg)
|
await stream.send(msg)
|
||||||
|
@ -16,6 +16,12 @@ dev = [
|
|||||||
"pylint"
|
"pylint"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# For logging to Loki
|
||||||
|
loki = [
|
||||||
|
# Loki logging
|
||||||
|
"python-logging-loki"
|
||||||
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
akibabot = "akibabot.main:main"
|
akibabot = "akibabot.main:main"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user