Skip to content

Structuered logs #32

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions