(core) Update logging in sandbox code, and log tracebacks as single log messages.

Summary:
- Replace logger module by the standard module 'logging'.
- When a log message from the sandbox includes newlines (e.g. for tracebacks),
  keep those lines together in the Node log message.

  Previously each line was a different message, making it difficult to view
  tracebacks, particularly in prod where each line becomes a separate message
  object.

- Fix assorted lint errors.

Test Plan: Added a test for the log-line splitting and escaping logic.

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D3956
This commit is contained in:
Dmitry S
2023-07-18 11:20:02 -04:00
parent 7fd48364df
commit 534615dd50
46 changed files with 154 additions and 249 deletions

View File

@@ -25,11 +25,20 @@ from acl_formula import parse_acl_formula
from sandbox import get_default_sandbox
from imports.register import register_import_parsers
import logger
log = logger.Logger(__name__, logger.INFO)
# Handler for logging, which flushes each message.
class FlushingStreamHandler(logging.StreamHandler):
def emit(self, record):
super(FlushingStreamHandler, self).emit(record)
self.flush()
# Configure logging module to behave similarly to logger. (It may be OK to get rid of logger.)
logging.basicConfig(format="[%(levelname)s] [%(name)s] %(message)s")
# Configure logging module to produce messages with log level and logger name.
logging.basicConfig(format="[%(levelname)s] [%(name)s] %(message)s",
handlers=[FlushingStreamHandler(sys.stderr)],
level=logging.INFO)
# The default level is INFO. If a different level is desired, add a call like this:
# log.setLevel(logging.WARNING)
log = logging.getLogger(__name__)
def table_data_from_db(table_name, table_data_repr):
if table_data_repr is None:
@@ -57,7 +66,7 @@ def run(sandbox):
# Wrap each method so that it logs a message that it's being called.
@functools.wraps(method)
def wrapper(*args, **kwargs):
log.debug("calling %s" % method.__name__)
log.debug("calling %s", method.__name__)
return method(*args, **kwargs)
sandbox.register(method.__name__, wrapper)