Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sdk/monitor/azure-monitor-opentelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## 1.0.1 (Unreleased)

- Add message ids for AppLens
([#32195](https://github.com/Azure/azure-sdk-for-python/pull/32195))

### Features Added

### Breaking Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# --------------------------------------------------------------------------


import logging
from warnings import warn

from opentelemetry.sdk._configuration import _OTelSDKConfigurator
Expand All @@ -16,25 +15,28 @@
)
from azure.monitor.opentelemetry._diagnostics.diagnostic_logging import (
AzureDiagnosticLogging,
_ATTACH_FAILURE_CONFIGURATOR,
_ATTACH_SUCCESS_CONFIGURATOR,
)
from azure.monitor.opentelemetry._diagnostics.status_logger import (
AzureStatusLogger,
)

_logger = logging.getLogger(__name__)


class AzureMonitorConfigurator(_OTelSDKConfigurator):
def _configure(self, **kwargs):
if not _is_attach_enabled():
warn(_PREVIEW_ENTRY_POINT_WARNING)
try:
AzureDiagnosticLogging.enable(_logger)
super()._configure(**kwargs)
except ValueError as e:
_logger.error(
"Azure Monitor Configurator failed during configuration due to a ValueError: %s", e
AzureStatusLogger.log_status(True)
Comment thread
lzchen marked this conversation as resolved.
AzureDiagnosticLogging.info(
"Azure Monitor Configurator configured successfully.",
_ATTACH_SUCCESS_CONFIGURATOR
)
raise e
except Exception as e:
_logger.error(
"Azure Monitor Configurator failed during configuration: %s", e
AzureDiagnosticLogging.error(
"Azure Monitor Configurator failed during configuration: %s" % str(e),
_ATTACH_FAILURE_CONFIGURATOR,
)
raise e
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# Licensed under the MIT License. See License in the project root for
# license information.
# --------------------------------------------------------------------------
import logging
from os import environ
from warnings import warn

Expand All @@ -27,55 +26,45 @@
)
from azure.monitor.opentelemetry._diagnostics.diagnostic_logging import (
AzureDiagnosticLogging,
_ATTACH_FAILURE_DISTRO,
_ATTACH_SUCCESS_DISTRO,
)
from azure.monitor.opentelemetry._diagnostics.status_logger import (
AzureStatusLogger,
)

_CONFIG_FAILED_MSG = "Azure Monitor OpenTelemetry Distro failed during configuration: %s"

_logger = logging.getLogger(__name__)
_opentelemetry_logger = logging.getLogger("opentelemetry")
# TODO: Enabled when duplicate logging issue is solved
# _exporter_logger = logging.getLogger("azure.monitor.opentelemetry.exporter")


class AzureMonitorDistro(BaseDistro):
def _configure(self, **kwargs) -> None:
if not _is_attach_enabled():
warn(_PREVIEW_ENTRY_POINT_WARNING)
try:
_configure_auto_instrumentation()
except Exception as ex:
_logger.exception(
("Error occurred auto-instrumenting AzureMonitorDistro")
AzureStatusLogger.log_status(True)
AzureDiagnosticLogging.info(
"Azure Monitor OpenTelemetry Distro configured successfully.",
_ATTACH_SUCCESS_DISTRO
)
except Exception as e:
AzureStatusLogger.log_status(False, reason=str(e))
Comment thread
lzchen marked this conversation as resolved.
AzureDiagnosticLogging.error(
"Azure Monitor OpenTelemetry Distro failed during configuration: %s" % str(e),
_ATTACH_FAILURE_DISTRO,
)
raise ex
raise e


def _configure_auto_instrumentation() -> None:
try:
AzureStatusLogger.log_status(False, "Distro being configured.")
AzureDiagnosticLogging.enable(_logger)
AzureDiagnosticLogging.enable(_opentelemetry_logger)
environ.setdefault(
OTEL_METRICS_EXPORTER, "azure_monitor_opentelemetry_exporter"
)
environ.setdefault(
OTEL_TRACES_EXPORTER, "azure_monitor_opentelemetry_exporter"
)
environ.setdefault(
OTEL_LOGS_EXPORTER, "azure_monitor_opentelemetry_exporter"
)
environ.setdefault(
_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "true"
)
settings.tracing_implementation = OpenTelemetrySpan
AzureStatusLogger.log_status(True)
_logger.info(
"Azure Monitor OpenTelemetry Distro configured successfully."
)
except Exception as exc:
AzureStatusLogger.log_status(False, reason=exc)
_logger.error(_CONFIG_FAILED_MSG, exc)
raise exc
environ.setdefault(
OTEL_METRICS_EXPORTER, "azure_monitor_opentelemetry_exporter"
)
environ.setdefault(
OTEL_TRACES_EXPORTER, "azure_monitor_opentelemetry_exporter"
)
environ.setdefault(
OTEL_LOGS_EXPORTER, "azure_monitor_opentelemetry_exporter"
)
environ.setdefault(
_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "true"
)
settings.tracing_implementation = OpenTelemetrySpan
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@
_IS_ON_APP_SERVICE = "WEBSITE_SITE_NAME" in environ
# TODO: Add environment variable to enabled diagnostics off of App Service
_IS_DIAGNOSTICS_ENABLED = _IS_ON_APP_SERVICE
# TODO: Enabled when duplicate logging issue is solved
Comment thread
jeremydvoss marked this conversation as resolved.
# _EXPORTER_DIAGNOSTICS_ENABLED_ENV_VAR = (
# "AZURE_MONITOR_OPENTELEMETRY_DISTRO_ENABLE_EXPORTER_DIAGNOSTICS"
# )
_CUSTOMER_IKEY_ENV_VAR = None
_PREVIEW_ENTRY_POINT_WARNING = "Autoinstrumentation for the Azure Monitor OpenTelemetry Distro is in preview."
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -74,19 +70,9 @@ def _env_var_or_default(var_name, default_val=""):
return default_val


# TODO: Enabled when duplicate logging issue is solved
# def _is_exporter_diagnostics_enabled():
# return (
# _EXPORTER_DIAGNOSTICS_ENABLED_ENV_VAR in environ
# and environ[_EXPORTER_DIAGNOSTICS_ENABLED_ENV_VAR] == "True"
# )


_EXTENSION_VERSION = _env_var_or_default(
"ApplicationInsightsAgent_EXTENSION_VERSION", "disabled"
)
# TODO: Enabled when duplicate logging issue is solved
# _EXPORTER_DIAGNOSTICS_ENABLED = _is_exporter_diagnostics_enabled()


def _is_attach_enabled():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@
_SUBSCRIPTION_ID_ENV_VAR.split("+")[0] if _SUBSCRIPTION_ID_ENV_VAR else None
)
_logger = logging.getLogger(__name__)
_logger.propagate = False
_logger.setLevel(logging.INFO)
_DIAGNOSTIC_LOG_PATH = _get_log_path()
_ATTACH_SUCCESS_DISTRO = "4200"
Comment thread
jeremydvoss marked this conversation as resolved.
_ATTACH_SUCCESS_CONFIGURATOR = "4201"
Comment thread
lzchen marked this conversation as resolved.
_ATTACH_FAILURE_DISTRO = "4400"
_ATTACH_FAILURE_CONFIGURATOR = "4401"


class AzureDiagnosticLogging:
_initialized = False
_lock = threading.Lock()
_f_handler = None

@classmethod
def _initialize(cls):
Expand All @@ -51,29 +56,36 @@ def _initialize(cls):
+ f'"extensionVersion":"{_EXTENSION_VERSION}", '
+ f'"sdkVersion":"{VERSION}", '
+ f'"subscriptionId":"{_SUBSCRIPTION_ID}", '
+ '"msgId":"%(msgId)s", '
+ '"language":"python"'
+ "}"
+ "}"
)
if not exists(_DIAGNOSTIC_LOG_PATH):
makedirs(_DIAGNOSTIC_LOG_PATH)
AzureDiagnosticLogging._f_handler = logging.FileHandler(
f_handler = logging.FileHandler(
join(
_DIAGNOSTIC_LOG_PATH, _DIAGNOSTIC_LOGGER_FILE_NAME
)
)
formatter = logging.Formatter(
fmt=log_format, datefmt="%Y-%m-%dT%H:%M:%S"
)
AzureDiagnosticLogging._f_handler.setFormatter(formatter)
f_handler.setFormatter(formatter)
_logger.addHandler(f_handler)
AzureDiagnosticLogging._initialized = True
_logger.info("Initialized Azure Diagnostic Logger.")

@classmethod
def enable(cls, logger: logging.Logger):
def info(cls, message: str, message_id: int):
AzureDiagnosticLogging._initialize()
if AzureDiagnosticLogging._initialized and AzureDiagnosticLogging._f_handler:
logger.addHandler(AzureDiagnosticLogging._f_handler)
_logger.info(
"Added Azure diagnostics logging to %s.", logger.name
)
_logger.info(message, extra={'msgId': message_id})

@classmethod
def warning(cls, message: str, message_id: int):
AzureDiagnosticLogging._initialize()
_logger.warning(message, extra={'msgId': message_id})

@classmethod
def error(cls, message: str, message_id: int):
AzureDiagnosticLogging._initialize()
_logger.error(message, extra={'msgId': message_id})
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,51 @@
from azure.monitor.opentelemetry._autoinstrumentation.configurator import (
AzureMonitorConfigurator,
)
from azure.monitor.opentelemetry._diagnostics.diagnostic_logging import (
_ATTACH_FAILURE_CONFIGURATOR,
_ATTACH_SUCCESS_CONFIGURATOR
)


class TestConfigurator(TestCase):
@patch("azure.monitor.opentelemetry._autoinstrumentation.configurator._is_attach_enabled", return_value=True)
@patch(
"azure.monitor.opentelemetry._autoinstrumentation.configurator.AzureDiagnosticLogging.enable"
"azure.monitor.opentelemetry._autoinstrumentation.configurator.AzureDiagnosticLogging"
)
def test_configure(self, mock_diagnostics, attach_mock):
configurator = AzureMonitorConfigurator()
with warnings.catch_warnings():
warnings.simplefilter("error")
configurator._configure()
mock_diagnostics.assert_called_once()
mock_diagnostics.info.assert_called_once_with(
"Azure Monitor Configurator configured successfully.",
_ATTACH_SUCCESS_CONFIGURATOR
)

@patch("azure.monitor.opentelemetry._autoinstrumentation.configurator._is_attach_enabled", return_value=False)
@patch(
"azure.monitor.opentelemetry._autoinstrumentation.configurator.AzureDiagnosticLogging.enable"
"azure.monitor.opentelemetry._autoinstrumentation.configurator.AzureDiagnosticLogging"
)
def test_configure_preview(self, mock_diagnostics, attach_mock):
configurator = AzureMonitorConfigurator()
with self.assertWarns(Warning):
configurator._configure()
mock_diagnostics.assert_called_once()
mock_diagnostics.info.assert_called_once_with(
"Azure Monitor Configurator configured successfully.",
_ATTACH_SUCCESS_CONFIGURATOR
)

@patch("azure.monitor.opentelemetry._autoinstrumentation.configurator.super")
@patch("azure.monitor.opentelemetry._autoinstrumentation.configurator._is_attach_enabled", return_value=True)
@patch(
"azure.monitor.opentelemetry._autoinstrumentation.configurator.AzureDiagnosticLogging"
)
def test_configure_exc(self, mock_diagnostics, attach_mock, super_mock):
configurator = AzureMonitorConfigurator()
super_mock()._configure.side_effect = Exception("Test Exception")
with self.assertRaises(Exception):
configurator._configure()
mock_diagnostics.error.assert_called_once_with(
"Azure Monitor Configurator failed during configuration: Test Exception",
_ATTACH_FAILURE_CONFIGURATOR
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,60 @@
from azure.monitor.opentelemetry._autoinstrumentation.distro import (
AzureMonitorDistro,
)
from azure.monitor.opentelemetry._diagnostics.diagnostic_logging import (
_ATTACH_FAILURE_DISTRO,
_ATTACH_SUCCESS_DISTRO
)


class TestDistro(TestCase):
@patch("azure.monitor.opentelemetry._autoinstrumentation.distro._is_attach_enabled", return_value=True)
@patch("azure.monitor.opentelemetry._autoinstrumentation.distro.settings")
@patch(
"azure.monitor.opentelemetry._autoinstrumentation.distro.AzureDiagnosticLogging.enable"
"azure.monitor.opentelemetry._autoinstrumentation.distro.AzureDiagnosticLogging"
)
def test_configure(self, mock_diagnostics, azure_core_mock, attach_mock):
distro = AzureMonitorDistro()
with warnings.catch_warnings():
warnings.simplefilter("error")
distro.configure()
self.assertEqual(mock_diagnostics.call_count, 2)
mock_diagnostics.info.assert_called_once_with(
"Azure Monitor OpenTelemetry Distro configured successfully.",
_ATTACH_SUCCESS_DISTRO
)
self.assertEqual(
azure_core_mock.tracing_implementation, OpenTelemetrySpan
)

@patch("azure.monitor.opentelemetry._autoinstrumentation.distro._is_attach_enabled", return_value=False)
@patch("azure.monitor.opentelemetry._autoinstrumentation.distro.settings")
@patch(
"azure.monitor.opentelemetry._autoinstrumentation.distro.AzureDiagnosticLogging.enable"
"azure.monitor.opentelemetry._autoinstrumentation.distro.AzureDiagnosticLogging"
)
def test_configure_preview(self, mock_diagnostics, azure_core_mock, attach_mock):
distro = AzureMonitorDistro()
with self.assertWarns(Warning):
distro.configure()
self.assertEqual(mock_diagnostics.call_count, 2)
mock_diagnostics.info.assert_called_once_with(
"Azure Monitor OpenTelemetry Distro configured successfully.",
_ATTACH_SUCCESS_DISTRO
)
self.assertEqual(
azure_core_mock.tracing_implementation, OpenTelemetrySpan
)

@patch("azure.monitor.opentelemetry._autoinstrumentation.distro._configure_auto_instrumentation")
@patch("azure.monitor.opentelemetry._autoinstrumentation.distro._is_attach_enabled", return_value=True)
@patch("azure.monitor.opentelemetry._autoinstrumentation.distro.settings")
@patch(
"azure.monitor.opentelemetry._autoinstrumentation.distro.AzureDiagnosticLogging"
)
def test_configure_exc(self, mock_diagnostics, azure_core_mock, attach_mock, configure_mock):
distro = AzureMonitorDistro()
configure_mock.side_effect = Exception("Test Exception")
with self.assertRaises(Exception):
distro.configure()
mock_diagnostics.error.assert_called_once_with(
"Azure Monitor OpenTelemetry Distro failed during configuration: Test Exception",
_ATTACH_FAILURE_DISTRO
)
Loading