Delgan / loguru

Python logging made (stupidly) simple
MIT License
19.79k stars 695 forks source link

Use Loguru with Azure App Insights and OpenTelemetry #1222

Open bbaabemhp opened 5 days ago

bbaabemhp commented 5 days ago

I wanted to know if there is some way to save the logs from Loguru in Azure App Insights? I know that logs are written automatically to App Insights when using the standard logging library, but I couldn't see any way to do with loguru. When going to the Azure Portal and look into the Logs, I can not see any logs I used in my code, regardless of the log level.

Thanks! :)

For context, my code to initialize loguru (used the code from another issue):

import sys

from loguru import logger
from opentelemetry.trace import (
    INVALID_SPAN,
    INVALID_SPAN_CONTEXT,
    get_current_span,
    get_tracer_provider,
)

def instrument_loguru():
    provider = get_tracer_provider()
    service_name = None

    def add_trace_context(record):
        record["extra"]["otelSpanID"] = "0"
        record["extra"]["otelTraceID"] = "0"
        record["extra"]["otelTraceSampled"] = False

        nonlocal service_name
        if service_name is None:
            resource = getattr(provider, "resource", None)
            if resource:
                service_name = resource.attributes.get("service.name") or ""
            else:
                service_name = ""

        record["extra"]["otelServiceName"] = service_name

        span = get_current_span()
        if span != INVALID_SPAN:
            ctx = span.get_span_context()
            if ctx != INVALID_SPAN_CONTEXT:
                record["extra"]["otelSpanID"] = format(ctx.span_id, "016x")
                record["extra"]["otelTraceID"] = format(ctx.trace_id, "032x")
                record["extra"]["otelTraceSampled"] = ctx.trace_flags.sampled

    logger.configure(patcher=add_trace_context)
    logger.remove()
    format_ = "{time:YYYY-MM-DD HH:MM:SS.sss} {level} [{name}] [{file}:{line} [trace_id={extra[otelTraceID]} span_id={extra[otelSpanID]} resource.service.name={extra[otelServiceName]} trace_sampled={extra[otelTraceSampled]}] - {message}"
    logger.add(sys.stderr, format=format_)
oieduardorabelo commented 5 days ago

i'm using SINKs as destinations target and converting the record to logging

based on this https://github.com/Delgan/loguru/blob/3b66fb5b2ff38909dbeb817cb50e24f27677db8e/loguru/_simple_sinks.py#L43-L60

something like:

import logging
import os
from loguru import logger

APP_ENV = os.getenv("APP_ENV", "dev")

logger.remove()

def sink_json(loguru_message):
    # code to log as json
    pass

def sink_azure_app_insights(loguru_message):
    record = loguru_message.record
    exc = record["exception"]

    logging_logger = logging.getLogger("my-awesome-app")
    logging_record = logging_logger.makeRecord(
        f"{record['file'].name}:{record['line']}",
        record["level"].no,
        record["file"].path,
        record["line"],
        record["message"],
        (),
        (exc.type, exc.value, exc.traceback) if exc else None,
        record["function"],
        record["extra"],
    )

    if exc:
        logging_record.exc_text = "\n"

    logging_logger.handle(logging_record)

logger.configure(
    handlers=[
        {
            "backtrace": False,
            "diagnose": False,
            "level": "DEBUG",
            "serialize": True,
            "sink": azure_app_insights if APP_ENV == "prod" else sink_json,
        }
    ],
    extra={},
)
Delgan commented 3 days ago

Would you be able to use the PropagateHandler snippet from the docs?

It should automatically propagate messagges to loggers of the standard logging library.

oieduardorabelo commented 2 days ago

@Delgan is my understanding that PropagateHandler adds a new sink (using .add) and the approach I suggested above is similar, but toggling the sinks instead? (i'm asking to solidify some assumptions i have about loguru)