Django OpenTelemetry Logging Error: 'ProxyLogger' object has no attribute 'resource' Azure application insights

Я интегрирую регистрацию OpenTelemetry в свое Django-приложение для отправки журналов в Azure Application Insights, но сталкиваюсь со следующей ошибкой:

AttributeError: 'ProxyLogger' object has no attribute 'resource'

В настройках есть следующая настройка логгера copilot/settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'standard',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'INFO',
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': True,
        },
        'copilot': {  # Parent logger for your app
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': True,  # Allows child loggers to inherit handlers
        },
    },

}

Это copilot/otel_config.py

# otel_config.py

import os
from django.conf import settings
import logging
from dotenv import load_dotenv
from opentelemetry import trace
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import (
    LoggerProvider,
    LoggingHandler,
)
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter, AzureMonitorLogExporter
from opentelemetry.instrumentation.django import DjangoInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor

def setup_opentelemetry():
    # Set up the tracer provider with resource attributes
    resource = Resource(attributes={
        "service.name": "copilot",
    })

    tracer_provider = TracerProvider()
    trace.set_tracer_provider(tracer_provider)

    connection_string = settings.APPLICATIONINSIGHTS_CONNECTION_STRING

    trace_exporter = AzureMonitorTraceExporter(
        connection_string = connection_string
        )
    span_processor = BatchSpanProcessor(trace_exporter)
    tracer_provider.add_span_processor(span_processor)
    
    # Initialize LoggerProvider
    logger_provider = LoggerProvider(resource=resource)
    set_logger_provider(logger_provider)
    log_exporter = AzureMonitorLogExporter(
        connection_string = connection_string
    )
    logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))

    LoggingInstrumentor().instrument(set_logging_format=True)
    \
    DjangoInstrumentor().instrument()


    logging.basicConfig(level=logging.INFO)  # Set to INFO or DEBUG as needed
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.INFO)  # Ensure the root logger captures INFO level logs

     # Remove existing handlers to avoid duplication
    # for handler in root_logger.handlers[:]:
    #     root_logger.removeHandler(handler)

    # Add Azure Monitor Log Exporter as a handler
    azure_log_handler = LoggingHandler(level=logging.INFO)
    root_logger.addHandler(azure_log_handler)
    
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)  
    formatter = logging.Formatter(
        '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
    )
    console_handler.setFormatter(formatter)
    root_logger.addHandler(console_handler)

   

    # Log a test warning to verify setup
    root_logger.warning("OpenTelemetry setup complete")

Это logger_utils utils/logger_utils.py

import logging
from opentelemetry.sdk._logs import LoggingHandler
from django.conf import settings

def get_logger(name: str):
    logger = logging.getLogger(name)
    # if settings.DJANGO_ENV == 'development':
    #     return logger
    handler = LoggingHandler(level=logging.DEBUG)
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)
    return logger

Я вызываю регистратор, как показано ниже в коде в представлениях и службах

from utils.logger_utils import get_logger
logger = get_logger(__name__)

logger.info("Test")

При доступе к файлам в большинстве случаев это работает и также регистрируется на azure app insights, но в некоторых случаях это не удается и выдает ошибку

В вашем коде Django неправильно настроено ведение журнала открытой телеметрии.

Ниже приводится подробное объяснение причины проблемы и пути ее решения.

Убедитесь, что открытая телеметрия инициализирована до того, как Django загрузит конфигурации ведения журнала.

Изменить wsgi.py или manage.py:

from otel_config import setup_opentelemetry
setup_opentelemetry()

Измените otel_config.py, чтобы убедиться, что LoggerProvider установлено перед вызовом LoggingInstrumentor():

import logging
from opentelemetry import trace
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter, AzureMonitorLogExporter
from opentelemetry.instrumentation.django import DjangoInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor

def setup_opentelemetry():

    resource = Resource(attributes={"service.name": "copilot"})
    tracer_provider = TracerProvider(resource=resource)
    trace.set_tracer_provider(tracer_provider)

    connection_string = "YOUR_AZURE_MONITOR_CONNECTION_STRING"

    trace_exporter = AzureMonitorTraceExporter(connection_string=connection_string)
    span_processor = BatchSpanProcessor(trace_exporter)
    tracer_provider.add_span_processor(span_processor)
    logger_provider = LoggerProvider(resource=resource)
    set_logger_provider(logger_provider)

    log_exporter = AzureMonitorLogExporter(connection_string=connection_string)
    logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
   LoggingInstrumentor().instrument(set_logging_format=True)
    DjangoInstrumentor().instrument()
    logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.INFO)
    azure_log_handler = LoggingHandler(level=logging.INFO)
    root_logger.addHandler(azure_log_handler)    logging.getLogger("django").info("OpenTelemetry setup complete")

Измените utils/logger_utils.py, чтобы использовать открытый поставщик регистраторов телеметрии:

import logging
from opentelemetry._logs import get_logger_provider

def get_logger(name: str):
    provider = get_logger_provider()
    logger = provider.get_logger(name)  # Ensures logger comes from OpenTelemetry
    return logger

Output

Вернуться на верх