Skip to content

Colored output (issues #65) #141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c6c700e
feat: implement color wrapper
lawrence910426 Mar 20, 2023
29d2cd5
feat: replace logging with colored printer
lawrence910426 Mar 20, 2023
1195fd3
fix: output to logging
lawrence910426 Mar 20, 2023
cf7209b
fix: stop output to stdout
lawrence910426 Mar 20, 2023
49f0153
Revert "fix: stop output to stdout"
lawrence910426 Mar 20, 2023
fc41871
fix: revert intercepting on sebs.py
lawrence910426 Mar 23, 2023
c9751e4
feat: move color to utils.py
lawrence910426 Mar 23, 2023
158b697
feat: miliseconds
lawrence910426 Mar 23, 2023
0242cef
feat: intercept @ logging base
lawrence910426 Mar 23, 2023
41763f6
fix: rename vars to avoid conflict
lawrence910426 Mar 23, 2023
b90d725
fix: remove legacy output
lawrence910426 Mar 25, 2023
39758cd
fix: legacy imports
lawrence910426 Mar 25, 2023
885b645
fix: wrong return type
lawrence910426 Mar 25, 2023
72bd7f3
fix: mypy precedence
lawrence910426 Mar 25, 2023
613a12d
fix: mypy precedence
lawrence910426 Mar 25, 2023
603d0d4
fix: change precedence of colored printer
lawrence910426 Mar 25, 2023
5cb813c
fix: define return signature
lawrence910426 Mar 25, 2023
16c8870
feat: colored wrapper
lawrence910426 Mar 25, 2023
2550432
Merge branch 'master' of https://github.com/lawrence910426/serverless…
lawrence910426 Mar 25, 2023
e724d08
fix: update to single handler
lawrence910426 Mar 25, 2023
1b7e399
fix: propagate only if file input exists
lawrence910426 Mar 25, 2023
b3ada3c
feat: metadata before main message
lawrence910426 Mar 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sebs.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def parse_common_params(

sebs_client = sebs.SeBS(cache, output_dir, verbose, logging_filename)
output_dir = sebs.utils.create_output(output_dir, preserve_out, verbose)

sebs_client.logging.info("Created experiment output at {}".format(output_dir))

# CLI overrides JSON options
Expand Down
86 changes: 71 additions & 15 deletions sebs/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import subprocess
import sys
import uuid
import click
import datetime

from typing import List, Optional, TextIO, Union

PROJECT_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir)
Expand Down Expand Up @@ -141,48 +144,101 @@ def global_logging():
logging_date_format = "%H:%M:%S"
logging.basicConfig(format=logging_format, datefmt=logging_date_format, level=logging.INFO)

class ColoredWrapper:
SUCCESS = "\033[92m"
STATUS = "\033[94m"
WARNING = "\033[93m"
ERROR = "\033[91m"
BOLD = "\033[1m"
END = "\033[0m"

def __init__(self, prefix, logger, verbose=True, propagte=False):
self.verbose = verbose
self.propagte = propagte
self.prefix = prefix
self._logging = logger

def debug(self, message):
if self.verbose:
self._print(message, ColoredWrapper.STATUS)
if self.propagte:
self._logging.debug(message)

def info(self, message):
self._print(message, ColoredWrapper.SUCCESS)
if self.propagte:
self._logging.info(message)

def warning(self, message):
self._print(message, ColoredWrapper.WARNING)
if self.propagte:
self._logging.warning(message)

def error(self, message):
self._print(message, ColoredWrapper.ERROR)
if self.propagte:
self._logging.error(message)

def critical(self, message):
self._print(message, ColoredWrapper.ERROR)
if self.propagte:
self._logging.critical(message)

def _print(self, message, color):
timestamp = datetime.datetime.now().strftime("%H:%M:%S.%f")
click.echo(f"{color}{ColoredWrapper.BOLD}[{timestamp}]{ColoredWrapper.END} {self.prefix} {message}")

class LoggingHandlers:
def __init__(self, verbose: bool = False, filename: Optional[str] = None):
logging_format = "%(asctime)s,%(msecs)d %(levelname)s %(name)s: %(message)s"
logging_date_format = "%H:%M:%S"
formatter = logging.Formatter(logging_format, logging_date_format)
self.handlers: List[Union[logging.FileHandler, logging.StreamHandler[TextIO]]] = []
self.handler: logging.FileHandler = None

# Add stdout output
if verbose:
stdout = logging.StreamHandler(sys.stdout)
stdout.setFormatter(formatter)
stdout.setLevel(logging.DEBUG if verbose else logging.INFO)
self.handlers.append(stdout)
# Remember verbosity for colored wrapper
self.verbosity = verbose

# Add file output if needed
if filename:
file_out = logging.FileHandler(filename=filename, mode="w")
file_out.setFormatter(formatter)
file_out.setLevel(logging.DEBUG if verbose else logging.INFO)
self.handlers.append(file_out)
self.handler = file_out


class LoggingBase:
def __init__(self):
uuid_name = str(uuid.uuid4())[0:4]
if hasattr(self, "typename"):
self.logging = logging.getLogger(f"{self.typename()}-{uuid_name}")
self.log_name = f"{self.typename()}-{uuid_name}"
else:
self.logging = logging.getLogger(f"{self.__class__.__name__}-{uuid_name}")
self.logging.setLevel(logging.INFO)
self.log_name = f"{self.__class__.__name__}-{uuid_name}"

self._logging = logging.getLogger(self.log_name)
self._logging.setLevel(logging.INFO)
self.wrapper = ColoredWrapper(self.log_name, self._logging)

@property
def logging(self) -> ColoredWrapper:
# This would always print log with color. And only if
# filename in LoggingHandlers is set, it would log to file.
return self.wrapper

@property
def logging_handlers(self) -> LoggingHandlers:
return self._logging_handlers

@logging_handlers.setter
def logging_handlers(self, handlers: LoggingHandlers):
self._logging_handlers = handlers
self.logging.propagate = False
for handler in handlers.handlers:
self.logging.addHandler(handler)

self._logging.propagate = False
self.wrapper = ColoredWrapper(self.log_name, self._logging,
verbose=handlers.verbosity,
propagte=handlers.handler is not None)

if self._logging_handlers.handler is not None:
self._logging.addHandler(self._logging_handlers.handler)


def has_platform(name: str) -> bool:
Expand All @@ -199,4 +255,4 @@ def handler(x, y):
traceback.print_stack()
sys.exit(signal.SIGINT)

signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGINT, handler)