Skip to content

Structred logs#33

Description

@vikramsubramanian

Hey ! 馃憢 馃檪

I've been through quite some "issues" with a similar topic (including which I have also participated in! ) but I thought perhaps a new thread is worth it, instead of reviving a closed one. 馃槄

hashtag Logging Lists & Dicts

Previously, you helped me get to [this]( point:

import sys

from loguru import logger

def formatter(record):
base_format = "{time} {level} {name} {message} " + " " * 10
base = base_format.format_map(record)
lines = str(record["extra"].get("data", "")).splitlines()
indent = "\n" + " " * len(base)
reformatted = base + indent.join(lines)
record["extra"]["reformatted"] = reformatted
return "{extra[reformatted]}\n{exception}"

logger.remove()
logger.add(sys.stderr, format=formatter)

data = """---------------- Request ----------------
Headers : {"Accept": "/",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Content-Length": "20",
"User-Agent": "python-requests/2.27.1",
"cookie": "foo=bar; bar=baz",
"x-pretty-print": "2"}
URL :
Method : POST
Body : {"foo": "bar"}"""

logger.info("Default message")
logger.bind(data=data).info("Message with data")
However, in the above example, I was logging a str, and instead, I'd like to log a dict:

{
"Headers": {
"Accept": "/",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Content-Length": "20",
"User-Agent": "python-requests/2.27.1",
"cookie": "foo=bar; bar=baz",
"x-pretty-print": "2",
},
"URL": "
"Method": "POST",
"Body": {
"foo": "bar",
},
}
Is there a newer, better way of the above solution? Have things changed perhaps? 馃憖
How could I make it so that I can "auto-format" the output for lists or dicts?
hashtag Logging with indents

Wrt OP's original query, I'd like to also have indentation, but slightly different.

This was the proposed solution:

logger_indentation = ContextVar("logger_indentation", default=0)

def indent_logs(indent_size):
val = logger_indentation.get()
logger_indentation.set(val + indent_size)
yield
logger_indentation.set(val)

def patcher(record):
indentation = logger_indentation.get()
record.update(message=" " * indentation + record["message"])
And in my use-case, I am doing this:

logger.info(f"Parameters:")
for param_info in param_info_list:
with indent_logs(4):
logger.info(param_info)
With output:

2023-12-04 15:31:27.057 | INFO | actions_wrapper:action_wrapper:129 - Parameters:
2023-12-04 15:31:27.057 | INFO | actions_wrapper:action_wrapper:132 - element = "some_str"
2023-12-04 15:31:27.058 | INFO | actions_wrapper:action_wrapper:132 - element_index = 0 (Default)
But, what I'd preferably like to have is one log statement:

2023-12-04 15:31:27.057 | INFO | actions_wrapper:action_wrapper:129 - Parameters:
element = "some_str"
element_index = 0 (Default)
And preferably not having to use a context manager - maybe something similar to using bind()? 馃

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions