From c00c065483a0716595433aa0cdca9a10b01a3dbd Mon Sep 17 00:00:00 2001 From: jerevoss Date: Wed, 11 Jan 2023 16:58:31 -0800 Subject: [PATCH] Add diagnostic logging --- CHANGELOG.md | 2 + .../opentelemetry/distro/_constants.py | 66 ++++++ .../distro/_diagnostic_logging.py | 84 +++++++ .../opentelemetry/distro/configurator.py | 18 +- .../monitor/opentelemetry/distro/distro.py | 42 +++- .../tests/test_constants.py | 149 +++++++++++++ .../tests/test_diagnostic_logging.py | 206 ++++++++++++++++++ .../tests/test_distro.py | 32 +++ test-requirements.txt | 3 + 9 files changed, 592 insertions(+), 10 deletions(-) create mode 100644 azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_constants.py create mode 100644 azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_diagnostic_logging.py create mode 100644 azure-monitor-opentelemetry-distro/tests/test_constants.py create mode 100644 azure-monitor-opentelemetry-distro/tests/test_diagnostic_logging.py create mode 100644 azure-monitor-opentelemetry-distro/tests/test_distro.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 3844e028..f862bdc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Added Diagnostic Logging for App Service + ([#212](https://github.com/microsoft/ApplicationInsights-Python/pull/212)) - Updated main and distro READMEs ([#205](https://github.com/microsoft/ApplicationInsights-Python/pull/205)) - Update CONTRIBUTING.md, support Py3.11 diff --git a/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_constants.py b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_constants.py new file mode 100644 index 00000000..810c500c --- /dev/null +++ b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_constants.py @@ -0,0 +1,66 @@ +import logging +import platform +from os import environ +from pathlib import Path + +from azure.monitor.opentelemetry.exporter._connection_string_parser import ( + ConnectionStringParser, +) + +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License in the project root for +# license information. +# -------------------------------------------------------------------------- + +_LOG_PATH_LINUX = "/var/log/applicationinsights" +_LOG_PATH_WINDOWS = "\\LogFiles\\ApplicationInsights" +_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 duplciate logging issue is solved +# _EXPORTER_DIAGNOSTICS_ENABLED_ENV_VAR = ( +# "AZURE_MONITOR_OPENTELEMETRY_DISTRO_ENABLE_EXPORTER_DIAGNOSTICS" +# ) +logger = logging.getLogger(__name__) +_CUSTOMER_IKEY = "unknown" +try: + _CUSTOMER_IKEY = ConnectionStringParser().instrumentation_key +except ValueError as e: + logger.error("Failed to parse Instrumentation Key: %s" % e) + + +def _get_log_path(status_log_path=False): + system = platform.system() + if system == "Linux": + return _LOG_PATH_LINUX + elif system == "Windows": + log_path = str(Path.home()) + _LOG_PATH_WINDOWS + if status_log_path: + return log_path + "\\status" + else: + return log_path + else: + return None + + +def _env_var_or_default(var_name, default_val=""): + try: + return environ[var_name] + except KeyError: + return default_val + + +# TODO: Enabled when duplciate 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 duplciate logging issue is solved +# _EXPORTER_DIAGNOSTICS_ENABLED = _is_exporter_diagnostics_enabled() diff --git a/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_diagnostic_logging.py b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_diagnostic_logging.py new file mode 100644 index 00000000..1796f7bd --- /dev/null +++ b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/_diagnostic_logging.py @@ -0,0 +1,84 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License in the project root for +# license information. +# -------------------------------------------------------------------------- + +import logging +import threading +from os import makedirs +from os.path import exists, join + +from azure.monitor.opentelemetry.distro._constants import ( + _CUSTOMER_IKEY, + _EXTENSION_VERSION, + _IS_DIAGNOSTICS_ENABLED, + _env_var_or_default, + _get_log_path, +) +from azure.monitor.opentelemetry.distro._version import VERSION + +_OPENTELEMETRY_DIAGNOSTIC_LOGGER_NAME = "opentelemetry" +_DIAGNOSTIC_LOGGER_FILE_NAME = "applicationinsights-extension.log" +_SITE_NAME = _env_var_or_default("WEBSITE_SITE_NAME") +_SUBSCRIPTION_ID_ENV_VAR = _env_var_or_default("WEBSITE_OWNER_NAME") +_SUBSCRIPTION_ID = ( + _SUBSCRIPTION_ID_ENV_VAR.split("+")[0] + if _SUBSCRIPTION_ID_ENV_VAR + else None +) +_opentelemetry_logger = logging.getLogger( + _OPENTELEMETRY_DIAGNOSTIC_LOGGER_NAME +) +_logger = logging.getLogger(__name__) +_DIAGNOSTIC_LOG_PATH = _get_log_path() + + +class AzureDiagnosticLogging: + _initialized = False + _lock = threading.Lock() + _f_handler = None + + def _initialize(): + with AzureDiagnosticLogging._lock: + if not AzureDiagnosticLogging._initialized: + if _IS_DIAGNOSTICS_ENABLED and _DIAGNOSTIC_LOG_PATH: + format = ( + "{" + + '"time":"%(asctime)s.%(msecs)03d", ' + + '"level":"%(levelname)s", ' + + '"logger":"%(name)s", ' + + '"message":"%(message)s", ' + + '"properties":{' + + '"operation":"Startup", ' + + f'"sitename":"{_SITE_NAME}", ' + + f'"ikey":"{_CUSTOMER_IKEY}", ' + + f'"extensionVersion":"{_EXTENSION_VERSION}", ' + + f'"sdkVersion":"{VERSION}", ' + + f'"subscriptionId":"{_SUBSCRIPTION_ID}", ' + + '"language":"python"' + + "}" + + "}" + ) + if not exists(_DIAGNOSTIC_LOG_PATH): + makedirs(_DIAGNOSTIC_LOG_PATH) + AzureDiagnosticLogging._f_handler = logging.FileHandler( + join( + _DIAGNOSTIC_LOG_PATH, _DIAGNOSTIC_LOGGER_FILE_NAME + ) + ) + formatter = logging.Formatter( + fmt=format, datefmt="%Y-%m-%dT%H:%M:%S" + ) + AzureDiagnosticLogging._f_handler.setFormatter(formatter) + _logger.addHandler(AzureDiagnosticLogging._f_handler) + AzureDiagnosticLogging._initialized = True + _logger.info("Initialized Azure Diagnostic Logger.") + + def enable(logger: logging.Logger): + AzureDiagnosticLogging._initialize() + if AzureDiagnosticLogging._initialized: + logger.addHandler(AzureDiagnosticLogging._f_handler) + _logger.info( + "Added Azure diagnostics logging to %s." % logger.name + ) diff --git a/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/configurator.py b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/configurator.py index 1cc545f4..4445149b 100644 --- a/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/configurator.py +++ b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/configurator.py @@ -4,8 +4,24 @@ # license information. # -------------------------------------------------------------------------- + +from azure.monitor.opentelemetry.distro._diagnostic_logging import ( + AzureDiagnosticLogging, +) from opentelemetry.sdk._configuration import _OTelSDKConfigurator class AzureMonitorConfigurator(_OTelSDKConfigurator): - pass + def _configure(self, **kwargs): + try: + super()._configure(**kwargs) + except ValueError as e: + AzureDiagnosticLogging.log_diagnostic_error( + f"The components failed to initialize due to a ValueError: {e}" + ) + raise e + except Exception as e: + AzureDiagnosticLogging.log_diagnostic_error( + f"The components failed to initialize: {e}" + ) + raise e diff --git a/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/distro.py b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/distro.py index b87f02db..703bb361 100644 --- a/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/distro.py +++ b/azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/distro.py @@ -6,6 +6,9 @@ import logging from os import environ +from azure.monitor.opentelemetry.distro._diagnostic_logging import ( + AzureDiagnosticLogging, +) from opentelemetry.environment_variables import ( OTEL_METRICS_EXPORTER, OTEL_TRACES_EXPORTER, @@ -13,6 +16,9 @@ from opentelemetry.instrumentation.distro import BaseDistro _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): @@ -27,12 +33,30 @@ def _configure(self, **kwargs) -> None: def _configure_auto_instrumentation() -> None: - # TODO: support configuration via env vars - # TODO: Uncomment when logging is out of preview - # environ.setdefault(OTEL_LOGS_EXPORTER, "azure_monitor_opentelemetry_exporter") - environ.setdefault( - OTEL_METRICS_EXPORTER, "azure_monitor_opentelemetry_exporter" - ) - environ.setdefault( - OTEL_TRACES_EXPORTER, "azure_monitor_opentelemetry_exporter" - ) + try: + AzureDiagnosticLogging.enable(_logger) + AzureDiagnosticLogging.enable(_opentelemetry_logger) + # TODO: Enabled when duplicate logging issue is solved + # if _EXPORTER_DIAGNOSTICS_ENABLED: + # exporter_logger = logging.getLogger( + # "azure.monitor.opentelemetry.exporter" + # ) + # AzureDiagnosticLogging.enable(_exporter_logger) + # TODO: Uncomment when logging is out of preview + # environ.setdefault(OTEL_LOGS_EXPORTER, + # "azure_monitor_opentelemetry_exporter") + environ.setdefault( + OTEL_METRICS_EXPORTER, "azure_monitor_opentelemetry_exporter" + ) + environ.setdefault( + OTEL_TRACES_EXPORTER, "azure_monitor_opentelemetry_exporter" + ) + _logger.info( + "Azure Monitor OpenTelemetry Distro configured successfully." + ) + except Exception as exc: + _logger.error( + "Azure Monitor OpenTelemetry Distro failed during " + + f"configuration: {exc}" + ) + raise exc diff --git a/azure-monitor-opentelemetry-distro/tests/test_constants.py b/azure-monitor-opentelemetry-distro/tests/test_constants.py new file mode 100644 index 00000000..d887435e --- /dev/null +++ b/azure-monitor-opentelemetry-distro/tests/test_constants.py @@ -0,0 +1,149 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License in the project root for +# license information. +# -------------------------------------------------------------------------- + +from importlib import reload +from os import environ +from unittest import TestCase +from unittest.mock import patch + +from azure.monitor.opentelemetry.distro import _constants + +TEST_VALUE = "TEST_VALUE" +TEST_IKEY = "1234abcd-ab12-34cd-ab12-a23456abcdef" +TEST_CONN_STR = f"InstrumentationKey={TEST_IKEY};IngestionEndpoint=https://centralus-2.in.applicationinsights.azure.com/;LiveEndpoint=https://centralus.livediagnostics.monitor.azure.com/" + + +def clear_env_var(env_var): + if env_var in environ: + del environ[env_var] + + +class TestConstants(TestCase): + @patch.dict( + "os.environ", + {"ApplicationInsightsAgent_EXTENSION_VERSION": TEST_VALUE}, + ) + def test_extension_version(self): + reload(_constants) + self.assertEqual(_constants._EXTENSION_VERSION, TEST_VALUE) + + def test_extension_version_default(self): + clear_env_var("ApplicationInsightsAgent_EXTENSION_VERSION") + reload(_constants) + self.assertEqual(_constants._EXTENSION_VERSION, "disabled") + + @patch.dict( + "os.environ", {"APPLICATIONINSIGHTS_CONNECTION_STRING": TEST_CONN_STR} + ) + def test_ikey(self): + reload(_constants) + self.assertEqual(_constants._CUSTOMER_IKEY, TEST_IKEY) + + def test_ikey_defaults(self): + clear_env_var("APPLICATIONINSIGHTS_CONNECTION_STRING") + reload(_constants) + self.assertEqual(_constants._CUSTOMER_IKEY, "unknown") + + # TODO: Enabled when duplciate logging issue is solved + # @patch.dict( + # "os.environ", + # {"AZURE_MONITOR_OPENTELEMETRY_DISTRO_ENABLE_EXPORTER_DIAGNOSTICS": "True"}, + # ) + # def test_exporter_diagnostics_enabled(self): + # reload(_constants) + # self.assertTrue(_constants._EXPORTER_DIAGNOSTICS_ENABLED) + + # def test_exporter_diagnostics_disabled(self): + # clear_env_var("AZURE_MONITOR_OPENTELEMETRY_DISTRO_ENABLE_EXPORTER_DIAGNOSTICS") + # reload(_constants) + # self.assertFalse(_constants._EXPORTER_DIAGNOSTICS_ENABLED) + + # @patch.dict( + # "os.environ", + # {"AZURE_MONITOR_OPENTELEMETRY_DISTRO_ENABLE_EXPORTER_DIAGNOSTICS": "foobar"}, + # ) + # def test_exporter_diagnostics_other(self): + # reload(_constants) + # self.assertFalse(_constants._EXPORTER_DIAGNOSTICS_ENABLED) + + @patch.dict("os.environ", {"WEBSITE_SITE_NAME": TEST_VALUE}) + def test_diagnostics_enabled(self): + reload(_constants) + self.assertTrue(_constants._IS_DIAGNOSTICS_ENABLED) + + def test_diagnostics_disabled(self): + clear_env_var("WEBSITE_SITE_NAME") + reload(_constants) + self.assertFalse(_constants._IS_DIAGNOSTICS_ENABLED) + + @patch( + "azure.monitor.opentelemetry.distro._constants.platform.system", + return_value="Linux", + ) + def test_log_path_linux(self, mock_system): + self.assertEqual( + _constants._get_log_path(), "/var/log/applicationinsights" + ) + + @patch( + "azure.monitor.opentelemetry.distro._constants.platform.system", + return_value="Linux", + ) + def test_status_log_path_linux(self, mock_system): + self.assertEqual( + _constants._get_log_path(status_log_path=True), + "/var/log/applicationinsights", + ) + + @patch( + "azure.monitor.opentelemetry.distro._constants.platform.system", + return_value="Windows", + ) + @patch("pathlib.Path.home", return_value="\\HOME\\DIR") + def test_log_path_windows(self, mock_system, mock_home): + self.assertEqual( + _constants._get_log_path(), + "\\HOME\\DIR\\LogFiles\\ApplicationInsights", + ) + + @patch( + "azure.monitor.opentelemetry.distro._constants.platform.system", + return_value="Windows", + ) + @patch("pathlib.Path.home", return_value="\\HOME\\DIR") + def test_status_log_path_windows(self, mock_system, mock_home): + self.assertEqual( + _constants._get_log_path(status_log_path=True), + "\\HOME\\DIR\\LogFiles\\ApplicationInsights\\status", + ) + + @patch( + "azure.monitor.opentelemetry.distro._constants.platform.system", + return_value="Window", + ) + def test_log_path_other(self, mock_platform): + self.assertIsNone(_constants._get_log_path()) + + @patch( + "azure.monitor.opentelemetry.distro._constants.platform.system", + return_value="linux", + ) + def test_status_log_path_other(self, mock_platform): + self.assertIsNone(_constants._get_log_path(status_log_path=True)) + + @patch.dict("os.environ", {"key": "value"}) + def test_env_var_or_default(self): + self.assertEqual(_constants._env_var_or_default("key"), "value") + + @patch.dict("os.environ", {}) + def test_env_var_or_default_empty(self): + self.assertEqual(_constants._env_var_or_default("key"), "") + + @patch.dict("os.environ", {}) + def test_env_var_or_default_empty_with_defaults(self): + self.assertEqual( + _constants._env_var_or_default("key", default_val="value"), "value" + ) diff --git a/azure-monitor-opentelemetry-distro/tests/test_diagnostic_logging.py b/azure-monitor-opentelemetry-distro/tests/test_diagnostic_logging.py new file mode 100644 index 00000000..9a9beb15 --- /dev/null +++ b/azure-monitor-opentelemetry-distro/tests/test_diagnostic_logging.py @@ -0,0 +1,206 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License in the project root for +# license information. +# -------------------------------------------------------------------------- + +import logging +from importlib import reload +from json import loads +from os.path import join +from pathlib import Path +from unittest import TestCase +from unittest.mock import patch + +import azure.monitor.opentelemetry.distro._diagnostic_logging as diagnostic_logger + +TEST_LOGGER_PATH = str(Path.home()) +TEST_DIAGNOSTIC_LOGGER_FILE_NAME = "test-applicationinsights-extension.log" +TEST_DIAGNOSTIC_LOGGER_LOCATION = join( + TEST_LOGGER_PATH, TEST_DIAGNOSTIC_LOGGER_FILE_NAME +) +TEST_SITE_NAME = "TEST_SITE_NAME" +TEST_CUSTOMER_IKEY = "TEST_CUSTOMER_IKEY" +TEST_EXTENSION_VERSION = "TEST_EXTENSION_VERSION" +TEST_VERSION = "TEST_VERSION" +TEST_SUBSCRIPTION_ID_ENV_VAR = "TEST_SUBSCRIPTION_ID+TEST_SUBSCRIPTION_ID" +TEST_SUBSCRIPTION_ID = "TEST_SUBSCRIPTION_ID" +MESSAGE1 = "MESSAGE1" +MESSAGE2 = "MESSAGE2" +MESSAGE3 = "MESSAGE3" +TEST_LOGGER_NAME = "test.logger.name" +TEST_LOGGER = logging.getLogger(TEST_LOGGER_NAME) +TEST_LOGGER_NAME_SUB_MODULE = TEST_LOGGER_NAME + ".sub.module" +TEST_LOGGER_SUB_MODULE = logging.getLogger(TEST_LOGGER_NAME_SUB_MODULE) + + +def clear_file(): + with open(TEST_DIAGNOSTIC_LOGGER_LOCATION, "w") as f: + f.seek(0) + f.truncate() + + +def check_file_for_messages( + level, messages, logger_name=TEST_LOGGER_NAME_SUB_MODULE +): + with open(TEST_DIAGNOSTIC_LOGGER_LOCATION, "r") as f: + f.seek(0) + for message in messages: + json = loads(f.readline()) + assert json["time"] + assert json["level"] == level + assert json["logger"] == logger_name + assert json["message"] == message + properties = json["properties"] + assert properties["operation"] == "Startup" + assert properties["sitename"] == TEST_SITE_NAME + assert properties["ikey"] == TEST_CUSTOMER_IKEY + assert properties["extensionVersion"] == TEST_EXTENSION_VERSION + assert properties["sdkVersion"] == TEST_VERSION + assert properties["subscriptionId"] == TEST_SUBSCRIPTION_ID + assert not f.read() + + +def check_file_is_empty(): + with open(TEST_DIAGNOSTIC_LOGGER_LOCATION, "r") as f: + f.seek(0) + assert not f.read() + + +def set_up( + is_diagnostics_enabled, + logger=TEST_LOGGER, + subscription_id_env_var=TEST_SUBSCRIPTION_ID_ENV_VAR, +) -> None: + clear_file() + check_file_is_empty() + diagnostic_logger._logger.handlers.clear() + logger.handlers.clear() + TEST_LOGGER.handlers.clear() + TEST_LOGGER_SUB_MODULE.handlers.clear() + patch.dict( + "os.environ", + { + "WEBSITE_SITE_NAME": TEST_SITE_NAME, + "WEBSITE_OWNER_NAME": subscription_id_env_var, + }, + ).start() + reload(diagnostic_logger) + assert not diagnostic_logger.AzureDiagnosticLogging._initialized + patch( + "azure.monitor.opentelemetry.distro._diagnostic_logging._DIAGNOSTIC_LOG_PATH", + TEST_LOGGER_PATH, + ).start() + patch( + "azure.monitor.opentelemetry.distro._diagnostic_logging._DIAGNOSTIC_LOGGER_FILE_NAME", + TEST_DIAGNOSTIC_LOGGER_FILE_NAME, + ).start() + patch( + "azure.monitor.opentelemetry.distro._diagnostic_logging._CUSTOMER_IKEY", + TEST_CUSTOMER_IKEY, + ).start() + patch( + "azure.monitor.opentelemetry.distro._diagnostic_logging._EXTENSION_VERSION", + TEST_EXTENSION_VERSION, + ).start() + patch( + "azure.monitor.opentelemetry.distro._diagnostic_logging.VERSION", + TEST_VERSION, + ).start() + patch( + "azure.monitor.opentelemetry.distro._diagnostic_logging._IS_DIAGNOSTICS_ENABLED", + is_diagnostics_enabled, + ).start() + diagnostic_logger.AzureDiagnosticLogging.enable(logger) + + +class TestDiagnosticLogger(TestCase): + def test_initialized(self): + set_up(is_diagnostics_enabled=True) + self.assertTrue(diagnostic_logger.AzureDiagnosticLogging._initialized) + + def test_uninitialized(self): + set_up(is_diagnostics_enabled=False) + self.assertFalse(diagnostic_logger.AzureDiagnosticLogging._initialized) + + def test_info(self): + set_up(is_diagnostics_enabled=True) + TEST_LOGGER_SUB_MODULE.info(MESSAGE1) + TEST_LOGGER_SUB_MODULE.info(MESSAGE2) + check_file_is_empty() + + def test_info_with_info_log_level(self): + set_up(is_diagnostics_enabled=True) + TEST_LOGGER_SUB_MODULE.setLevel(logging.INFO) + TEST_LOGGER_SUB_MODULE.info(MESSAGE1) + TEST_LOGGER_SUB_MODULE.info(MESSAGE2) + TEST_LOGGER_SUB_MODULE.setLevel(logging.NOTSET) + check_file_for_messages("INFO", (MESSAGE1, MESSAGE2)) + + def test_info_with_sub_module_info_log_level(self): + set_up(is_diagnostics_enabled=True) + TEST_LOGGER_SUB_MODULE.setLevel(logging.INFO) + TEST_LOGGER_SUB_MODULE.info(MESSAGE1) + TEST_LOGGER_SUB_MODULE.info(MESSAGE2) + TEST_LOGGER_SUB_MODULE.setLevel(logging.NOTSET) + check_file_for_messages("INFO", (MESSAGE1, MESSAGE2)) + + def test_warning(self): + set_up(is_diagnostics_enabled=True) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE1) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE2) + check_file_for_messages("WARNING", (MESSAGE1, MESSAGE2)) + + def test_error(self): + set_up(is_diagnostics_enabled=True) + TEST_LOGGER_SUB_MODULE.error(MESSAGE1) + TEST_LOGGER_SUB_MODULE.error(MESSAGE2) + check_file_for_messages("ERROR", (MESSAGE1, MESSAGE2)) + + def test_off_app_service_info(self): + set_up(is_diagnostics_enabled=False) + TEST_LOGGER.info(MESSAGE1) + TEST_LOGGER.info(MESSAGE2) + TEST_LOGGER_SUB_MODULE.info(MESSAGE1) + TEST_LOGGER_SUB_MODULE.info(MESSAGE2) + check_file_is_empty() + + def test_off_app_service_warning(self): + set_up(is_diagnostics_enabled=False) + TEST_LOGGER.warning(MESSAGE1) + TEST_LOGGER.warning(MESSAGE2) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE1) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE2) + check_file_is_empty() + + def test_off_app_service_error(self): + set_up(is_diagnostics_enabled=False) + TEST_LOGGER.error(MESSAGE1) + TEST_LOGGER.error(MESSAGE2) + TEST_LOGGER_SUB_MODULE.error(MESSAGE1) + TEST_LOGGER_SUB_MODULE.error(MESSAGE2) + check_file_is_empty() + + def test_subscription_id_plus(self): + set_up( + is_diagnostics_enabled=True, + subscription_id_env_var=TEST_SUBSCRIPTION_ID_ENV_VAR, + ) + self.assertEqual( + diagnostic_logger._SUBSCRIPTION_ID, TEST_SUBSCRIPTION_ID + ) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE1) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE2) + check_file_for_messages("WARNING", (MESSAGE1, MESSAGE2)) + + def test_subscription_id_no_plus(self): + set_up( + is_diagnostics_enabled=True, + subscription_id_env_var=TEST_SUBSCRIPTION_ID, + ) + self.assertEqual( + diagnostic_logger._SUBSCRIPTION_ID, TEST_SUBSCRIPTION_ID + ) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE1) + TEST_LOGGER_SUB_MODULE.warning(MESSAGE2) + check_file_for_messages("WARNING", (MESSAGE1, MESSAGE2)) diff --git a/azure-monitor-opentelemetry-distro/tests/test_distro.py b/azure-monitor-opentelemetry-distro/tests/test_distro.py new file mode 100644 index 00000000..50a4f530 --- /dev/null +++ b/azure-monitor-opentelemetry-distro/tests/test_distro.py @@ -0,0 +1,32 @@ +from unittest import TestCase +from unittest.mock import patch + +from azure.monitor.opentelemetry.distro.distro import AzureMonitorDistro + + +class TestDistro(TestCase): + @patch( + "azure.monitor.opentelemetry.distro.distro.AzureDiagnosticLogging.enable" + ) + # TODO: Enabled when duplciate logging issue is solved + # @patch( + # "azure.monitor.opentelemetry.distro._diagnostic_logging._EXPORTER_DIAGNOSTICS_ENABLED", + # False, + # ) + def test_configure(self, mock_diagnostics): + distro = AzureMonitorDistro() + distro.configure() + self.assertEqual(mock_diagnostics.call_count, 2) + + # TODO: Enabled when duplciate logging issue is solved + # @patch( + # "azure.monitor.opentelemetry.distro.distro.AzureDiagnosticLogging.enable" + # ) + # @patch( + # "azure.monitor.opentelemetry.distro._diagnostic_logging._EXPORTER_DIAGNOSTICS_ENABLED", + # True, + # ) + # def test_configure_exporter_diagnostics(self, mock_diagnostics): + # distro = AzureMonitorDistro() + # distro.configure() + # self.assertEqual(mock_diagnostics.call_count, 3) diff --git a/test-requirements.txt b/test-requirements.txt index e079f8a6..9d908300 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1 +1,4 @@ pytest +psycopg2 +flask +requests \ No newline at end of file