Repository: microsoft/AzureTRE

Issue:
[BUG] Resource processor outputs duplicate log items
**Describe the bug**
The VMSS resource processor outputs many duplicate log items (some twice, some 3 times, 4, etc.)

**Steps to reproduce**

1. Make a query in app insights and look for rolename=runner.py
2. Make actions that require the RP to do something - create a workspace for instance
3. See that some of the logs entries appear multiple times


Discussion:

Resolving patch:
diff --git a/resource_processor/shared/logging.py b/resource_processor/shared/logging.py
--- a/resource_processor/shared/logging.py
+++ b/resource_processor/shared/logging.py
@@ -40,6 +40,7 @@ def initialize_logging(logging_level: int, correlation_id: str) -> logging.Logge
     """
     Adds the Application Insights handler for the root logger and sets the given logging level.
     Creates and returns a logger adapter that integrates the correlation ID, if given, to the log messages.
+    Note: This should be called only once, otherwise duplicate log entries could be produced.
 
     :param logging_level: The logging level to set e.g., logging.WARNING.
     :param correlation_id: Optional. The correlation ID that is passed on to the operation_Id in App Insights.
@@ -68,3 +69,21 @@ def initialize_logging(logging_level: int, correlation_id: str) -> logging.Logge
     adapter.debug(f"Logger adapter initialized with extra: {extra}")
 
     return adapter
+
+
+def get_message_id_logger(correlation_id: str) -> logging.LoggerAdapter:
+    """
+    Gets a logger that includes message id for easy correlation between log entries.
+    :param correlation_id: Optional. The correlation ID that is passed on to the operation_Id in App Insights.
+    :returns: A modified logger adapter (from the original initiated one).
+    """
+    logger = logging.getLogger()
+    extra = None
+
+    if correlation_id:
+        extra = {'traceId': correlation_id}
+
+    adapter = logging.LoggerAdapter(logger, extra)
+    adapter.debug(f"Logger adapter now includes extra: {extra}")
+
+    return adapter
diff --git a/resource_processor/vmss_porter/runner.py b/resource_processor/vmss_porter/runner.py
--- a/resource_processor/vmss_porter/runner.py
+++ b/resource_processor/vmss_porter/runner.py
@@ -5,7 +5,7 @@
 import asyncio
 import logging
 
-from shared.logging import disable_unwanted_loggers, initialize_logging  # pylint: disable=import-error # noqa
+from shared.logging import disable_unwanted_loggers, initialize_logging, get_message_id_logger  # pylint: disable=import-error # noqa
 from resources import strings  # pylint: disable=import-error # noqa
 from contextlib import asynccontextmanager
 from azure.servicebus import ServiceBusMessage
@@ -199,7 +199,7 @@ async def runner(env_vars):
             try:
                 async for message in receive_message_gen:
                     logger_adapter.info(f"Message received for id={message['id']}")
-                    message_logger_adapter = initialize_logging(logging.INFO, message['id'])
+                    message_logger_adapter = get_message_id_logger(message['id'])  # logger includes message id in every entry.
                     result = await deploy_porter_bundle(message, service_bus_client, env_vars, message_logger_adapter)
                     await receive_message_gen.asend(result)
             except StopAsyncIteration:  # the async generator when finished signals end with this exception.


Test patch: