mirror of https://github.com/nucypher/nucypher.git
Hide registering/unregistering observers and Sentry init inside utilities/logging
Also add a check that Sentry SDK is only initialized oncepull/1124/head
parent
9bca91d97d
commit
b473c0f4bd
|
@ -3,13 +3,12 @@ import sys
|
|||
|
||||
import datetime
|
||||
import maya
|
||||
from twisted.logger import globalLogPublisher
|
||||
from umbral.keys import UmbralPublicKey
|
||||
|
||||
from nucypher.characters.lawful import Alice, Bob, Ursula
|
||||
from nucypher.characters.lawful import Enrico as Enrico
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.utilities.logging import SimpleObserver, GlobalConsoleLogger
|
||||
from nucypher.utilities.logging import GlobalLoggerSettings
|
||||
from nucypher.utilities.sandbox.constants import TEMPORARY_DOMAIN
|
||||
|
||||
######################
|
||||
|
@ -24,8 +23,8 @@ BOOK_PATH = os.path.join('.', 'finnegans-wake.txt')
|
|||
NUMBER_OF_LINES_TO_REENCRYPT = 25
|
||||
|
||||
# Twisted Logger
|
||||
globalLogPublisher.addObserver(SimpleObserver())
|
||||
GlobalConsoleLogger.set_log_level(log_level_name='debug')
|
||||
GlobalLoggerSettings.set_log_level(log_level_name='debug')
|
||||
GlobalLoggerSettings.start_console_logging()
|
||||
|
||||
|
||||
#######################################
|
||||
|
|
|
@ -5,11 +5,10 @@ import os
|
|||
import shutil
|
||||
|
||||
import maya
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.characters.lawful import Bob, Ursula
|
||||
from nucypher.config.characters import AliceConfiguration
|
||||
from nucypher.utilities.logging import SimpleObserver
|
||||
from nucypher.utilities.logging import GlobalLoggerSettings
|
||||
|
||||
|
||||
######################
|
||||
|
@ -20,7 +19,7 @@ from nucypher.utilities.logging import SimpleObserver
|
|||
# Twisted Logger
|
||||
from nucypher.utilities.sandbox.constants import TEMPORARY_DOMAIN
|
||||
|
||||
globalLogPublisher.addObserver(SimpleObserver())
|
||||
GlobalLoggerSettings.start_console_logging()
|
||||
|
||||
TEMP_ALICE_DIR = os.path.join('/', 'tmp', 'heartbeat-demo-alice')
|
||||
|
||||
|
|
|
@ -7,8 +7,6 @@ import maya
|
|||
import traceback
|
||||
from timeit import default_timer as timer
|
||||
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.characters.lawful import Bob, Ursula, Enrico
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.powers import DecryptingPower, SigningPower
|
||||
|
@ -17,10 +15,11 @@ from nucypher.network.middleware import RestMiddleware
|
|||
|
||||
from umbral.keys import UmbralPublicKey
|
||||
|
||||
from nucypher.utilities.logging import SimpleObserver
|
||||
from nucypher.utilities.logging import GlobalLoggerSettings
|
||||
from nucypher.utilities.sandbox.constants import TEMPORARY_DOMAIN
|
||||
|
||||
globalLogPublisher.addObserver(SimpleObserver())
|
||||
|
||||
GlobalLoggerSettings.start_console_logging()
|
||||
|
||||
######################
|
||||
# Boring setup stuff #
|
||||
|
|
|
@ -20,15 +20,10 @@ import os
|
|||
|
||||
import click
|
||||
from twisted.logger import Logger
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.config.constants import NUCYPHER_SENTRY_ENDPOINT
|
||||
from nucypher.utilities.logging import (
|
||||
logToSentry,
|
||||
getTextFileObserver,
|
||||
initialize_sentry,
|
||||
getJsonFileObserver
|
||||
)
|
||||
from nucypher.config.node import CharacterConfiguration
|
||||
from nucypher.utilities.logging import GlobalLoggerSettings
|
||||
|
||||
|
||||
class NucypherClickConfig:
|
||||
|
@ -48,13 +43,12 @@ class NucypherClickConfig:
|
|||
|
||||
# Sentry Logging
|
||||
if self.log_to_sentry is True:
|
||||
initialize_sentry(dsn=NUCYPHER_SENTRY_ENDPOINT)
|
||||
globalLogPublisher.addObserver(logToSentry)
|
||||
GlobalLoggerSettings.start_sentry_logging(self.sentry_endpoint)
|
||||
|
||||
# File Logging
|
||||
if self.log_to_file is True:
|
||||
globalLogPublisher.addObserver(getTextFileObserver())
|
||||
globalLogPublisher.addObserver(getJsonFileObserver())
|
||||
GlobalLoggerSettings.start_text_file_logging()
|
||||
GlobalLoggerSettings.start_json_file_logging()
|
||||
|
||||
# You guessed it
|
||||
self.debug = False
|
||||
|
|
|
@ -18,7 +18,6 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import click
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.characters.banners import NUCYPHER_BANNER
|
||||
from nucypher.characters.control.emitters import JSONRPCStdoutEmitter
|
||||
|
@ -28,7 +27,7 @@ from nucypher.cli.characters import moe, ursula, alice, bob, enrico, felix
|
|||
from nucypher.cli.config import nucypher_click_config, NucypherClickConfig
|
||||
from nucypher.cli.painting import echo_version
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.utilities.logging import GlobalConsoleLogger, getJsonFileObserver, SimpleObserver, logToSentry
|
||||
from nucypher.utilities.logging import GlobalLoggerSettings
|
||||
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
||||
|
||||
|
||||
|
@ -73,18 +72,18 @@ def nucypher_cli(click_config,
|
|||
if debug:
|
||||
click_config.log_to_sentry = False
|
||||
click_config.log_to_file = True # File Logging
|
||||
globalLogPublisher.addObserver(SimpleObserver()) # Console Logging
|
||||
globalLogPublisher.removeObserver(logToSentry) # No Sentry
|
||||
GlobalConsoleLogger.set_log_level(log_level_name='debug')
|
||||
GlobalLoggerSettings.start_console_logging()
|
||||
GlobalLoggerSettings.stop_sentry_logging()
|
||||
GlobalLoggerSettings.set_log_level(log_level_name='debug')
|
||||
|
||||
elif quiet: # Disable Logging
|
||||
globalLogPublisher.removeObserver(logToSentry)
|
||||
globalLogPublisher.removeObserver(SimpleObserver)
|
||||
globalLogPublisher.removeObserver(getJsonFileObserver())
|
||||
GlobalLoggerSettings.stop_sentry_logging()
|
||||
GlobalLoggerSettings.stop_console_logging()
|
||||
GlobalLoggerSettings.stop_json_file_logging()
|
||||
|
||||
# Logging
|
||||
if not no_logs:
|
||||
GlobalConsoleLogger.start_if_not_started()
|
||||
GlobalLoggerSettings.start_text_file_logging()
|
||||
|
||||
# CLI Session Configuration
|
||||
click_config.verbose = verbose
|
||||
|
@ -115,17 +114,17 @@ def nucypher_cli(click_config,
|
|||
|
||||
r"""
|
||||
ursula
|
||||
|
|
||||
| moe
|
||||
| /
|
||||
|
|
||||
| moe
|
||||
| /
|
||||
| /
|
||||
stdin --> cli.main --- alice
|
||||
| \
|
||||
| \
|
||||
| bob
|
||||
| \
|
||||
| bob
|
||||
|
|
||||
enrico
|
||||
|
||||
enrico
|
||||
|
||||
|
||||
|
||||
New character CLI modules must be added here
|
||||
|
|
|
@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from functools import lru_cache
|
||||
import pathlib
|
||||
|
||||
from sentry_sdk import capture_exception, add_breadcrumb
|
||||
|
@ -22,12 +23,11 @@ from sentry_sdk.integrations.logging import LoggingIntegration
|
|||
from twisted.logger import FileLogObserver, jsonFileLogObserver, formatEvent, formatEventAsClassicLogText
|
||||
from twisted.logger import ILogObserver
|
||||
from twisted.logger import LogLevel
|
||||
from twisted.logger import globalLogPublisher
|
||||
from twisted.logger import globalLogPublisher, globalLogBeginner
|
||||
from twisted.python.logfile import DailyLogFile
|
||||
from zope.interface import provider
|
||||
|
||||
import nucypher
|
||||
from nucypher.config.constants import USER_LOG_DIR
|
||||
from nucypher.config.constants import USER_LOG_DIR, NUCYPHER_SENTRY_ENDPOINT
|
||||
|
||||
|
||||
def initialize_sentry(dsn: str):
|
||||
|
@ -63,8 +63,67 @@ def initialize_sentry(dsn: str):
|
|||
)
|
||||
|
||||
|
||||
def logToSentry(event):
|
||||
class GlobalLoggerSettings:
|
||||
|
||||
log_level = LogLevel.levelWithName("info")
|
||||
|
||||
@classmethod
|
||||
def set_log_level(cls, log_level_name):
|
||||
cls.log_level = LogLevel.levelWithName(log_level_name)
|
||||
|
||||
@classmethod
|
||||
def start_console_logging(cls):
|
||||
globalLogPublisher.addObserver(console_observer)
|
||||
|
||||
@classmethod
|
||||
def stop_console_logging(cls):
|
||||
globalLogPublisher.removeObserver(console_observer)
|
||||
|
||||
@classmethod
|
||||
def start_text_file_logging(cls):
|
||||
globalLogPublisher.addObserver(get_text_file_observer())
|
||||
|
||||
@classmethod
|
||||
def stop_text_file_logging(cls):
|
||||
globalLogPublisher.removeObserver(get_text_file_observer())
|
||||
|
||||
@classmethod
|
||||
def start_json_file_logging(cls):
|
||||
globalLogPublisher.addObserver(get_json_file_observer())
|
||||
|
||||
@classmethod
|
||||
def stop_json_file_logging(cls):
|
||||
globalLogPublisher.removeObserver(get_json_file_observer())
|
||||
|
||||
@classmethod
|
||||
def start_sentry_logging(cls, dsn: str):
|
||||
_SentryInitGuard.init(dsn)
|
||||
globalLogPublisher.addObserver(sentry_observer)
|
||||
|
||||
@classmethod
|
||||
def stop_sentry_logging(cls):
|
||||
globalLogPublisher.removeObserver(sentry_observer)
|
||||
|
||||
|
||||
def console_observer(event):
|
||||
if event['log_level'] >= GlobalLoggerSettings.log_level:
|
||||
print(formatEvent(event))
|
||||
|
||||
|
||||
class _SentryInitGuard:
|
||||
|
||||
initialized = False
|
||||
dsn = None
|
||||
|
||||
@classmethod
|
||||
def init(cls, dsn: str = NUCYPHER_SENTRY_ENDPOINT):
|
||||
if not cls.initialized:
|
||||
initialize_sentry(dsn)
|
||||
else:
|
||||
raise ValueError(f"Sentry has been already initialized with DSN {cls.dsn}")
|
||||
|
||||
|
||||
def sentry_observer(event):
|
||||
# Handle breadcrumbs...
|
||||
if not event.get('isError') or 'failure' not in event:
|
||||
add_breadcrumb(level=event.get('log_level').name,
|
||||
|
@ -77,50 +136,21 @@ def logToSentry(event):
|
|||
capture_exception((f.type, f.value, f.getTracebackObject()))
|
||||
|
||||
|
||||
def _get_or_create_user_log_dir():
|
||||
return pathlib.Path(USER_LOG_DIR).mkdir(parents=True, exist_ok=True)
|
||||
def _ensure_dir_exists(path):
|
||||
pathlib.Path(path).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def getJsonFileObserver(name="nucypher.log.json", path=USER_LOG_DIR): # TODO: More configurable naming here?
|
||||
_get_or_create_user_log_dir()
|
||||
@lru_cache()
|
||||
def get_json_file_observer(name="nucypher.log.json", path=USER_LOG_DIR): # TODO: More configurable naming here?
|
||||
_ensure_dir_exists(path)
|
||||
logfile = DailyLogFile(name, path)
|
||||
observer = jsonFileLogObserver(outFile=logfile)
|
||||
return observer
|
||||
|
||||
|
||||
def getTextFileObserver(name="nucypher.log", path=USER_LOG_DIR):
|
||||
_get_or_create_user_log_dir()
|
||||
@lru_cache()
|
||||
def get_text_file_observer(name="nucypher.log", path=USER_LOG_DIR):
|
||||
_ensure_dir_exists(path)
|
||||
logfile = DailyLogFile(name, path)
|
||||
observer = FileLogObserver(formatEvent=formatEventAsClassicLogText, outFile=logfile)
|
||||
return observer
|
||||
|
||||
|
||||
class SimpleObserver:
|
||||
|
||||
@provider(ILogObserver)
|
||||
def __call__(self, event):
|
||||
if event['log_level'] >= GlobalConsoleLogger.log_level:
|
||||
event['log_format'] = event['log_format']
|
||||
print(formatEvent(event))
|
||||
|
||||
|
||||
class GlobalConsoleLogger:
|
||||
|
||||
log_level = LogLevel.levelWithName("info")
|
||||
started = False
|
||||
|
||||
@classmethod
|
||||
def set_log_level(cls, log_level_name):
|
||||
cls.log_level = LogLevel.levelWithName(log_level_name)
|
||||
if not cls.started:
|
||||
cls.start()
|
||||
|
||||
@classmethod
|
||||
def start(cls):
|
||||
globalLogPublisher.addObserver(getTextFileObserver())
|
||||
cls.started = True
|
||||
|
||||
@classmethod
|
||||
def start_if_not_started(cls):
|
||||
if not cls.started:
|
||||
cls.start()
|
||||
|
|
|
@ -26,7 +26,6 @@ import os
|
|||
|
||||
from twisted.internet import protocol
|
||||
from twisted.internet import reactor
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.utilities.logging import SimpleObserver
|
||||
|
||||
|
|
|
@ -17,21 +17,17 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import os
|
||||
|
||||
import pytest
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.characters.control.emitters import WebEmitter
|
||||
from nucypher.cli.config import NucypherClickConfig
|
||||
from nucypher.utilities.logging import GlobalConsoleLogger, logToSentry
|
||||
from nucypher.utilities.logging import GlobalLoggerSettings
|
||||
# Logger Configuration
|
||||
#
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
|
||||
# Disable click sentry and file logging
|
||||
globalLogPublisher.removeObserver(logToSentry)
|
||||
NucypherClickConfig.log_to_sentry = False
|
||||
|
||||
# Log to files
|
||||
NucypherClickConfig.log_to_file = True
|
||||
|
||||
# Crash on server error by default
|
||||
|
@ -106,4 +102,6 @@ def pytest_collection_modifyitems(config, items):
|
|||
|
||||
log_level_name = config.getoption("--log-level", "info", skip=True)
|
||||
|
||||
GlobalConsoleLogger.set_log_level(log_level_name)
|
||||
GlobalLoggerSettings.set_log_level(log_level_name)
|
||||
GlobalLoggerSettings.start_text_file_logging()
|
||||
GlobalLoggerSettings.start_json_file_logging()
|
||||
|
|
Loading…
Reference in New Issue