1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 11:34:18 +00:00

Better colored logging

This commit is contained in:
Steffo 2019-11-24 16:02:32 +01:00
parent 075fb262cc
commit 4e16e3ee7a
11 changed files with 127 additions and 40 deletions

View file

@ -2,6 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/docs_source/royalpack" vcs="Git" />
</component>
</project>

View file

@ -53,10 +53,10 @@ def run(telegram: typing.Optional[bool],
royalnet_log.setLevel(log_level)
stream_handler = StreamHandler()
if coloredlogs is not None:
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t|"
" {message}", style="{")
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
else:
stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}",
stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready")
@ -96,8 +96,12 @@ def run(telegram: typing.Optional[bool],
secret=get_secret("herald"),
secure=False,
path="/")
herald_kwargs = {
"log_level": log_level
}
herald_process = multiprocessing.Process(name="Herald Server",
target=r.herald.Server(config=herald_config).run_blocking,
kwargs=herald_kwargs,
daemon=True)
herald_process.start()
else:

View file

@ -1,10 +1,20 @@
# Imports go here!
from .version import VersionCommand
from .exception import ExceptionCommand
from .excevent import ExceventCommand
# Enter the commands of your Pack here!
available_commands = [
VersionCommand,
]
# noinspection PyUnreachableCode
if __debug__:
available_commands = [
*available_commands,
ExceptionCommand,
ExceventCommand,
]
# Don't change this, it should automatically generate __all__
__all__ = [command.__name__ for command in available_commands]

View file

@ -0,0 +1,11 @@
import royalnet
from royalnet.commands import *
class ExceptionCommand(Command):
name: str = "exception"
description: str = "Raise an exception in the command."
async def run(self, args: CommandArgs, data: CommandData) -> None:
raise Exception(f"{self.interface.prefix}{self.name} was called")

View file

@ -0,0 +1,12 @@
import royalnet
from royalnet.commands import *
class ExceventCommand(Command):
name: str = "excevent"
description: str = "Call an event that raises an exception."
async def run(self, args: CommandArgs, data: CommandData) -> None:
await self.interface.call_herald_event(self.interface.name, "exception")
await data.reply("✅ Event called!")

View file

@ -5,10 +5,14 @@ from royalnet.commands import *
class VersionCommand(Command):
name: str = "version"
description: str = "Get the current Royalnet version."
description: str = "Display the current Royalnet version."
async def run(self, args: CommandArgs, data: CommandData) -> None:
message = f" Royalnet {royalnet.__version__}\n"
# noinspection PyUnreachableCode
if __debug__:
message = f" Royalnet {royalnet.__version__} (debug)\n"
else:
message = f" Royalnet {royalnet.__version__}\n"
if "69" in message:
message += "(Nice.)"
await data.reply(message)

View file

@ -1,10 +1,14 @@
# Imports go here!
from .exception import ExceptionEvent
# Enter the commands of your Pack here!
available_events = [
]
# noinspection PyUnreachableCode
if __debug__:
available_events.append(ExceptionEvent)
# Don't change this, it should automatically generate __all__
__all__ = [command.__name__ for command in available_events]

View file

@ -0,0 +1,8 @@
from royalnet.commands import *
class ExceptionEvent(Event):
name = "exception"
def run(self, **kwargs):
raise Exception(f"{self.name} event was called")

View file

@ -142,14 +142,14 @@ class Constellation:
royalnet_log.setLevel(log_level)
stream_handler = logging.StreamHandler()
if coloredlogs is not None:
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {levelname}\t|"
" {name}\t| {message}", style="{")
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
else:
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}",
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
if len(royalnet_log.handlers) < 1:
royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready")
log.debug("Logging: ready")
# Initialize Sentry on the process
if sentry_sdk is None:
@ -172,7 +172,7 @@ class Constellation:
release=release)
log.info(f"Sentry: enabled (Royalnet {release})")
# Run the server
log.info(f"Running Constellation on https://{address}:{port}/ ...")
log.info(f"Running Constellation on https://{address}:{port}/...")
constellation.running = True
try:
uvicorn.run(constellation.starlette, host=address, port=port, log_config=UVICORN_LOGGING_CONFIG)

View file

