mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
revamp logging
This commit is contained in:
@@ -6,7 +6,6 @@ import copy
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
# Third Party
|
||||
import yaml
|
||||
@@ -14,10 +13,15 @@ from aiofile import AIOFile
|
||||
from pydantic import ValidationError
|
||||
|
||||
# Project
|
||||
from hyperglass.util import log, check_path, set_app_path
|
||||
from hyperglass.log import (
|
||||
log,
|
||||
set_log_level,
|
||||
enable_file_logging,
|
||||
enable_syslog_logging,
|
||||
)
|
||||
from hyperglass.util import check_path, set_app_path
|
||||
from hyperglass.constants import (
|
||||
CREDIT,
|
||||
LOG_HANDLER,
|
||||
DEFAULT_HELP,
|
||||
DEFAULT_TERMS,
|
||||
DEFAULT_DETAILS,
|
||||
@@ -82,66 +86,6 @@ STATIC_PATH = CONFIG_PATH / "static"
|
||||
CONFIG_MAIN, CONFIG_DEVICES, CONFIG_COMMANDS = _check_config_files(CONFIG_PATH)
|
||||
|
||||
|
||||
def _set_log_level(debug):
|
||||
"""Set log level based on debug state.
|
||||
|
||||
Arguments:
|
||||
debug {bool} -- Debug state from config file
|
||||
|
||||
Returns:
|
||||
{bool} -- True
|
||||
"""
|
||||
stdout_handler = LOG_HANDLER.copy()
|
||||
|
||||
if debug:
|
||||
log_level = "DEBUG"
|
||||
stdout_handler["level"] = log_level
|
||||
os.environ["HYPERGLASS_LOG_LEVEL"] = log_level
|
||||
log.configure(handlers=[stdout_handler])
|
||||
|
||||
if debug:
|
||||
log.debug("Debugging enabled")
|
||||
return True
|
||||
|
||||
|
||||
def _set_file_logging(log_directory, log_format, log_max_size):
|
||||
"""Set up file-based logging from configuration parameters."""
|
||||
|
||||
if log_format == "json":
|
||||
log_file_name = "hyperglass_log.json"
|
||||
structured = True
|
||||
else:
|
||||
log_file_name = "hyperglass_log.log"
|
||||
structured = False
|
||||
|
||||
log_file = log_directory / log_file_name
|
||||
|
||||
if log_format == "text":
|
||||
now_str = "hyperglass logs for " + datetime.utcnow().strftime(
|
||||
"%B %d, %Y beginning at %H:%M:%S UTC"
|
||||
)
|
||||
now_str_y = len(now_str) + 6
|
||||
now_str_x = len(now_str) + 4
|
||||
log_break = (
|
||||
"#" * now_str_y,
|
||||
"\n#" + " " * now_str_x + "#\n",
|
||||
"# ",
|
||||
now_str,
|
||||
" #",
|
||||
"\n#" + " " * now_str_x + "#\n",
|
||||
"#" * now_str_y,
|
||||
)
|
||||
|
||||
with log_file.open("a+") as lf:
|
||||
lf.write(f'\n\n{"".join(log_break)}\n\n')
|
||||
|
||||
log.add(log_file, rotation=log_max_size, serialize=structured)
|
||||
|
||||
log.debug("Logging to file enabled")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _config_required(config_path: Path) -> dict:
|
||||
try:
|
||||
with config_path.open("r") as cf:
|
||||
@@ -224,11 +168,8 @@ async def _config_devices():
|
||||
|
||||
user_config = _config_optional(CONFIG_MAIN)
|
||||
|
||||
# Logging Config
|
||||
_debug = user_config.get("debug", True)
|
||||
|
||||
# Read raw debug value from config to enable debugging quickly.
|
||||
_set_log_level(_debug)
|
||||
set_log_level(logger=log, debug=user_config.get("debug", True))
|
||||
|
||||
_user_commands = _config_optional(CONFIG_COMMANDS)
|
||||
_user_devices = _config_required(CONFIG_DEVICES)
|
||||
@@ -247,13 +188,25 @@ except ValidationError as validation_errors:
|
||||
error_msg=error["msg"],
|
||||
)
|
||||
|
||||
# Re-evaluate debug state after config is validated
|
||||
set_log_level(logger=log, debug=params.debug)
|
||||
|
||||
# Set up file logging once configuration parameters are initialized.
|
||||
_set_file_logging(
|
||||
log_directory=params.log_directory,
|
||||
log_format=params.log_format,
|
||||
log_max_size=params.log_max_size,
|
||||
enable_file_logging(
|
||||
logger=log,
|
||||
log_directory=params.logging.directory,
|
||||
log_format=params.logging.format,
|
||||
log_max_size=params.logging.max_size,
|
||||
)
|
||||
|
||||
# Set up syslog logging if enabled.
|
||||
if params.logging.syslog is not None and params.logging.syslog.enable:
|
||||
enable_syslog_logging(
|
||||
logger=log,
|
||||
syslog_host=params.logging.syslog.host,
|
||||
syslog_port=params.logging.syslog.port,
|
||||
)
|
||||
|
||||
# Perform post-config initialization string formatting or other
|
||||
# functions that require access to other config levels. E.g.,
|
||||
# something in 'params.web.text' needs to be formatted with a value
|
||||
@@ -288,10 +241,6 @@ except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
# Re-evaluate debug state after config is validated
|
||||
_set_log_level(params.debug)
|
||||
|
||||
|
||||
def _build_frontend_networks():
|
||||
"""Build filtered JSON structure of networks for frontend.
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"""Markdown processing utility functions."""
|
||||
|
||||
# Project
|
||||
from hyperglass.util import log
|
||||
from hyperglass.log import log
|
||||
|
||||
|
||||
def _get_file(path_obj):
|
||||
|
28
hyperglass/configuration/models/logging.py
Normal file
28
hyperglass/configuration/models/logging.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""Validate logging configuration."""
|
||||
|
||||
# Standard Library
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
|
||||
# Third Party
|
||||
from pydantic import ByteSize, StrictInt, StrictStr, StrictBool, DirectoryPath, constr
|
||||
|
||||
# Project
|
||||
from hyperglass.configuration.models._utils import HyperglassModel
|
||||
|
||||
|
||||
class Syslog(HyperglassModel):
|
||||
"""Validation model for syslog configuration."""
|
||||
|
||||
enable: StrictBool = True
|
||||
host: StrictStr
|
||||
port: StrictInt = 514
|
||||
|
||||
|
||||
class Logging(HyperglassModel):
|
||||
"""Validation model for logging configuration."""
|
||||
|
||||
directory: DirectoryPath = Path("/tmp") # noqa: S108
|
||||
format: constr(regex=r"(text|json)") = "text"
|
||||
syslog: Optional[Syslog]
|
||||
max_size: ByteSize = "50MB"
|
@@ -1,11 +1,9 @@
|
||||
"""Validate error message configuration variables."""
|
||||
|
||||
# Third Party
|
||||
# Third Party Imports
|
||||
from pydantic import Field, StrictStr
|
||||
|
||||
# Project
|
||||
# Project Imports
|
||||
from hyperglass.configuration.models._utils import HyperglassModel
|
||||
|
||||
|
||||
|
@@ -2,17 +2,14 @@
|
||||
|
||||
# Standard Library
|
||||
from typing import List, Union, Optional
|
||||
from pathlib import Path
|
||||
from ipaddress import ip_address
|
||||
|
||||
# Third Party
|
||||
from pydantic import (
|
||||
Field,
|
||||
ByteSize,
|
||||
StrictInt,
|
||||
StrictStr,
|
||||
StrictBool,
|
||||
DirectoryPath,
|
||||
IPvAnyAddress,
|
||||
constr,
|
||||
validator,
|
||||
@@ -23,6 +20,7 @@ from hyperglass.configuration.models.web import Web
|
||||
from hyperglass.configuration.models.docs import Docs
|
||||
from hyperglass.configuration.models.cache import Cache
|
||||
from hyperglass.configuration.models._utils import IntFloat, HyperglassModel
|
||||
from hyperglass.configuration.models.logging import Logging
|
||||
from hyperglass.configuration.models.queries import Queries
|
||||
from hyperglass.configuration.models.messages import Messages
|
||||
|
||||
@@ -98,19 +96,6 @@ class Params(HyperglassModel):
|
||||
title="Listen Port",
|
||||
description="Local TCP port the hyperglass application listens on to serve web traffic.",
|
||||
)
|
||||
log_directory: DirectoryPath = Field(
|
||||
Path("/tmp"), # noqa: S108
|
||||
title="Log Directory",
|
||||
description="Path to a directory, to which hyperglass can write logs. If none is set, hyperglass will write logs to a file located at `/tmp/`, with a uniquely generated name for each time hyperglass is started.",
|
||||
)
|
||||
log_format: constr(regex=r"(text|json)") = Field(
|
||||
"text", title="Log Format", description="Format for logs written to a file."
|
||||
)
|
||||
log_max_size: ByteSize = Field(
|
||||
"50MB",
|
||||
title="Maximum Log File Size",
|
||||
description="Maximum storage space log file may consume.",
|
||||
)
|
||||
cors_origins: List[StrictStr] = Field(
|
||||
[],
|
||||
title="Cross-Origin Resource Sharing",
|
||||
@@ -125,6 +110,7 @@ class Params(HyperglassModel):
|
||||
# Sub Level Params
|
||||
cache: Cache = Cache()
|
||||
docs: Docs = Docs()
|
||||
logging: Logging = Logging()
|
||||
messages: Messages = Messages()
|
||||
queries: Queries = Queries()
|
||||
web: Web = Web()
|
||||
|
@@ -10,7 +10,8 @@ from pathlib import Path
|
||||
from pydantic import StrictInt, StrictStr, validator
|
||||
|
||||
# Project
|
||||
from hyperglass.util import log, clean_name
|
||||
from hyperglass.log import log
|
||||
from hyperglass.util import clean_name
|
||||
from hyperglass.constants import SCRAPE_HELPERS, TRANSPORT_REST, TRANSPORT_SCRAPE
|
||||
from hyperglass.exceptions import ConfigError, UnsupportedDevice
|
||||
from hyperglass.configuration.models.ssl import Ssl
|
||||
|
Reference in New Issue
Block a user