mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-25 18:40:06 -04:00
Reworking and unifying log levels.
This commit is contained in:
parent
628b9f3096
commit
42f5607281
6 changed files with 89 additions and 18 deletions
|
|
@ -18,4 +18,5 @@ COPY wrolpi /opt/wrolpi/wrolpi
|
|||
COPY modules /opt/wrolpi/modules
|
||||
|
||||
ENTRYPOINT [ "python3", "-OO", "/opt/wrolpi/main.py"]
|
||||
CMD ["-v", "api", "--host", "0.0.0.0"]
|
||||
# Log level controlled by LOG_LEVEL env var or wrolpi.yaml config (default: info)
|
||||
CMD ["api", "--host", "0.0.0.0"]
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ from sqlalchemy.orm import Session
|
|||
from wrolpi.dates import now, from_timestamp
|
||||
from wrolpi.errors import WROLModeEnabled, NativeOnly, LogLevelError, InvalidConfig, \
|
||||
ValidationError
|
||||
from wrolpi.log_levels import TRACE_LEVEL, name_to_int as log_level_name_to_int, int_to_name as log_level_int_to_name
|
||||
from wrolpi.vars import PYTEST, DOCKERIZED, CONFIG_DIR, MEDIA_DIRECTORY, DEFAULT_HTTP_HEADERS
|
||||
|
||||
|
||||
|
|
@ -176,8 +177,7 @@ class TraceLogger(logging.Logger):
|
|||
logger: TraceLogger = logging.getLogger() # noqa Not really a TraceLogger, but I wanted IDE suggestions.
|
||||
logging.config.dictConfig(LOGGING_CONFIG)
|
||||
|
||||
# Add extra verbose debug level (-vvv)
|
||||
TRACE_LEVEL = logging.DEBUG - 5
|
||||
# Add extra verbose debug level (-vvv). TRACE_LEVEL imported from log_levels.
|
||||
if not hasattr(logging, 'TRACE'):
|
||||
add_logging_level('TRACE', TRACE_LEVEL)
|
||||
|
||||
|
|
@ -705,6 +705,7 @@ class WROLPiConfigValidator:
|
|||
hotspot_password: str = None
|
||||
hotspot_ssid: str = None
|
||||
ignore_outdated_zims: bool = None
|
||||
log_level: str = None
|
||||
map_destination: str = None
|
||||
nav_color: str = None
|
||||
throttle_on_startup: bool = None
|
||||
|
|
@ -769,6 +770,7 @@ class WROLPiConfig(ConfigFile):
|
|||
check_for_upgrades=True,
|
||||
ignore_outdated_zims=False,
|
||||
ignored_directories=['config', 'tags'],
|
||||
log_level='info',
|
||||
map_destination='map',
|
||||
nav_color='violet',
|
||||
throttle_on_startup=False,
|
||||
|
|
@ -877,6 +879,14 @@ class WROLPiConfig(ConfigFile):
|
|||
def ignore_outdated_zims(self, value: bool):
|
||||
self.update({'ignore_outdated_zims': value})
|
||||
|
||||
@property
|
||||
def log_level(self) -> str:
|
||||
return self._config.get('log_level', 'info')
|
||||
|
||||
@log_level.setter
|
||||
def log_level(self, value: str):
|
||||
self.update({'log_level': value})
|
||||
|
||||
@property
|
||||
def check_for_upgrades(self) -> bool:
|
||||
return self._config.get('check_for_upgrades', True)
|
||||
|
|
|
|||
|
|
@ -100,13 +100,9 @@ def test_session() -> Session:
|
|||
|
||||
@pytest.fixture(autouse=True)
|
||||
def test_debug_logger(request):
|
||||
"""The tests use debug logging by default. Use pytest's verbosity level if set."""
|
||||
level = logging.INFO
|
||||
verbose = request.config.option.verbose
|
||||
if verbose == 2:
|
||||
# -vv
|
||||
level = logging.DEBUG
|
||||
elif verbose == 3:
|
||||
"""Tests default to DEBUG logging. Use pytest -vvv for TRACE level."""
|
||||
level = logging.DEBUG
|
||||
if request.config.option.verbose >= 3:
|
||||
# -vvv
|
||||
level = TRACE_LEVEL
|
||||
|
||||
|
|
|
|||
65
wrolpi/log_levels.py
Normal file
65
wrolpi/log_levels.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
"""
|
||||
Log level utilities.
|
||||
|
||||
IMPORTANT: Keep this module minimal with NO imports from wrolpi to avoid circular imports.
|
||||
This module is imported very early by vars.py.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
TRACE_LEVEL = 5
|
||||
|
||||
LOG_LEVELS = {
|
||||
'critical': logging.CRITICAL,
|
||||
'warning': logging.WARNING,
|
||||
'info': logging.INFO,
|
||||
'debug': logging.DEBUG,
|
||||
'trace': TRACE_LEVEL,
|
||||
}
|
||||
|
||||
|
||||
def name_to_int(name: str) -> int:
|
||||
"""Convert log level name to integer. Defaults to INFO for invalid names."""
|
||||
return LOG_LEVELS.get(str(name).lower(), logging.INFO)
|
||||
|
||||
|
||||
def int_to_name(level: int) -> str:
|
||||
"""Convert log level integer to name. Defaults to 'info' for invalid levels."""
|
||||
for name, value in LOG_LEVELS.items():
|
||||
if value == level:
|
||||
return name
|
||||
return 'info'
|
||||
|
||||
|
||||
def get_log_level_from_env_or_config() -> int:
|
||||
"""
|
||||
Get log level from environment variable or config file.
|
||||
|
||||
Priority:
|
||||
1. LOG_LEVEL environment variable
|
||||
2. log_level in wrolpi.yaml config file
|
||||
3. Default to INFO
|
||||
|
||||
NOTE: CLI flags are handled separately by main.py argparse and take highest priority.
|
||||
This function is called during vars.py import (very early), before argparse runs.
|
||||
"""
|
||||
# 1. Environment variable (highest priority at this stage)
|
||||
if env_level := os.environ.get('LOG_LEVEL'):
|
||||
return name_to_int(env_level)
|
||||
|
||||
# 2. Config file
|
||||
try:
|
||||
import yaml
|
||||
media_dir = Path(os.environ.get('MEDIA_DIRECTORY', '/media/wrolpi'))
|
||||
config_path = media_dir / 'config/wrolpi.yaml'
|
||||
if config_path.is_file():
|
||||
with open(config_path) as f:
|
||||
config = yaml.safe_load(f)
|
||||
if config and 'log_level' in config:
|
||||
return name_to_int(config['log_level'])
|
||||
except Exception:
|
||||
pass # Config doesn't exist or is invalid, use default
|
||||
|
||||
# 3. Default
|
||||
return logging.INFO
|
||||
|
|
@ -24,7 +24,7 @@ from wrolpi.api_utils import json_response, api_app
|
|||
from wrolpi.collections.api import collection_bp
|
||||
from wrolpi.common import logger, get_wrolpi_config, wrol_mode_enabled, get_media_directory, \
|
||||
wrol_mode_check, native_only, disable_wrol_mode, enable_wrol_mode, get_global_statistics, url_strip_host, \
|
||||
set_global_log_level, get_relative_to_media_directory, search_other_estimates
|
||||
set_global_log_level, get_relative_to_media_directory, search_other_estimates, log_level_int_to_name
|
||||
from wrolpi.config_api import config_bp
|
||||
from wrolpi.dates import now
|
||||
from wrolpi.downloader import download_manager
|
||||
|
|
@ -232,6 +232,8 @@ async def update_settings(_: Request, body: schema.SettingsRequest):
|
|||
log_level = new_config.pop('log_level', None)
|
||||
if isinstance(log_level, int):
|
||||
set_global_log_level(log_level)
|
||||
# Persist log level to config
|
||||
wrolpi_config.log_level = log_level_int_to_name(log_level)
|
||||
|
||||
old_password = wrolpi_config.hotspot_password
|
||||
wrolpi_config.update(new_config)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import pathlib
|
||||
|
|
@ -45,12 +44,10 @@ def list_var(name: str, default='') -> List[str]:
|
|||
return [i for i in os.environ.get(name, default).split(',')]
|
||||
|
||||
|
||||
LOG_LEVEL_INT = logging.INFO
|
||||
if '-vv' in sys.argv:
|
||||
LOG_LEVEL_INT = logging.DEBUG
|
||||
elif '-vvv' in sys.argv:
|
||||
# SQLAlchemy will increase logging.
|
||||
LOG_LEVEL_INT = logging.DEBUG - 5
|
||||
from wrolpi.log_levels import get_log_level_from_env_or_config
|
||||
|
||||
# Get initial log level from ENV or config. CLI flags are handled by main.py argparse.
|
||||
LOG_LEVEL_INT = get_log_level_from_env_or_config()
|
||||
|
||||
# Special environment variable set in the docker/api/Dockerfile.
|
||||
DOCKERIZED = truthy_arg(os.environ.get('DOCKER', ''))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue