pydantic / logfire

Uncomplicated Observability for Python and beyond! 🪵🔥
https://logfire.pydantic.dev/docs/
MIT License
2.05k stars 61 forks source link

Logging formatter for stdout log records #486

Open LumaC0 opened 5 days ago

LumaC0 commented 5 days ago

Description

Can logfire provide a logging format configuration with access to LogRecord Attributes for logs written to stdout? The API can be as simple as adding an argument like logfire.configure(format="<format_string>").

The stdout logger is not configurable by means provided to the end user (as far as I can tell) and it really doesn't provide enough information to be useful (filename, line number, etc.). Integrating logfire into the stdlib logger via LogfireLoggingHandler might allow for custom formats but, per the documentation, using logfire directly is recommended.

current:

import logfire

logfire.configure()

logfire.info("log this message") # 23:04:47.846 log this message

proposed:

import logfire

log_format = "%(asctime)s - %(filename)s -%(lineno)d - %(message)s"
logfire.configure(format=log_format)

logfire.info("log this message") # 2024-10-08 16:49:45,896 - file.py - 16 - log this message
alexmojaki commented 4 days ago

I agree that we need to make console logging more flexible and customizable in a user friendly way. Unfortunately it's not easy. The objects we have are OpenTelemetry spans, not LogRecords. Here's a rough demo of what you can do now:

import datetime

from opentelemetry.sdk.trace.export import ConsoleSpanExporter, ReadableSpan, SimpleSpanProcessor

import logfire

def format_span(span: ReadableSpan):
    timestamp = datetime.datetime.fromtimestamp(span.start_time / 1_000_000_000)
    filename = span.attributes.get('code.filepath', '')
    lineno = span.attributes.get('code.lineno', '')
    message = span.attributes.get('logfire.msg', '')
    return f'{timestamp} - {filename}:{lineno} - {message}'

logfire.configure(
    additional_span_processors=[
        SimpleSpanProcessor(
            ConsoleSpanExporter(
                formatter=format_span,
            )
        )
    ],
    console=False,
)

But the filename and lineno won't always be available, and this will log two lines for every non-log span (the first being for the pending span), and there's probably other complications.