Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Loguru with Azure App Insights and OpenTelemetry #1222

Open
bbaabemhp opened this issue Oct 17, 2024 · 4 comments
Open

Use Loguru with Azure App Insights and OpenTelemetry #1222

bbaabemhp opened this issue Oct 17, 2024 · 4 comments
Labels
question Further information is requested

Comments

@bbaabemhp
Copy link

bbaabemhp commented Oct 17, 2024

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
Copy link

oieduardorabelo commented Oct 18, 2024

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

based on this

def write(self, message):
record = message.record
message = str(message)
exc = record["exception"]
record = logging.getLogger().makeRecord(
record["name"],
record["level"].no,
record["file"].path,
record["line"],
message,
(),
(exc.type, exc.value, exc.traceback) if exc else None,
record["function"],
record["extra"],
)
if exc:
record.exc_text = "\n"
self._handler.handle(record)

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
Copy link
Owner

Delgan commented Oct 20, 2024

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

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

@Delgan Delgan added the question Further information is requested label Oct 20, 2024
@oieduardorabelo
Copy link

@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)

@Delgan
Copy link
Owner

Delgan commented Oct 23, 2024

@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)

@oieduardorabelo Yes, this is correct.
While using logger.configure(), you're basically wiping out the existing configuration and replacing it with a new one. In particular, that will replace the default sink (sys.stderr) with the ones in the handlers argument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants