Commit 10be0d6a authored by Georges Racinet's avatar Georges Racinet 🦑
Browse files

message: wrapper class for easy logging

With gRPC, the `repr` of messages, notably Gitaly Requests
is made of multiple lines.
This is very bad for logging: a log should always be made of
a single line for:

- meaningful grepping
- detangling when several processes log to the same file

We want in particular service method to be able to log
easily their incoming requests and/or more messages, but
we want the formatting to be done only if the log is
actually to be emitted (important to avoid debug logs to
make production servers choke). This is usually achieved with
the following pattern, because logging evaluation is inherently

logging.debug('the interesting object is %r', obj)

We could use extras, as `hg-loggingmod` does for the repository,
but that is evaluated in the final formatting of the entire log
line, and requires to register a specific format, then a specific
handler to use it.

The provided solution (wrapping in a class), is not zero-cost,
but is expected to be cheap enough for the time being.
parent cade6be9d2f1
......@@ -21,6 +21,7 @@
from .stub.commit_pb2 import (
from google.protobuf.text_format import MessageToString
from google.protobuf.timestamp_pb2 import Timestamp
......@@ -24,6 +25,23 @@
from google.protobuf.timestamp_pb2 import Timestamp
class Logging:
"""Wrapper of requests and responses for sensible logging.
Still has the formatting happen lazily, only if the message
is emitted. We still pay the price of at least one instantiation though.
def __init__(self, message):
self.msg = message
def __repr__(self):
return '%s { %s }' % (self.msg.__class__.__name__,
MessageToString(self.msg, as_one_line=True))
__str__ = __repr__
def commit_author(ctx):
"""Produce a `GitCommit` message from a :class:`changectx` instance.
......@@ -13,6 +13,7 @@
from ..stub.shared_pb2 import (
......@@ -50,3 +51,11 @@
assert tag.message_size == 15
assert tag.tagger == message.commit_author(tagging_ctx)
assert tag.signature_type == SignatureType.PGP
def test_logging_class():
log_msg = message.Logging(Repository(storage_name='thestore',
assert repr(log_msg) == (
'Repository { storage_name: "thestore" relative_path: "a/b/c" }'
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment