feat: replace loguru with logging
This commit is contained in:
parent
cced09f1ac
commit
c6940db289
|
@ -4,7 +4,7 @@ from typing import Optional
|
||||||
import click
|
import click
|
||||||
from libretime_shared.cli import cli_config_options, cli_logging_options
|
from libretime_shared.cli import cli_config_options, cli_logging_options
|
||||||
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
||||||
from libretime_shared.logging import level_from_name, setup_logger
|
from libretime_shared.logging import setup_logger
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .message_listener import MessageListener
|
from .message_listener import MessageListener
|
||||||
|
@ -33,7 +33,7 @@ def cli(
|
||||||
"""
|
"""
|
||||||
Run analyzer.
|
Run analyzer.
|
||||||
"""
|
"""
|
||||||
setup_logger(level_from_name(log_level), log_filepath)
|
setup_logger(log_level, log_filepath)
|
||||||
config = Config(config_filepath)
|
config = Config(config_filepath)
|
||||||
|
|
||||||
# Start up the StatusReporter process
|
# Start up the StatusReporter process
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import signal
|
import signal
|
||||||
import time
|
import time
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
|
|
||||||
import pika
|
import pika
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .pipeline import Pipeline, PipelineOptions, PipelineStatus
|
from .pipeline import Pipeline, PipelineOptions, PipelineStatus
|
||||||
from .status_reporter import StatusReporter
|
from .status_reporter import StatusReporter
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
EXCHANGE = "airtime-uploads"
|
EXCHANGE = "airtime-uploads"
|
||||||
EXCHANGE_TYPE = "topic"
|
EXCHANGE_TYPE = "topic"
|
||||||
ROUTING_KEY = ""
|
ROUTING_KEY = ""
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
import logging
|
||||||
from subprocess import CalledProcessError, CompletedProcess, run
|
from subprocess import CalledProcessError, CompletedProcess, run
|
||||||
|
|
||||||
from loguru import logger
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def run_(*args, **kwargs) -> CompletedProcess:
|
def run_(*args, **kwargs) -> CompletedProcess:
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
|
import logging
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from math import isclose
|
from math import isclose
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ._ffmpeg import compute_silences, probe_duration
|
from ._ffmpeg import compute_silences, probe_duration
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def analyze_duration(filepath: str, metadata: Dict[str, Any]) -> Dict[str, Any]:
|
def analyze_duration(filepath: str, metadata: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
import logging
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
import mutagen
|
import mutagen
|
||||||
from libretime_shared.files import compute_md5
|
from libretime_shared.files import compute_md5
|
||||||
from loguru import logger
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def analyze_metadata(filepath_: str, metadata: Dict[str, Any]):
|
def analyze_metadata(filepath_: str, metadata: Dict[str, Any]):
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import logging
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ._liquidsoap import _liquidsoap
|
from ._liquidsoap import _liquidsoap
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UnplayableFileError(Exception):
|
class UnplayableFileError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import logging
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from loguru import logger
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
MAX_DIR_LEN = 48
|
MAX_DIR_LEN = 48
|
||||||
MAX_FILE_LEN = 48
|
MAX_FILE_LEN = 48
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
import logging
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from typing import Any, Dict, Protocol
|
from typing import Any, Dict, Protocol
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from .analyze_cuepoint import analyze_cuepoint, analyze_duration
|
from .analyze_cuepoint import analyze_cuepoint, analyze_duration
|
||||||
|
@ -11,6 +11,8 @@ from .analyze_playability import UnplayableFileError, analyze_playability
|
||||||
from .analyze_replaygain import analyze_replaygain
|
from .analyze_replaygain import analyze_replaygain
|
||||||
from .organise_file import organise_file
|
from .organise_file import organise_file
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Step(Protocol):
|
class Step(Protocol):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import collections
|
import collections
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import pickle
|
import pickle
|
||||||
import queue
|
import queue
|
||||||
import threading
|
import threading
|
||||||
|
@ -7,9 +8,10 @@ import time
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from loguru import logger
|
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PicklableHttpRequest:
|
class PicklableHttpRequest:
|
||||||
def __init__(self, method, url, api_key, data):
|
def __init__(self, method, url, api_key, data):
|
||||||
|
|
|
@ -2,11 +2,11 @@ import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from libretime_shared.logging import TRACE, setup_logger
|
from libretime_shared.logging import setup_logger
|
||||||
|
|
||||||
from .fixtures import fixtures_path
|
from .fixtures import fixtures_path
|
||||||
|
|
||||||
setup_logger(TRACE)
|
setup_logger("debug")
|
||||||
|
|
||||||
AUDIO_FILENAME = "s1-stereo-tagged.mp3"
|
AUDIO_FILENAME = "s1-stereo-tagged.mp3"
|
||||||
AUDIO_FILE = fixtures_path / AUDIO_FILENAME
|
AUDIO_FILE = fixtures_path / AUDIO_FILENAME
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
from requests import Response, Session as BaseSession
|
from requests import Response, Session as BaseSession
|
||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
from urllib3.util import Retry
|
from urllib3.util import Retry
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_TIMEOUT = 5
|
DEFAULT_TIMEOUT = 5
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ from libretime_shared.config import BaseConfig, GeneralConfig
|
||||||
|
|
||||||
from ._utils import ApiRequest, RequestProvider
|
from ._utils import ApiRequest, RequestProvider
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseConfig):
|
class Config(BaseConfig):
|
||||||
general: GeneralConfig
|
general: GeneralConfig
|
||||||
|
@ -72,9 +74,7 @@ class ApiClient:
|
||||||
UPLOAD_RETRIES = 3
|
UPLOAD_RETRIES = 3
|
||||||
UPLOAD_WAIT = 60
|
UPLOAD_WAIT = 60
|
||||||
|
|
||||||
def __init__(self, logger=None, config_path="/etc/libretime/config.yml"):
|
def __init__(self, config_path="/etc/libretime/config.yml"):
|
||||||
self.logger = logger or logging
|
|
||||||
|
|
||||||
config = Config(config_path)
|
config = Config(config_path)
|
||||||
self.base_url = config.general.public_url
|
self.base_url = config.general.public_url
|
||||||
self.api_key = config.general.api_key
|
self.api_key = config.general.api_key
|
||||||
|
@ -89,27 +89,27 @@ class ApiClient:
|
||||||
try:
|
try:
|
||||||
return self.services.version_url()["api_version"]
|
return self.services.version_url()["api_version"]
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def is_server_compatible(self, verbose=True):
|
def is_server_compatible(self, verbose=True):
|
||||||
api_version = self.__get_api_version()
|
api_version = self.__get_api_version()
|
||||||
if api_version == -1:
|
if api_version == -1:
|
||||||
if verbose:
|
if verbose:
|
||||||
self.logger.info("Unable to get Airtime API version number.\n")
|
logger.info("Unable to get Airtime API version number.\n")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if api_version[0:3] != AIRTIME_API_VERSION[0:3]:
|
if api_version[0:3] != AIRTIME_API_VERSION[0:3]:
|
||||||
if verbose:
|
if verbose:
|
||||||
self.logger.info("Airtime API version found: " + str(api_version))
|
logger.info("Airtime API version found: " + str(api_version))
|
||||||
self.logger.info(
|
logger.info(
|
||||||
"pypo is only compatible with API version: " + AIRTIME_API_VERSION
|
"pypo is only compatible with API version: " + AIRTIME_API_VERSION
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
self.logger.info("Airtime API version found: " + str(api_version))
|
logger.info("Airtime API version found: " + str(api_version))
|
||||||
self.logger.info(
|
logger.info(
|
||||||
"pypo is only compatible with API version: " + AIRTIME_API_VERSION
|
"pypo is only compatible with API version: " + AIRTIME_API_VERSION
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
@ -118,7 +118,7 @@ class ApiClient:
|
||||||
try:
|
try:
|
||||||
self.services.notify_liquidsoap_started()
|
self.services.notify_liquidsoap_started()
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
def notify_media_item_start_playing(self, media_id):
|
def notify_media_item_start_playing(self, media_id):
|
||||||
"""
|
"""
|
||||||
|
@ -129,14 +129,14 @@ class ApiClient:
|
||||||
try:
|
try:
|
||||||
return self.services.update_start_playing_url(media_id=media_id)
|
return self.services.update_start_playing_url(media_id=media_id)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_shows_to_record(self):
|
def get_shows_to_record(self):
|
||||||
try:
|
try:
|
||||||
return self.services.show_schedule_url()
|
return self.services.show_schedule_url()
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def upload_recorded_show(self, files, show_id):
|
def upload_recorded_show(self, files, show_id):
|
||||||
|
@ -147,19 +147,19 @@ class ApiClient:
|
||||||
|
|
||||||
url = self.construct_rest_url("upload_file_url")
|
url = self.construct_rest_url("upload_file_url")
|
||||||
|
|
||||||
self.logger.debug(url)
|
logger.debug(url)
|
||||||
|
|
||||||
for i in range(0, retries):
|
for i in range(0, retries):
|
||||||
self.logger.debug("Upload attempt: %s", i + 1)
|
logger.debug("Upload attempt: %s", i + 1)
|
||||||
self.logger.debug(files)
|
logger.debug(files)
|
||||||
self.logger.debug(ApiRequest.API_HTTP_REQUEST_TIMEOUT)
|
logger.debug(ApiRequest.API_HTTP_REQUEST_TIMEOUT)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
request = requests.post(
|
request = requests.post(
|
||||||
url, files=files, timeout=float(ApiRequest.API_HTTP_REQUEST_TIMEOUT)
|
url, files=files, timeout=float(ApiRequest.API_HTTP_REQUEST_TIMEOUT)
|
||||||
)
|
)
|
||||||
response = request.json()
|
response = request.json()
|
||||||
self.logger.debug(response)
|
logger.debug(response)
|
||||||
|
|
||||||
# FIXME: We need to tell LibreTime that the uploaded track was recorded
|
# FIXME: We need to tell LibreTime that the uploaded track was recorded
|
||||||
# for a specific show
|
# for a specific show
|
||||||
|
@ -183,14 +183,14 @@ class ApiClient:
|
||||||
break
|
break
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as exception:
|
except requests.exceptions.HTTPError as exception:
|
||||||
self.logger.error(f"Http error code: {exception.response.status_code}")
|
logger.error(f"Http error code: {exception.response.status_code}")
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError as exception:
|
except requests.exceptions.ConnectionError as exception:
|
||||||
self.logger.exception(f"Server is down: {exception}")
|
logger.exception(f"Server is down: {exception}")
|
||||||
|
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
# wait some time before next retry
|
# wait some time before next retry
|
||||||
time.sleep(retries_wait)
|
time.sleep(retries_wait)
|
||||||
|
@ -203,7 +203,7 @@ class ApiClient:
|
||||||
username=username, password=password, djtype=dj_type
|
username=username, password=password, djtype=dj_type
|
||||||
)
|
)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def construct_rest_url(self, action_key):
|
def construct_rest_url(self, action_key):
|
||||||
|
@ -239,7 +239,7 @@ class ApiClient:
|
||||||
boot_time=time,
|
boot_time=time,
|
||||||
).retry(5)
|
).retry(5)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
def notify_source_status(self, sourcename, status):
|
def notify_source_status(self, sourcename, status):
|
||||||
try:
|
try:
|
||||||
|
@ -247,7 +247,7 @@ class ApiClient:
|
||||||
sourcename=sourcename, status=status
|
sourcename=sourcename, status=status
|
||||||
).retry(5)
|
).retry(5)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
def get_bootstrap_info(self):
|
def get_bootstrap_info(self):
|
||||||
"""
|
"""
|
||||||
|
@ -260,7 +260,7 @@ class ApiClient:
|
||||||
Update the server with the latest metadata we've received from the
|
Update the server with the latest metadata we've received from the
|
||||||
external webstream
|
external webstream
|
||||||
"""
|
"""
|
||||||
self.logger.info(
|
logger.info(
|
||||||
self.services.notify_webstream_data.req(
|
self.services.notify_webstream_data.req(
|
||||||
_post_data={"data": data}, media_id=str(media_id)
|
_post_data={"data": data}, media_id=str(media_id)
|
||||||
).retry(5)
|
).retry(5)
|
||||||
|
@ -268,7 +268,7 @@ class ApiClient:
|
||||||
|
|
||||||
def get_stream_parameters(self):
|
def get_stream_parameters(self):
|
||||||
response = self.services.get_stream_parameters()
|
response = self.services.get_stream_parameters()
|
||||||
self.logger.debug(response)
|
logger.debug(response)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def push_stream_stats(self, data):
|
def push_stream_stats(self, data):
|
||||||
|
@ -285,7 +285,7 @@ class ApiClient:
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
def update_metadata_on_tunein(self):
|
def update_metadata_on_tunein(self):
|
||||||
self.services.update_metadata_on_tunein()
|
self.services.update_metadata_on_tunein()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
@ -6,7 +7,6 @@ from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from libretime_api_client.v1 import ApiClient as LegacyClient
|
from libretime_api_client.v1 import ApiClient as LegacyClient
|
||||||
from libretime_shared.config import IcecastOutput, ShoutcastOutput
|
from libretime_shared.config import IcecastOutput, ShoutcastOutput
|
||||||
from loguru import logger
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from requests import Session
|
from requests import Session
|
||||||
from requests.exceptions import ( # pylint: disable=redefined-builtin
|
from requests.exceptions import ( # pylint: disable=redefined-builtin
|
||||||
|
@ -17,6 +17,8 @@ from requests.exceptions import ( # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from ..config import Config
|
from ..config import Config
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
AnyOutput = Union[IcecastOutput, ShoutcastOutput]
|
AnyOutput = Union[IcecastOutput, ShoutcastOutput]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import CalledProcessError, check_output, run
|
from subprocess import CalledProcessError, check_output, run
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from typing import Any, Literal, Optional, Tuple
|
from typing import Any, Literal, Optional, Tuple
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ..models import MessageFormatKind
|
from ..models import MessageFormatKind
|
||||||
from ..utils import quote
|
from ..utils import quote
|
||||||
from ..version import parse_liquidsoap_version
|
from ..version import parse_liquidsoap_version
|
||||||
from ._connection import LiquidsoapConnection
|
from ._connection import LiquidsoapConnection
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LiquidsoapClientError(Exception):
|
class LiquidsoapClientError(Exception):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from socket import AF_UNIX, SOCK_STREAM, create_connection, socket
|
from socket import AF_UNIX, SOCK_STREAM, create_connection, socket
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from loguru import logger
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class InvalidConnection(Exception):
|
class InvalidConnection(Exception):
|
||||||
|
@ -61,7 +62,7 @@ class LiquidsoapConnection:
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
logger.trace("trying to acquire lock")
|
logger.debug("trying to acquire lock")
|
||||||
# pylint: disable=consider-using-with
|
# pylint: disable=consider-using-with
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
logger.debug(f"connecting to {self.address()}")
|
logger.debug(f"connecting to {self.address()}")
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
@ -6,14 +7,15 @@ import click
|
||||||
from libretime_api_client.v2 import ApiClient
|
from libretime_api_client.v2 import ApiClient
|
||||||
from libretime_shared.cli import cli_config_options, cli_logging_options
|
from libretime_shared.cli import cli_config_options, cli_logging_options
|
||||||
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
||||||
from libretime_shared.logging import level_from_name, setup_logger
|
from libretime_shared.logging import setup_logger
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ..config import Config
|
from ..config import Config
|
||||||
from .entrypoint import generate_entrypoint
|
from .entrypoint import generate_entrypoint
|
||||||
from .models import Info, StreamPreferences
|
from .models import Info, StreamPreferences
|
||||||
from .version import get_liquidsoap_version
|
from .version import get_liquidsoap_version
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
here = Path(__file__).parent
|
here = Path(__file__).parent
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[
|
||||||
"""
|
"""
|
||||||
Run liquidsoap.
|
Run liquidsoap.
|
||||||
"""
|
"""
|
||||||
logger_level, _ = setup_logger(level_from_name(log_level), log_filepath)
|
setup_logger(log_level, log_filepath)
|
||||||
config = Config(config_filepath)
|
config = Config(config_filepath)
|
||||||
|
|
||||||
api_client = ApiClient(
|
api_client = ApiClient(
|
||||||
|
@ -53,7 +55,7 @@ def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[
|
||||||
"--verbose",
|
"--verbose",
|
||||||
str(entrypoint_filepath),
|
str(entrypoint_filepath),
|
||||||
]
|
]
|
||||||
if logger_level.is_debug():
|
if log_level == "debug":
|
||||||
exec_args.append("--debug")
|
exec_args.append("--debug")
|
||||||
|
|
||||||
logger.debug(f"liquidsoap {version} using script: {entrypoint_filepath}")
|
logger.debug(f"liquidsoap {version} using script: {entrypoint_filepath}")
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
Python part of radio playout (pypo)
|
Python part of radio playout (pypo)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -14,8 +15,7 @@ from libretime_api_client.v1 import ApiClient as LegacyClient
|
||||||
from libretime_api_client.v2 import ApiClient
|
from libretime_api_client.v2 import ApiClient
|
||||||
from libretime_shared.cli import cli_config_options, cli_logging_options
|
from libretime_shared.cli import cli_config_options, cli_logging_options
|
||||||
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
||||||
from libretime_shared.logging import level_from_name, setup_logger
|
from libretime_shared.logging import setup_logger
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from .config import CACHE_DIR, RECORD_DIR, Config
|
from .config import CACHE_DIR, RECORD_DIR, Config
|
||||||
from .history.stats import StatsCollectorThread
|
from .history.stats import StatsCollectorThread
|
||||||
|
@ -28,6 +28,8 @@ from .player.liquidsoap import PypoLiquidsoap
|
||||||
from .player.push import PypoPush
|
from .player.push import PypoPush
|
||||||
from .recorder import Recorder
|
from .recorder import Recorder
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@click.command(context_settings={"auto_envvar_prefix": DEFAULT_ENV_PREFIX})
|
@click.command(context_settings={"auto_envvar_prefix": DEFAULT_ENV_PREFIX})
|
||||||
@cli_logging_options()
|
@cli_logging_options()
|
||||||
|
@ -36,7 +38,7 @@ def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[
|
||||||
"""
|
"""
|
||||||
Run playout.
|
Run playout.
|
||||||
"""
|
"""
|
||||||
setup_logger(level_from_name(log_level), log_filepath)
|
setup_logger(log_level, log_filepath)
|
||||||
config = Config(config_filepath)
|
config = Config(config_filepath)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from queue import Queue as ThreadQueue
|
from queue import Queue as ThreadQueue
|
||||||
from signal import SIGTERM, signal
|
from signal import SIGTERM, signal
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
@ -8,10 +9,11 @@ from typing import Any, Dict
|
||||||
from kombu.connection import Connection
|
from kombu.connection import Connection
|
||||||
from kombu.messaging import Exchange, Queue
|
from kombu.messaging import Exchange, Queue
|
||||||
from kombu.mixins import ConsumerMixin
|
from kombu.mixins import ConsumerMixin
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MessageHandler(ConsumerMixin):
|
class MessageHandler(ConsumerMixin):
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|
|
@ -12,6 +12,7 @@ Main case:
|
||||||
media id from it, and then calls back to the API to tell about it about it.
|
media id from it, and then calls back to the API to tell about it about it.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
@ -19,12 +20,13 @@ import click
|
||||||
from libretime_api_client.v1 import ApiClient as LegacyClient
|
from libretime_api_client.v1 import ApiClient as LegacyClient
|
||||||
from libretime_shared.cli import cli_logging_options
|
from libretime_shared.cli import cli_logging_options
|
||||||
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
from libretime_shared.config import DEFAULT_ENV_PREFIX
|
||||||
from libretime_shared.logging import level_from_name, setup_logger
|
from libretime_shared.logging import setup_logger
|
||||||
from loguru import logger
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def api_client():
|
def api_client():
|
||||||
return LegacyClient(logger=logger)
|
return LegacyClient()
|
||||||
|
|
||||||
|
|
||||||
@click.group(context_settings={"auto_envvar_prefix": DEFAULT_ENV_PREFIX})
|
@click.group(context_settings={"auto_envvar_prefix": DEFAULT_ENV_PREFIX})
|
||||||
|
@ -33,7 +35,7 @@ def cli(log_level: str, log_filepath: Optional[Path]):
|
||||||
"""
|
"""
|
||||||
A gateway between Liquidsoap and the API.
|
A gateway between Liquidsoap and the API.
|
||||||
"""
|
"""
|
||||||
setup_logger(level_from_name(log_level), log_filepath, rotate=False)
|
setup_logger(log_level, log_filepath, rotate=False)
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
@ -11,7 +12,6 @@ from typing import Any, Dict
|
||||||
|
|
||||||
from libretime_api_client.v1 import ApiClient as LegacyClient
|
from libretime_api_client.v1 import ApiClient as LegacyClient
|
||||||
from libretime_api_client.v2 import ApiClient
|
from libretime_api_client.v2 import ApiClient
|
||||||
from loguru import logger
|
|
||||||
from requests import RequestException
|
from requests import RequestException
|
||||||
|
|
||||||
from ..config import CACHE_DIR, POLL_INTERVAL, Config
|
from ..config import CACHE_DIR, POLL_INTERVAL, Config
|
||||||
|
@ -21,6 +21,8 @@ from ..timeout import ls_timeout
|
||||||
from .liquidsoap import PypoLiquidsoap
|
from .liquidsoap import PypoLiquidsoap
|
||||||
from .schedule import get_schedule
|
from .schedule import get_schedule
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PypoFetch(Thread):
|
class PypoFetch(Thread):
|
||||||
name = "fetch"
|
name = "fetch"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
import time
|
import time
|
||||||
|
@ -7,9 +8,10 @@ from threading import Thread
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from libretime_api_client.v2 import ApiClient
|
from libretime_api_client.v2 import ApiClient
|
||||||
from loguru import logger
|
|
||||||
from requests.exceptions import ConnectionError, HTTPError, Timeout
|
from requests.exceptions import ConnectionError, HTTPError, Timeout
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PypoFile(Thread):
|
class PypoFile(Thread):
|
||||||
name = "file"
|
name = "file"
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
import logging
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ..liquidsoap.client import LiquidsoapClient
|
from ..liquidsoap.client import LiquidsoapClient
|
||||||
from ..utils import seconds_between
|
from ..utils import seconds_between
|
||||||
from .events import EventKind
|
from .events import EventKind
|
||||||
from .liquidsoap_gateway import TelnetLiquidsoap
|
from .liquidsoap_gateway import TelnetLiquidsoap
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PypoLiquidsoap:
|
class PypoLiquidsoap:
|
||||||
def __init__(self, liq_client: LiquidsoapClient):
|
def __init__(self, liq_client: LiquidsoapClient):
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import logging
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ..liquidsoap.client import LiquidsoapClient
|
from ..liquidsoap.client import LiquidsoapClient
|
||||||
from ..timeout import ls_timeout
|
from ..timeout import ls_timeout
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def create_liquidsoap_annotation(media):
|
def create_liquidsoap_annotation(media):
|
||||||
# We need liq_start_next value in the annotate. That is the value that controls overlap duration of crossfade.
|
# We need liq_start_next value in the annotate. That is the value that controls overlap duration of crossfade.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
import math
|
import math
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -5,12 +6,12 @@ from queue import Queue
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ..config import PUSH_INTERVAL, Config
|
from ..config import PUSH_INTERVAL, Config
|
||||||
from .liquidsoap import PypoLiquidsoap
|
from .liquidsoap import PypoLiquidsoap
|
||||||
from .queue import PypoLiqQueue
|
from .queue import PypoLiqQueue
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def is_stream(media_item):
|
def is_stream(media_item):
|
||||||
return media_item["type"] == "stream_output_start"
|
return media_item["type"] == "stream_output_start"
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
import logging
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from queue import Empty, Queue
|
from queue import Empty, Queue
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from ..utils import seconds_between
|
from ..utils import seconds_between
|
||||||
from .liquidsoap import PypoLiquidsoap
|
from .liquidsoap import PypoLiquidsoap
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PypoLiqQueue(Thread):
|
class PypoLiqQueue(Thread):
|
||||||
name = "liquidsoap_queue"
|
name = "liquidsoap_queue"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -12,7 +13,6 @@ from threading import Thread
|
||||||
|
|
||||||
import mutagen
|
import mutagen
|
||||||
from libretime_api_client.v1 import ApiClient as LegacyClient
|
from libretime_api_client.v1 import ApiClient as LegacyClient
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from libretime_playout.config import PUSH_INTERVAL, RECORD_DIR, Config
|
from libretime_playout.config import PUSH_INTERVAL, RECORD_DIR, Config
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ if sys.version_info < (3, 9):
|
||||||
else:
|
else:
|
||||||
from zoneinfo import ZoneInfo
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# TODO : add docstrings everywhere in this module
|
# TODO : add docstrings everywhere in this module
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from random import randint
|
from random import randint
|
||||||
from subprocess import PIPE, STDOUT, Popen
|
from subprocess import PIPE, STDOUT, Popen
|
||||||
|
@ -5,13 +6,14 @@ from textwrap import dedent
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from libretime_shared.logging import TRACE, setup_logger
|
from libretime_shared.logging import setup_logger
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from libretime_playout.liquidsoap.client import LiquidsoapConnection
|
from libretime_playout.liquidsoap.client import LiquidsoapConnection
|
||||||
from libretime_playout.liquidsoap.version import get_liquidsoap_version
|
from libretime_playout.liquidsoap.version import get_liquidsoap_version
|
||||||
|
|
||||||
setup_logger(TRACE)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
setup_logger("debug")
|
||||||
|
|
||||||
LIQ_VERSION = get_liquidsoap_version()
|
LIQ_VERSION = get_liquidsoap_version()
|
||||||
LIQ_VERSION_STR = ".".join(map(str, LIQ_VERSION))
|
LIQ_VERSION_STR = ".".join(map(str, LIQ_VERSION))
|
||||||
|
|
|
@ -7,7 +7,6 @@ The `libretime_shared` package contains reusable functions and classes for the L
|
||||||
This library assumes that:
|
This library assumes that:
|
||||||
|
|
||||||
- You will use [`Click`](https://github.com/pallets/click) to build a CLI for your app.
|
- You will use [`Click`](https://github.com/pallets/click) to build a CLI for your app.
|
||||||
- You will use [`Loguru`](https://github.com/delgan/loguru) to log messages from your app.
|
|
||||||
- You will use [`Pydantic`](https://github.com/samuelcolvin/pydantic/) to validate objects in your app.
|
- You will use [`Pydantic`](https://github.com/samuelcolvin/pydantic/) to validate objects in your app.
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
|
@ -3,8 +3,6 @@ from typing import Any, Callable, Optional
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from .logging import INFO, LOG_LEVEL_MAP
|
|
||||||
|
|
||||||
|
|
||||||
def cli_logging_options() -> Callable:
|
def cli_logging_options() -> Callable:
|
||||||
def decorator(func: Callable) -> Callable:
|
def decorator(func: Callable) -> Callable:
|
||||||
|
@ -18,8 +16,8 @@ def cli_logging_options() -> Callable:
|
||||||
func = click.option(
|
func = click.option(
|
||||||
"--log-level",
|
"--log-level",
|
||||||
"log_level",
|
"log_level",
|
||||||
type=click.Choice(list(LOG_LEVEL_MAP.keys())),
|
type=click.Choice(["error", "warning", "info", "debug"]),
|
||||||
default=INFO.name,
|
default="info",
|
||||||
help="Name of the logging level.",
|
help="Name of the logging level.",
|
||||||
)(func)
|
)(func)
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
import logging
|
||||||
import sys
|
import sys
|
||||||
from itertools import zip_longest
|
from itertools import zip_longest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
from pydantic import BaseModel, ValidationError
|
from pydantic import BaseModel, ValidationError
|
||||||
from yaml import YAMLError, safe_load
|
from yaml import YAMLError, safe_load
|
||||||
|
|
||||||
from ._env import EnvLoader
|
from ._env import EnvLoader
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_ENV_PREFIX = "LIBRETIME"
|
DEFAULT_ENV_PREFIX = "LIBRETIME"
|
||||||
DEFAULT_CONFIG_FILEPATH = Path("/etc/libretime/config.yml")
|
DEFAULT_CONFIG_FILEPATH = Path("/etc/libretime/config.yml")
|
||||||
|
|
||||||
|
|
|
@ -1,127 +1,38 @@
|
||||||
import sys
|
import logging
|
||||||
from copy import deepcopy
|
from logging.handlers import TimedRotatingFileHandler
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, NamedTuple, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
from loguru import logger
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from loguru import Logger
|
|
||||||
|
|
||||||
logger.remove()
|
|
||||||
|
|
||||||
|
|
||||||
class LogLevel(NamedTuple):
|
|
||||||
name: str
|
|
||||||
no: int
|
|
||||||
|
|
||||||
def is_debug(self) -> bool:
|
|
||||||
return self.no <= 10
|
|
||||||
|
|
||||||
|
|
||||||
# See https://loguru.readthedocs.io/en/stable/api/logger.html#levels
|
|
||||||
ERROR = LogLevel(name="error", no=40)
|
|
||||||
WARNING = LogLevel(name="warning", no=30)
|
|
||||||
INFO = LogLevel(name="info", no=20)
|
|
||||||
DEBUG = LogLevel(name="debug", no=10)
|
|
||||||
TRACE = LogLevel(name="trace", no=5)
|
|
||||||
|
|
||||||
LOG_LEVEL_MAP = {
|
|
||||||
ERROR.name: ERROR,
|
|
||||||
WARNING.name: WARNING,
|
|
||||||
INFO.name: INFO,
|
|
||||||
DEBUG.name: DEBUG,
|
|
||||||
TRACE.name: TRACE,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def level_from_name(name: str) -> LogLevel:
|
|
||||||
"""
|
|
||||||
Find logging level, depending on the name provided.
|
|
||||||
|
|
||||||
:param name: name (one of "error", "warning", "info", "debug", "trace") of the log level
|
|
||||||
:returns: log level guessed from the name
|
|
||||||
:raises ValueError: on invalid level name
|
|
||||||
"""
|
|
||||||
name = name.lower()
|
|
||||||
if name not in LOG_LEVEL_MAP:
|
|
||||||
raise ValueError(f"invalid level name '{name}'")
|
|
||||||
return LOG_LEVEL_MAP[name]
|
|
||||||
|
|
||||||
|
|
||||||
def setup_logger(
|
def setup_logger(
|
||||||
level: LogLevel,
|
level: str,
|
||||||
filepath: Optional[Path] = None,
|
filepath: Optional[Path] = None,
|
||||||
serialize: bool = False,
|
serialize: bool = False, # pylint: disable=unused-argument
|
||||||
rotate: bool = True,
|
rotate: bool = True,
|
||||||
) -> Tuple[LogLevel, Optional[Path]]:
|
) -> Tuple[str, Optional[Path]]:
|
||||||
"""
|
"""
|
||||||
Configure the logger and return the computed log level.
|
Configure the logger and return the log level and log filepath.
|
||||||
|
|
||||||
See https://loguru.readthedocs.io/en/stable/overview.html
|
|
||||||
|
|
||||||
:param verbosity: verbosity (between -1 and 3) of the logger
|
|
||||||
:param filepath: write logs to filepath
|
|
||||||
:param serialize: generate JSON formatted log records
|
|
||||||
:param rotate: enable log rotation and retention
|
|
||||||
:returns: log level guessed from the verbosity
|
|
||||||
"""
|
"""
|
||||||
handlers = [{"sink": sys.stderr, "level": level.no, "serialize": serialize}]
|
level = level.upper()
|
||||||
|
|
||||||
|
root = logging.getLogger()
|
||||||
|
root.setLevel(level)
|
||||||
|
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
"%(asctime)s | %(levelname)-8s | %(name)s:%(funcName)s:%(lineno)s - %(message)s"
|
||||||
|
)
|
||||||
|
handlers: List[logging.Handler] = [logging.StreamHandler()]
|
||||||
|
|
||||||
if filepath is not None:
|
if filepath is not None:
|
||||||
file_handler = {
|
|
||||||
"sink": filepath,
|
|
||||||
"enqueue": True,
|
|
||||||
"level": level.no,
|
|
||||||
"serialize": serialize,
|
|
||||||
"encoding": "utf-8",
|
|
||||||
}
|
|
||||||
if rotate:
|
if rotate:
|
||||||
file_handler.update(
|
handlers.append(TimedRotatingFileHandler(filepath, when="midnight"))
|
||||||
{
|
else:
|
||||||
"rotation": "12:00",
|
handlers.append(logging.FileHandler(filepath))
|
||||||
"retention": "7 days",
|
|
||||||
"compression": "gz",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
handlers.append(file_handler)
|
for handler in handlers:
|
||||||
|
handler.setFormatter(formatter)
|
||||||
logger.configure(handlers=handlers)
|
root.addHandler(handler)
|
||||||
|
|
||||||
return level, filepath
|
return level, filepath
|
||||||
|
|
||||||
|
|
||||||
_empty_logger = deepcopy(logger)
|
|
||||||
|
|
||||||
|
|
||||||
def create_task_logger(
|
|
||||||
level: LogLevel,
|
|
||||||
filepath: Path,
|
|
||||||
serialize: bool = False,
|
|
||||||
) -> "Logger":
|
|
||||||
"""
|
|
||||||
Create and configure an independent logger for a task, return the new logger.
|
|
||||||
|
|
||||||
See #creating-independent-loggers-with-separate-set-of-handlers in
|
|
||||||
https://loguru.readthedocs.io/en/stable/resources/recipes.html
|
|
||||||
|
|
||||||
:returns: new logger
|
|
||||||
"""
|
|
||||||
task_logger = deepcopy(_empty_logger)
|
|
||||||
|
|
||||||
task_logger.configure(
|
|
||||||
handlers=[
|
|
||||||
{
|
|
||||||
"sink": filepath,
|
|
||||||
"enqueue": True,
|
|
||||||
"level": level.no,
|
|
||||||
"serialize": serialize,
|
|
||||||
"rotation": "12:00",
|
|
||||||
"retention": "7 days",
|
|
||||||
"encoding": "utf-8",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
return task_logger
|
|
||||||
|
|
|
@ -2,6 +2,5 @@
|
||||||
# This file is auto-generated by tools/extract_requirements.py.
|
# This file is auto-generated by tools/extract_requirements.py.
|
||||||
backports.zoneinfo>=0.2.1,<0.3;python_version<'3.9'
|
backports.zoneinfo>=0.2.1,<0.3;python_version<'3.9'
|
||||||
click>=8.0.4,<8.2
|
click>=8.0.4,<8.2
|
||||||
loguru==0.6.0
|
|
||||||
pydantic>=1.7.4,<1.11
|
pydantic>=1.7.4,<1.11
|
||||||
pyyaml>=5.3.1,<6.1
|
pyyaml>=5.3.1,<6.1
|
||||||
|
|
|
@ -12,7 +12,6 @@ setup(
|
||||||
install_requires=[
|
install_requires=[
|
||||||
"backports.zoneinfo>=0.2.1,<0.3;python_version<'3.9'",
|
"backports.zoneinfo>=0.2.1,<0.3;python_version<'3.9'",
|
||||||
"click>=8.0.4,<8.2",
|
"click>=8.0.4,<8.2",
|
||||||
"loguru==0.6.0",
|
|
||||||
"pydantic>=1.7.4,<1.11",
|
"pydantic>=1.7.4,<1.11",
|
||||||
"pyyaml>=5.3.1,<6.1",
|
"pyyaml>=5.3.1,<6.1",
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from libretime_shared.logging import (
|
|
||||||
DEBUG,
|
|
||||||
INFO,
|
|
||||||
create_task_logger,
|
|
||||||
level_from_name,
|
|
||||||
setup_logger,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"name,level_name,level_no",
|
|
||||||
[
|
|
||||||
("error", "error", 40),
|
|
||||||
("warning", "warning", 30),
|
|
||||||
("info", "info", 20),
|
|
||||||
("debug", "debug", 10),
|
|
||||||
("trace", "trace", 5),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_level_from_name(name, level_name, level_no):
|
|
||||||
level = level_from_name(name)
|
|
||||||
assert level.name == level_name
|
|
||||||
assert level.no == level_no
|
|
||||||
|
|
||||||
|
|
||||||
def test_level_from_name_invalid():
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
level_from_name("invalid")
|
|
||||||
|
|
||||||
|
|
||||||
def test_setup_logger(tmp_path: Path):
|
|
||||||
log_filepath = tmp_path / "test.log"
|
|
||||||
extra_log_filepath = tmp_path / "extra.log"
|
|
||||||
|
|
||||||
setup_logger(INFO, log_filepath)
|
|
||||||
|
|
||||||
extra_logger = create_task_logger(DEBUG, extra_log_filepath, True)
|
|
||||||
|
|
||||||
logger.info("test info")
|
|
||||||
extra_logger.info("extra info")
|
|
||||||
logger.debug("test debug")
|
|
||||||
|
|
||||||
extra_logger.complete()
|
|
||||||
logger.complete()
|
|
||||||
|
|
||||||
assert len(log_filepath.read_text(encoding="utf-8").splitlines()) == 1
|
|
||||||
assert len(extra_log_filepath.read_text(encoding="utf-8").splitlines()) == 1
|
|
Loading…
Reference in New Issue