Loguru: Allow log message as json object when serialize is true

Created on 11 Dec 2018  路  5Comments  路  Source: Delgan/loguru

When message is a json object, serializer should parse the json and output it as an object other than a json string.

question

Most helpful comment

I see, thanks. I think you should perform the deserialization in your custom sink function.

def sink(message):
    record = message.record
    if "deserialize" in record["extra"]:
        obj = json.loads(record["message"])
        # Do whatever you want with the deserialized object

And call log function using bind() like this:

logger.bind(deserialize=True).debug(aws_message)

That way, you can still log non-serialized message like logger.debug("No JSON here"), and others sinks using string can still continue to work.

All 5 comments

Unfortunately, this is not possible, as that would break the contract that as long as a sink accept a string message it will work.

If serialize would pass a object, you could not do logger.start("file.log", serialize=True).

You should proceed of the deserialization in your custom sink.

def sink(serialized_message):
    obj = json.loads(serialized_message)

Also, note that you can access the log values without even needing serialization, it is available through the .record attribute of each logged message.

def sink(message):
    record = message.record  # This is just a dict
    print(record["time"])
def serialize_record(text, record):
        exc = record["exception"]
        serializable = {
            "text": text,
            "record": {
                "elapsed": dict(repr=record["elapsed"], seconds=record["elapsed"].total_seconds()),
                "exception": exc
                and dict(type=exc.type.__name__, value=exc.value, traceback=bool(exc.traceback)),
                "extra": record["extra"],
                "file": dict(name=record["file"].name, path=record["file"].path),
                "function": record["function"],
                "level": dict(
                    icon=record["level"].icon, name=record["level"].name, no=record["level"].no
                ),
                "line": record["line"],
                "message": record["message"],
                "module": record["module"],
                "name": record["name"],
                "process": dict(id=record["process"].id, name=record["process"].name),
                "thread": dict(id=record["thread"].id, name=record["thread"].name),
                "time": dict(repr=record["time"], timestamp=record["time"].timestamp()),
            },
        }

Maybe we can try parse record["message"] as json object here.

What's your use case exactly please?
I have trouble understanding why the proposed solutions would not work.
As record["message"] is just the string passed to logger.debug("Message"), I don't see how it could be parsed as a JSON object.

like i want to log like logger.debug("\"message\": { \"source\": \"blabla\"}"). For example, the message can be an AWS sns message field, a json doc string generated by cloudwatch.

I see, thanks. I think you should perform the deserialization in your custom sink function.

def sink(message):
    record = message.record
    if "deserialize" in record["extra"]:
        obj = json.loads(record["message"])
        # Do whatever you want with the deserialized object

And call log function using bind() like this:

logger.bind(deserialize=True).debug(aws_message)

That way, you can still log non-serialized message like logger.debug("No JSON here"), and others sinks using string can still continue to work.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

volfco picture volfco  路  5Comments

talz picture talz  路  6Comments

shmilylty picture shmilylty  路  5Comments

BarryThrill picture BarryThrill  路  6Comments

HarveySummers picture HarveySummers  路  4Comments