mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Better colored logging
This commit is contained in:
parent
075fb262cc
commit
4e16e3ee7a
11 changed files with 127 additions and 40 deletions
|
@ -2,6 +2,5 @@
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/docs_source/royalpack" vcs="Git" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -53,10 +53,10 @@ def run(telegram: typing.Optional[bool],
|
||||||
royalnet_log.setLevel(log_level)
|
royalnet_log.setLevel(log_level)
|
||||||
stream_handler = StreamHandler()
|
stream_handler = StreamHandler()
|
||||||
if coloredlogs is not None:
|
if coloredlogs is not None:
|
||||||
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t|"
|
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
|
||||||
" {message}", style="{")
|
style="{")
|
||||||
else:
|
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="{")
|
style="{")
|
||||||
royalnet_log.addHandler(stream_handler)
|
royalnet_log.addHandler(stream_handler)
|
||||||
royalnet_log.debug("Logging: ready")
|
royalnet_log.debug("Logging: ready")
|
||||||
|
@ -96,8 +96,12 @@ def run(telegram: typing.Optional[bool],
|
||||||
secret=get_secret("herald"),
|
secret=get_secret("herald"),
|
||||||
secure=False,
|
secure=False,
|
||||||
path="/")
|
path="/")
|
||||||
|
herald_kwargs = {
|
||||||
|
"log_level": log_level
|
||||||
|
}
|
||||||
herald_process = multiprocessing.Process(name="Herald Server",
|
herald_process = multiprocessing.Process(name="Herald Server",
|
||||||
target=r.herald.Server(config=herald_config).run_blocking,
|
target=r.herald.Server(config=herald_config).run_blocking,
|
||||||
|
kwargs=herald_kwargs,
|
||||||
daemon=True)
|
daemon=True)
|
||||||
herald_process.start()
|
herald_process.start()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
# Imports go here!
|
# Imports go here!
|
||||||
from .version import VersionCommand
|
from .version import VersionCommand
|
||||||
|
from .exception import ExceptionCommand
|
||||||
|
from .excevent import ExceventCommand
|
||||||
|
|
||||||
# Enter the commands of your Pack here!
|
# Enter the commands of your Pack here!
|
||||||
available_commands = [
|
available_commands = [
|
||||||
VersionCommand,
|
VersionCommand,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# noinspection PyUnreachableCode
|
||||||
|
if __debug__:
|
||||||
|
available_commands = [
|
||||||
|
*available_commands,
|
||||||
|
ExceptionCommand,
|
||||||
|
ExceventCommand,
|
||||||
|
]
|
||||||
|
|
||||||
# Don't change this, it should automatically generate __all__
|
# Don't change this, it should automatically generate __all__
|
||||||
__all__ = [command.__name__ for command in available_commands]
|
__all__ = [command.__name__ for command in available_commands]
|
||||||
|
|
11
royalnet/backpack/commands/exception.py
Normal file
11
royalnet/backpack/commands/exception.py
Normal 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")
|
12
royalnet/backpack/commands/excevent.py
Normal file
12
royalnet/backpack/commands/excevent.py
Normal 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!")
|
|
@ -5,9 +5,13 @@ from royalnet.commands import *
|
||||||
class VersionCommand(Command):
|
class VersionCommand(Command):
|
||||||
name: str = "version"
|
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:
|
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||||
|
# noinspection PyUnreachableCode
|
||||||
|
if __debug__:
|
||||||
|
message = f"ℹ️ Royalnet {royalnet.__version__} (debug)\n"
|
||||||
|
else:
|
||||||
message = f"ℹ️ Royalnet {royalnet.__version__}\n"
|
message = f"ℹ️ Royalnet {royalnet.__version__}\n"
|
||||||
if "69" in message:
|
if "69" in message:
|
||||||
message += "(Nice.)"
|
message += "(Nice.)"
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
# Imports go here!
|
# Imports go here!
|
||||||
|
from .exception import ExceptionEvent
|
||||||
|
|
||||||
# Enter the commands of your Pack here!
|
# Enter the commands of your Pack here!
|
||||||
available_events = [
|
available_events = [
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# noinspection PyUnreachableCode
|
||||||
|
if __debug__:
|
||||||
|
available_events.append(ExceptionEvent)
|
||||||
|
|
||||||
# Don't change this, it should automatically generate __all__
|
# Don't change this, it should automatically generate __all__
|
||||||
__all__ = [command.__name__ for command in available_events]
|
__all__ = [command.__name__ for command in available_events]
|
||||||
|
|
8
royalnet/backpack/events/exception.py
Normal file
8
royalnet/backpack/events/exception.py
Normal 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")
|
|
@ -142,14 +142,14 @@ class Constellation:
|
||||||
royalnet_log.setLevel(log_level)
|
royalnet_log.setLevel(log_level)
|
||||||
stream_handler = logging.StreamHandler()
|
stream_handler = logging.StreamHandler()
|
||||||
if coloredlogs is not None:
|
if coloredlogs is not None:
|
||||||
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {levelname}\t|"
|
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
|
||||||
" {name}\t| {message}", style="{")
|
style="{")
|
||||||
else:
|
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="{")
|
style="{")
|
||||||
if len(royalnet_log.handlers) < 1:
|
if len(royalnet_log.handlers) < 1:
|
||||||
royalnet_log.addHandler(stream_handler)
|
royalnet_log.addHandler(stream_handler)
|
||||||
royalnet_log.debug("Logging: ready")
|
log.debug("Logging: ready")
|
||||||
|
|
||||||
# Initialize Sentry on the process
|
# Initialize Sentry on the process
|
||||||
if sentry_sdk is None:
|
if sentry_sdk is None:
|
||||||
|
@ -172,7 +172,7 @@ class Constellation:
|
||||||
release=release)
|
release=release)
|
||||||
log.info(f"Sentry: enabled (Royalnet {release})")
|
log.info(f"Sentry: enabled (Royalnet {release})")
|
||||||
# Run the server
|
# Run the server
|
||||||
log.info(f"Running Constellation on https://{address}:{port}/ ...")
|
log.info(f"Running Constellation on https://{address}:{port}/...")
|
||||||
constellation.running = True
|
constellation.running = True
|
||||||
try:
|
try:
|
||||||
uvicorn.run(constellation.starlette, host=address, port=port, log_config=UVICORN_LOGGING_CONFIG)
|
uvicorn.run(constellation.starlette, host=address, port=port, log_config=UVICORN_LOGGING_CONFIG)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import logging
|
||||||
import typing
|
import typing
|
||||||
import re
|
import re
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -7,6 +8,11 @@ import logging as _logging
|
||||||
from .package import Package
|
from .package import Package
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
|
||||||
|
try:
|
||||||
|
import coloredlogs
|
||||||
|
except ImportError:
|
||||||
|
coloredlogs = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import websockets
|
import websockets
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -144,7 +150,10 @@ class Server:
|
||||||
if self.config.secure:
|
if self.config.secure:
|
||||||
raise Exception("Secure servers aren't supported yet")
|
raise Exception("Secure servers aren't supported yet")
|
||||||
log.debug(f"Serving on {self.config.url}")
|
log.debug(f"Serving on {self.config.url}")
|
||||||
|
try:
|
||||||
self.loop.run_until_complete(self.run())
|
self.loop.run_until_complete(self.run())
|
||||||
|
except OSError as e:
|
||||||
|
log.fatal(f"OSError: {e}")
|
||||||
self.loop.run_forever()
|
self.loop.run_forever()
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
|
@ -153,7 +162,20 @@ class Server:
|
||||||
port=self.config.port,
|
port=self.config.port,
|
||||||
loop=self.loop)
|
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:
|
if self.loop is None:
|
||||||
self.loop = asyncio.get_event_loop()
|
self.loop = asyncio.get_event_loop()
|
||||||
self.serve()
|
self.serve()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
from asyncio import Task, AbstractEventLoop, get_event_loop
|
from asyncio import Task, AbstractEventLoop, get_event_loop
|
||||||
from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set
|
from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set
|
||||||
from keyring import get_password
|
from keyring import get_password
|
||||||
|
@ -161,6 +163,9 @@ class Serf:
|
||||||
request: Request = Request(handler=event_name, data=kwargs)
|
request: Request = Request(handler=event_name, data=kwargs)
|
||||||
response: Response = await self.herald.request(destination=destination, request=request)
|
response: Response = await self.herald.request(destination=destination, request=request)
|
||||||
if isinstance(response, ResponseFailure):
|
if isinstance(response, ResponseFailure):
|
||||||
|
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
|
# TODO: pretty sure there's a better way to do this
|
||||||
if response.extra_info["type"] == "CommandError":
|
if response.extra_info["type"] == "CommandError":
|
||||||
raise CommandError(response.extra_info["message"])
|
raise CommandError(response.extra_info["message"])
|
||||||
|
@ -249,6 +254,7 @@ class Serf:
|
||||||
response_data = await event.run(**message.data)
|
response_data = await event.run(**message.data)
|
||||||
return ResponseSuccess(data=response_data)
|
return ResponseSuccess(data=response_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
self.sentry_exc(e)
|
||||||
return ResponseFailure("exception_in_event",
|
return ResponseFailure("exception_in_event",
|
||||||
f"An exception was raised in the event for '{message.handler}'.",
|
f"An exception was raised in the event for '{message.handler}'.",
|
||||||
extra_info={
|
extra_info={
|
||||||
|
@ -273,11 +279,19 @@ class Serf:
|
||||||
release=release)
|
release=release)
|
||||||
log.info(f"Sentry: enabled (Royalnet {release})")
|
log.info(f"Sentry: enabled (Royalnet {release})")
|
||||||
|
|
||||||
|
# noinspection PyUnreachableCode
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sentry_exc(exc: Exception):
|
def sentry_exc(exc: Exception,
|
||||||
|
level: str = "error"):
|
||||||
if sentry_sdk is not None:
|
if sentry_sdk is not None:
|
||||||
|
with sentry_sdk.configure_scope() as scope:
|
||||||
|
scope.set_level(level)
|
||||||
sentry_sdk.capture_exception(exc)
|
sentry_sdk.capture_exception(exc)
|
||||||
log.error(f"Captured error: {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):
|
def get_secret(self, username: str):
|
||||||
"""Get a Royalnet secret from the keyring.
|
"""Get a Royalnet secret from the keyring.
|
||||||
|
@ -325,14 +339,14 @@ class Serf:
|
||||||
royalnet_log.setLevel(log_level)
|
royalnet_log.setLevel(log_level)
|
||||||
stream_handler = logging.StreamHandler()
|
stream_handler = logging.StreamHandler()
|
||||||
if coloredlogs is not None:
|
if coloredlogs is not None:
|
||||||
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t|"
|
stream_handler.formatter = coloredlogs.ColoredFormatter("{asctime}\t| {processName}\t| {name}\t| {message}",
|
||||||
" {message}", style="{")
|
style="{")
|
||||||
else:
|
else:
|
||||||
stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}",
|
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {name}\t| {message}",
|
||||||
style="{")
|
style="{")
|
||||||
if len(royalnet_log.handlers) < 1:
|
if len(royalnet_log.handlers) < 1:
|
||||||
royalnet_log.addHandler(stream_handler)
|
royalnet_log.addHandler(stream_handler)
|
||||||
royalnet_log.debug("Logging: ready")
|
log.debug("Logging: ready")
|
||||||
|
|
||||||
if sentry_sdk is None:
|
if sentry_sdk is None:
|
||||||
log.info("Sentry: not installed")
|
log.info("Sentry: not installed")
|
||||||
|
@ -347,5 +361,4 @@ class Serf:
|
||||||
try:
|
try:
|
||||||
serf.loop.run_until_complete(serf.run())
|
serf.loop.run_until_complete(serf.run())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"Uncaught exception: {e}")
|
serf.sentry_exc(e, level="fatal")
|
||||||
serf.sentry_exc(e)
|
|
||||||
|
|
Loading…
Reference in a new issue