Mayil-AI / loguru

MIT License
0 stars 0 forks source link

Structured logs #31

Open vikramsubramanian opened 2 months ago

vikramsubramanian commented 2 months ago

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()? šŸ¤”