Skip to content

Commit

Permalink
envoy.base.runner: Fix verbosity and logging (#166)
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Northey <ryan@synca.io>
  • Loading branch information
phlax authored Jan 11, 2022
1 parent 39aedca commit 983ec58
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 103 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pypi: https://pypi.org/project/envoy.base.checker

#### [envoy.base.runner](envoy.base.runner)

version: 0.0.5.dev0
version: 0.1.0

pypi: https://pypi.org/project/envoy.base.runner

Expand Down
2 changes: 1 addition & 1 deletion envoy.base.runner/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.5-dev
0.1.0
6 changes: 3 additions & 3 deletions envoy.base.runner/envoy/base/runner/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@

from . import runner
from .decorators import (
catches,
cleansup)

from .abstract import AAsyncRunnerWithCommands

from .runner import (
AsyncRunner,
BaseRunner,
Expand All @@ -27,4 +26,5 @@
"cleansup",
"ForkingAdapter",
"ForkingRunner",
"Runner")
"Runner",
"runner")
112 changes: 83 additions & 29 deletions envoy.base.runner/envoy/base/runner/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,29 @@ class BazelRunError(Exception):
pass


class BaseLogFilter(logging.Filter):

def __init__(self, app_logger: logging.Logger, *args, **kwargs) -> None:
self.app_logger = app_logger


class AppLogFilter(BaseLogFilter):

def filter(self, record) -> bool:
return record.name == self.app_logger.name


class RootLogFilter(BaseLogFilter):

def filter(self, record) -> bool:
return record.name != self.app_logger.name


class BaseRunner:

def __init__(self, *args):
self._args = args

def __call__(self):
return self.run()
self.setup_logging()

@cached_property
def args(self) -> argparse.Namespace:
Expand All @@ -63,38 +79,36 @@ def extra_args(self) -> list:
"""Unparsed args."""
return self.parser.parse_known_args(self._args)[1]

@property
def log_field_styles(self):
return LOG_FIELD_STYLES

@property
def log_fmt(self):
return LOG_FMT

@property
def log_level_styles(self):
return LOG_LEVEL_STYLES

@cached_property
def log(self) -> verboselogs.VerboseLogger:
"""Instantiated logger."""
verboselogs.install()
logger = logging.getLogger(self.name)
logger.setLevel(self.log_level)
app_logger = verboselogs.VerboseLogger(self.name)
coloredlogs.install(
field_styles=self.log_field_styles,
level_styles=self.log_level_styles,
fmt=self.log_fmt,
level='DEBUG',
logger=logger,
level=self.verbosity,
logger=app_logger,
isatty=True)
return logger
return app_logger

@property
def log_field_styles(self):
return LOG_FIELD_STYLES

@property
def log_fmt(self):
return LOG_FMT

@cached_property
def log_level(self) -> int:
"""Log level parsed from args."""
return dict(LOG_LEVELS)[self.args.log_level]

@property
def log_level_styles(self):
return LOG_LEVEL_STYLES

@property
def name(self) -> str:
"""Name of the runner."""
Expand All @@ -111,6 +125,27 @@ def parser(self) -> argparse.ArgumentParser:
def path(self) -> pathlib.Path:
return pathlib.Path(".")

@property
def root_log_format(self) -> logging.Formatter:
return logging.Formatter("%(name)s: %(levelname)s %(message)s")

@cached_property
def root_log_handler(self) -> logging.Handler:
"""Instantiated logger."""
root_handler = logging.StreamHandler()
root_handler.setLevel(self.log_level)
root_handler.addFilter(RootLogFilter(self.log))
root_handler.setFormatter(self.root_log_format)
return root_handler

@cached_property
def root_logger(self) -> logging.Logger:
"""Instantiated logger."""
root_logger = logging.getLogger()
root_logger.handlers[0].addFilter(AppLogFilter(self.log))
root_logger.addHandler(self.root_log_handler)
return root_logger

@cached_property
def stdout(self) -> logging.Logger:
"""Log to stdout."""
Expand All @@ -134,14 +169,10 @@ def tempdir(self) -> tempfile.TemporaryDirectory:
"decorated with `@runner.cleansup`")
return tempfile.TemporaryDirectory()

def add_arguments(self, parser: argparse.ArgumentParser) -> None:
"""Override this method to add custom arguments to the arg parser."""
parser.add_argument(
"--log-level",
"-l",
choices=[level[0] for level in LOG_LEVELS],
default="info",
help="Log level to display")
@cached_property
def verbosity(self) -> int:
"""Log level parsed from args."""
return dict(LOG_LEVELS)[self.args.verbosity]

@property
def _missing_cleanup(self) -> bool:
Expand All @@ -152,6 +183,26 @@ def _missing_cleanup(self) -> bool:
getattr(run_fun, "__wrapped__", object()),
"__cleansup__", False))

def add_arguments(self, parser: argparse.ArgumentParser) -> None:
"""Override this method to add custom arguments to the arg parser."""
parser.add_argument(
"--verbosity",
"-v",
choices=[level[0] for level in LOG_LEVELS],
default="info",
help="Application log level")
parser.add_argument(
"--log-level",
"-l",
choices=[level[0] for level in LOG_LEVELS],
default="warn",
help="Log level for non-application logs")

def setup_logging(self):
logging.basicConfig(level=self.log_level)
self.root_logger.setLevel(self.log_level)
self.log.setLevel(self.verbosity)

def _cleanup_tempdir(self) -> None:
if "tempdir" in self.__dict__:
self.tempdir.cleanup()
Expand All @@ -160,6 +211,9 @@ def _cleanup_tempdir(self) -> None:

class Runner(BaseRunner):

def __call__(self) -> Optional[int]:
return self.run()

@cleansup
def run(self) -> Optional[int]:
raise NotImplementedError
Expand Down
3 changes: 3 additions & 0 deletions envoy.base.runner/tests/test_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
@abstracts.implementer(AAsyncRunnerWithCommands)
class DummyAsyncRunnerWithCommands:

def __init__(self):
pass

@property
def command(self):
return super().command
Expand Down
Loading

0 comments on commit 983ec58

Please sign in to comment.