@ -1,3 +1,4 @@
import logging
import typing
import re
import datetime
@ -7,6 +8,11 @@ import logging as _logging
from .package import Package
from .config import Config
try:
import coloredlogs
except ImportError:
coloredlogs = None
try:
import websockets
except ImportError:
@ -144,7 +150,10 @@ class Server:
if self.config.secure:
raise Exception("Secure servers aren't supported yet")
log.debug(f"Serving on {self.config.url}")
self.loop.run_until_complete(self.run())
try:
self.loop.run_until_complete(self.run())
except OSError as e:
log.fatal(f"OSError: {e}")
self.loop.run_forever()
async def run(self):
@ -153,7 +162,20 @@ class Server:
port=self.config.port,
loop=self.loop)
def run_blocking(self):
def run_blocking(self, log_level):
# Initialize logging, as Windows doesn't have fork
royalnet_log: logging.Logger = logging.getLogger("royalnet")
royalnet_log.setLevel(log_level)
stream_handler = logging.StreamHandler()
if coloredlogs is not None:
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
else:
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
if len(royalnet_log.handlers) < 1:
royalnet_log.addHandler(stream_handler)
log.debug("Logging: ready")
if self.loop is None:
self.loop = asyncio.get_event_loop()
self.serve()

View file

@ -1,4 +1,6 @@
import logging
import sys
import traceback
from asyncio import Task, AbstractEventLoop, get_event_loop
from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set
from keyring import get_password
@ -161,22 +163,25 @@ class Serf:
request: Request = Request(handler=event_name, data=kwargs)
response: Response = await self.herald.request(destination=destination, request=request)
if isinstance(response, ResponseFailure):
# TODO: pretty sure there's a better way to do this
if response.extra_info["type"] == "CommandError":
raise CommandError(response.extra_info["message"])
elif response.extra_info["type"] == "UserError":
raise UserError(response.extra_info["message"])
elif response.extra_info["type"] == "InvalidInputError":
raise InvalidInputError(response.extra_info["message"])
elif response.extra_info["type"] == "UnsupportedError":
raise UnsupportedError(response.extra_info["message"])
elif response.extra_info["type"] == "ConfigurationError":
raise ConfigurationError(response.extra_info["message"])
elif response.extra_info["type"] == "ExternalError":
raise ExternalError(response.extra_info["message"])
else:
raise TypeError(f"Herald action call returned invalid error:\n"
f"[p]{response}[/p]")
if response.name == "no_event":
raise CommandError(f"There is no event named {event_name} in {destination}.")
elif response.name == "exception_in_event":
# TODO: pretty sure there's a better way to do this
if response.extra_info["type"] == "CommandError":
raise CommandError(response.extra_info["message"])
elif response.extra_info["type"] == "UserError":
raise UserError(response.extra_info["message"])
elif response.extra_info["type"] == "InvalidInputError":
raise InvalidInputError(response.extra_info["message"])
elif response.extra_info["type"] == "UnsupportedError":
raise UnsupportedError(response.extra_info["message"])
elif response.extra_info["type"] == "ConfigurationError":
raise ConfigurationError(response.extra_info["message"])
elif response.extra_info["type"] == "ExternalError":
raise ExternalError(response.extra_info["message"])
else:
raise TypeError(f"Herald action call returned invalid error:\n"
f"[p]{response}[/p]")
elif isinstance(response, ResponseSuccess):
return response.data
else:
@ -249,6 +254,7 @@ class Serf:
response_data = await event.run(**message.data)
return ResponseSuccess(data=response_data)
except Exception as e:
self.sentry_exc(e)
return ResponseFailure("exception_in_event",
f"An exception was raised in the event for '{message.handler}'.",
extra_info={
@ -273,11 +279,19 @@ class Serf:
release=release)
log.info(f"Sentry: enabled (Royalnet {release})")
# noinspection PyUnreachableCode
@staticmethod
def sentry_exc(exc: Exception):
def sentry_exc(exc: Exception,
level: str = "error"):
if sentry_sdk is not None:
sentry_sdk.capture_exception(exc)
log.error(f"Captured error: {exc}")
with sentry_sdk.configure_scope() as scope:
scope.set_level(level)
sentry_sdk.capture_exception(exc)
log.log(level, f"Captured {level}: {exc}")
# If started in debug mode (without -O), raise the exception, allowing you to see its source
if __debug__:
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback)
def get_secret(self, username: str):
"""Get a Royalnet secret from the keyring.
@ -325,14 +339,14 @@ class Serf:
royalnet_log.setLevel(log_level)
stream_handler = logging.StreamHandler()
if coloredlogs is not None:
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t|"
" {message}", style="{")
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
else:
stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}",
style="{")
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {name}\t| {message}",
style="{")
if len(royalnet_log.handlers) < 1:
royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready")
log.debug("Logging: ready")
if sentry_sdk is None:
log.info("Sentry: not installed")
@ -347,5 +361,4 @@ class Serf:
try:
serf.loop.run_until_complete(serf.run())
except Exception as e:
log.error(f"Uncaught exception: {e}")
serf.sentry_exc(e)
serf.sentry_exc(e, level="fatal")