From f424399862aef065c4fb493d5ced7f952f1945a9 Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Thu, 6 Nov 2025 11:29:14 -0800 Subject: [PATCH 1/9] Outline of changes --- .../microsoft_agents/activity/__init__.py | 2 +- .../microsoft_agents/activity/config/__init__.py | 0 .../microsoft_agents/activity/config/_configure_logging.py | 4 ++++ .../activity/{ => config}/_load_configuration.py | 0 4 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py create mode 100644 libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py rename libraries/microsoft-agents-activity/microsoft_agents/activity/{ => config}/_load_configuration.py (100%) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py index b18336b7..a8499754 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py @@ -101,7 +101,7 @@ from .channel_adapter_protocol import ChannelAdapterProtocol from .turn_context_protocol import TurnContextProtocol -from ._load_configuration import load_configuration_from_env +from .config._load_configuration import load_configuration_from_env __all__ = [ "AgentsModel", diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py new file mode 100644 index 00000000..60296916 --- /dev/null +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -0,0 +1,4 @@ +import logging + +def configure_logging(): + pass \ No newline at end of file diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/_load_configuration.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_load_configuration.py similarity index 100% rename from libraries/microsoft-agents-activity/microsoft_agents/activity/_load_configuration.py rename to libraries/microsoft-agents-activity/microsoft_agents/activity/config/_load_configuration.py From c44287a2ade590eb226fe2c2c52c0ba1b74be286 Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Tue, 11 Nov 2025 08:03:29 -0800 Subject: [PATCH 2/9] Adding logging configuration handling when loading configuration --- .../microsoft_agents/activity/__init__.py | 2 +- .../activity/config/__init__.py | 8 ++++ .../activity/config/_configure_logging.py | 40 ++++++++++++++++++- .../activity/config/_load_configuration.py | 4 ++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py index a8499754..7311abf2 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py @@ -101,7 +101,7 @@ from .channel_adapter_protocol import ChannelAdapterProtocol from .turn_context_protocol import TurnContextProtocol -from .config._load_configuration import load_configuration_from_env +from .config import load_configuration_from_env __all__ = [ "AgentsModel", diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py index e69de29b..73eadc2b 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/__init__.py @@ -0,0 +1,8 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +from ._load_configuration import load_configuration_from_env + +__all__ = [ + "load_configuration_from_env", +] diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index 60296916..6dbd9456 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -1,4 +1,40 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + import logging -def configure_logging(): - pass \ No newline at end of file + +def _configure_logging(logging_config: dict): + """Configures logging based on the provided logging configuration dictionary. + + :param logging_config: A dictionary containing logging configuration. + :raises ValueError: If an invalid log level is provided in the configuration. + """ + + levels_map = logging.getLevelNamesMapping() + + log_levels = logging_config.get("LOGLEVEL", {}) + + for key in log_levels.keys(): + level_name = log_levels[key].upper() + if level_name == "INFORMATION": # .NET parity + level_name = "INFO" + level = levels_map.get(level_name) + if not level: + raise ValueError(f"Invalid configured log level: {level_name}") + + console_handler = logging.StreamHandler() + console_handler.setFormatter( + logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + ) + ) + + namespace = key.lower() + if namespace == "default": + logger = logging.getLogger() + else: + logger = logging.getLogger(namespace) + + logger.addHandler(console_handler) + logger.setLevel(level) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_load_configuration.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_load_configuration.py index cfc8a420..ef0de9f3 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_load_configuration.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_load_configuration.py @@ -3,6 +3,8 @@ from typing import Any +from ._configure_logging import _configure_logging + def load_configuration_from_env(env_vars: dict[str, Any]) -> dict: """ @@ -26,6 +28,8 @@ def load_configuration_from_env(env_vars: dict[str, Any]) -> dict: conn for conn in result.get("CONNECTIONSMAP", {}).values() ] + _configure_logging(result.get("LOGGING", {})) + return { "AGENTAPPLICATION": result.get("AGENTAPPLICATION", {}), "CONNECTIONS": result.get("CONNECTIONS", {}), From 7712b933508a0482ec7ae62006cf4f21228f43d6 Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Tue, 11 Nov 2025 08:15:57 -0800 Subject: [PATCH 3/9] name to level mapping fix for Python 3.10 --- .../activity/config/_configure_logging.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index 6dbd9456..78d77be3 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -3,6 +3,20 @@ import logging +# in Python 3.11, we can move to using +# logging.getLevelNamesMapping() +_NAME_TO_LEVEL = { + "CRITICAL": logging.CRITICAL, + "FATAL": logging.FATAL, + "ERROR": logging.ERROR, + "WARN": logging.WARNING, + "WARNING": logging.WARNING, + "INFO": logging.INFO, + "INFORMATION": logging.INFO, # .NET parity + "DEBUG": logging.DEBUG, + "NOTSET": logging.NOTSET, +} + def _configure_logging(logging_config: dict): """Configures logging based on the provided logging configuration dictionary. @@ -11,15 +25,13 @@ def _configure_logging(logging_config: dict): :raises ValueError: If an invalid log level is provided in the configuration. """ - levels_map = logging.getLevelNamesMapping() - log_levels = logging_config.get("LOGLEVEL", {}) for key in log_levels.keys(): level_name = log_levels[key].upper() if level_name == "INFORMATION": # .NET parity level_name = "INFO" - level = levels_map.get(level_name) + level = _NAME_TO_LEVEL.get(level_name) if not level: raise ValueError(f"Invalid configured log level: {level_name}") From 44c07317252e089ff0aeb7088797a2608a229226 Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Tue, 11 Nov 2025 08:21:26 -0800 Subject: [PATCH 4/9] Code feedback changes --- .../microsoft_agents/activity/config/_configure_logging.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index 78d77be3..49d04d01 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -29,10 +29,8 @@ def _configure_logging(logging_config: dict): for key in log_levels.keys(): level_name = log_levels[key].upper() - if level_name == "INFORMATION": # .NET parity - level_name = "INFO" level = _NAME_TO_LEVEL.get(level_name) - if not level: + if level is None: raise ValueError(f"Invalid configured log level: {level_name}") console_handler = logging.StreamHandler() @@ -48,5 +46,6 @@ def _configure_logging(logging_config: dict): else: logger = logging.getLogger(namespace) + logger.handlers.clear() # Remove existing handlers to prevent duplicates logger.addHandler(console_handler) logger.setLevel(level) From dccf8aed77c817ab4c9777c66c6fed1d8e271ed2 Mon Sep 17 00:00:00 2001 From: rodrigobr-msft Date: Thu, 13 Nov 2025 07:05:20 -0800 Subject: [PATCH 5/9] Update libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../microsoft_agents/activity/config/_configure_logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index 49d04d01..a5b9c3e1 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -27,7 +27,7 @@ def _configure_logging(logging_config: dict): log_levels = logging_config.get("LOGLEVEL", {}) - for key in log_levels.keys(): + for key in log_levels: level_name = log_levels[key].upper() level = _NAME_TO_LEVEL.get(level_name) if level is None: From 6a4ac08fb4e61bb63d3452da1fded14bbda2ecde Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Thu, 13 Nov 2025 07:08:04 -0800 Subject: [PATCH 6/9] Small changes --- .../activity/config/_configure_logging.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index a5b9c3e1..dce7c192 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -27,19 +27,19 @@ def _configure_logging(logging_config: dict): log_levels = logging_config.get("LOGLEVEL", {}) + console_handler = logging.StreamHandler() + console_handler.setFormatter( + logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + ) + ) + for key in log_levels: level_name = log_levels[key].upper() level = _NAME_TO_LEVEL.get(level_name) if level is None: raise ValueError(f"Invalid configured log level: {level_name}") - console_handler = logging.StreamHandler() - console_handler.setFormatter( - logging.Formatter( - "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" - ) - ) - namespace = key.lower() if namespace == "default": logger = logging.getLogger() From 8bb10c50e8961efc81549fbf1ff0bb54e66d905d Mon Sep 17 00:00:00 2001 From: rodrigobr-msft Date: Thu, 13 Nov 2025 07:10:09 -0800 Subject: [PATCH 7/9] Update libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../microsoft_agents/activity/config/_configure_logging.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index dce7c192..690f02d7 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -38,7 +38,9 @@ def _configure_logging(logging_config: dict): level_name = log_levels[key].upper() level = _NAME_TO_LEVEL.get(level_name) if level is None: - raise ValueError(f"Invalid configured log level: {level_name}") + raise ValueError( + f"Invalid configured log level: {level_name}. Valid levels are: {', '.join(_NAME_TO_LEVEL.keys())}" + ) namespace = key.lower() if namespace == "default": From 0f860d8903f1457d8187adbaa62fb8bc0506e1f9 Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Tue, 25 Nov 2025 12:39:05 -0800 Subject: [PATCH 8/9] Creating ConfigurationErrorResources for microsoft-agents-activity --- .../activity/config/_configure_logging.py | 8 ++++++-- .../microsoft_agents/activity/errors/__init__.py | 11 +++++++++-- .../activity/errors/error_resources.py | 12 ++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index 690f02d7..c493ba89 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -3,6 +3,8 @@ import logging +from ..errors import configuration_errors + # in Python 3.11, we can move to using # logging.getLevelNamesMapping() _NAME_TO_LEVEL = { @@ -39,8 +41,10 @@ def _configure_logging(logging_config: dict): level = _NAME_TO_LEVEL.get(level_name) if level is None: raise ValueError( - f"Invalid configured log level: {level_name}. Valid levels are: {', '.join(_NAME_TO_LEVEL.keys())}" - ) + configuration_errors.InvalidLoggingConfiguration.format( + key, level_name + ) + ) namespace = key.lower() if namespace == "default": diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py index 90283f53..f692c875 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py @@ -6,9 +6,16 @@ """ from .error_message import ErrorMessage -from .error_resources import ActivityErrorResources +from .error_resources import ActivityErrorResources, ConfigurationErrorResources # Singleton instance activity_errors = ActivityErrorResources() +configuration_errors = ConfigurationErrorResources() -__all__ = ["ErrorMessage", "ActivityErrorResources", "activity_errors"] +__all__ = [ + "ErrorMessage", + "ActivityErrorResources", + "ConfigurationErrorResources", + "activity_errors", + "configuration_errors" +] \ No newline at end of file diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py index 0b0b68e9..4cad7495 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py @@ -50,3 +50,15 @@ class ActivityErrorResources: def __init__(self): """Initialize ActivityErrorResources.""" pass + +class ConfigurationErrorResources: + """ + Error messages for environment configuration operations. + + Error codes are organized in the range -66000 to -66999. + """ + + InvalidLoggingConfiguration = ErrorMessage( + "Invalid logging level configured: {0} = {1}", + -66011, + ) \ No newline at end of file From f35009f94db36e561c912fbd010adff712ed3566 Mon Sep 17 00:00:00 2001 From: Rodrigo Brandao Date: Tue, 25 Nov 2025 12:41:29 -0800 Subject: [PATCH 9/9] Pulling from remote --- .../microsoft_agents/activity/config/_configure_logging.py | 6 ++---- .../microsoft_agents/activity/errors/__init__.py | 4 ++-- .../microsoft_agents/activity/errors/error_resources.py | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index c493ba89..eb76594e 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -41,10 +41,8 @@ def _configure_logging(logging_config: dict): level = _NAME_TO_LEVEL.get(level_name) if level is None: raise ValueError( - configuration_errors.InvalidLoggingConfiguration.format( - key, level_name - ) - ) + configuration_errors.InvalidLoggingConfiguration.format(key, level_name) + ) namespace = key.lower() if namespace == "default": diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py index f692c875..a9f63d69 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/__init__.py @@ -17,5 +17,5 @@ "ActivityErrorResources", "ConfigurationErrorResources", "activity_errors", - "configuration_errors" -] \ No newline at end of file + "configuration_errors", +] diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py index 4cad7495..455f7bc4 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/errors/error_resources.py @@ -51,6 +51,7 @@ def __init__(self): """Initialize ActivityErrorResources.""" pass + class ConfigurationErrorResources: """ Error messages for environment configuration operations. @@ -61,4 +62,4 @@ class ConfigurationErrorResources: InvalidLoggingConfiguration = ErrorMessage( "Invalid logging level configured: {0} = {1}", -66011, - ) \ No newline at end of file + )