Repository: MatterMiners/tardis

Issue:
[RFC] Log levels in COBalD / TARDIS
Hi together,

it is currently unclear to me which log levels best to use for "production" and "debugging". 

We are right now running with log level `INFO`, but are flooded with hundreds of lines with "Ressource attributes" and "Drone" information during each status update, this becomes rather heavy with many drones. 

At the same time, the default log level of the ["Logger" decorator](https://github.com/MatterMiners/cobald/blob/master/src/cobald/decorator/logger.py) in COBalD (which logs the changes, which might be interesting also for log analysis) is "INFO". 

So I wonder if:
- the log level to use for production should be "WARN", but then we'd also lose the "changes" logger unless we reconfigure its log level
- some of the messages currently printed with "INFO" should be tuned down to "DEBUG". 

For the latter point, I'm thinking for example about these messages:
https://github.com/MatterMiners/tardis/commit/05c30e93f3ccad938a5ca3970647d0784f864f85

What is the general consensus, is there already a clear idea in mind what the log levels should mean? 
From my naïve "syslog"-like point of view, I would go with the latter option. 

Discussion:
eileen-kuehn: Oh that is great! I am really looking forward on how practical this is going to be. If it is as good as expected, we should also go for it in other projects! :)

Patch:
diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst
index d9dc66d..d7667ed 100644
--- a/docs/source/changelog.rst
+++ b/docs/source/changelog.rst
@@ -1,4 +1,4 @@
-.. Created by changelog.py at 2020-05-18, command
+.. Created by changelog.py at 2020-05-25, command
    '/Users/giffler/.cache/pre-commit/repont7o94ca/py_env-default/bin/changelog docs/source/changes compile --output=docs/source/changelog.rst'
    based on the format of 'https://keepachangelog.com/'
 
@@ -32,7 +32,7 @@ Fixed
 * Fix state transitions for jobs retried by HTCondor
 * Fix state transitions and refactoring of the SLURM site adapter
 
-[Unreleased] - 2020-05-18
+[Unreleased] - 2020-05-25
 =========================
 
 Added
@@ -44,5 +44,6 @@ Added
 Changed
 -------
 
+* Added log channels and adjusted log levels according to the conventions in `COBalD` documentation
 * The Moab adapter can now be configured to use different startup commands for each machine type.
 * The SLURM adapter can now be configured to use different startup commands for each machine type.
diff --git a/docs/source/changes/146.improve_logging.yaml b/docs/source/changes/146.improve_logging.yaml
new file mode 100644
index 0000000..89f7c18
--- /dev/null
+++ b/docs/source/changes/146.improve_logging.yaml
@@ -0,0 +1,9 @@
+category: changed
+summary: Added log channels and adjusted log levels according to the conventions in `COBalD` documentation
+pull requests:
+  - 146
+issues:
+  - 137
+description: |
+  Added log channels and adjusted log levels according to the conventions in the `COBalD` documentation.
+  This will improve the user's ability to filter log messages according their needs.
diff --git a/tardis/adapters/batchsystems/htcondor.py b/tardis/adapters/batchsystems/htcondor.py
index 5cf6faf..aa7c201 100644
--- a/tardis/adapters/batchsystems/htcondor.py
+++ b/tardis/adapters/batchsystems/htcondor.py
@@ -13,6 +13,8 @@ from shlex import quote
 from typing import Iterable
 import logging
 
+logger = logging.getLogger("cobald.runtime.tardis.adapters.batchsystem.htcondor")
+
 
 async def htcondor_status_updater(
     options: AttributeDict, attributes: AttributeDict
@@ -31,6 +33,7 @@ async def htcondor_status_updater(
     :return: Dictionary containing the output of the ``condor_status`` command
     :rtype: dict
     """
+
     attributes_string = f'-af:t {" ".join(attributes.values())}'
 
     options_string = htcondor_cmd_option_formatter(options)
@@ -43,7 +46,7 @@ async def htcondor_status_updater(
     htcondor_status = {}
 
     try:
-        logging.debug(f"HTCondor status update is running. Command: {cmd}")
+        logger.debug(f"HTCondor status update is running. Command: {cmd}")
         condor_status = await async_run_command(cmd)
         for row in htcondor_csv_parser(
             htcondor_input=condor_status,
@@ -55,11 +58,10 @@ async def htcondor_status_updater(
             htcondor_status[status_key] = row
 
     except CommandExecutionFailure as cef:
-        logging.error("condor_status could not be executed!")
-        logging.error(str(cef))
+        logger.warning(f"condor_status could not be executed due to {cef}!")
         raise
     else:
-        logging.debug("HTCondor status update finished.")
+        logger.debug("HTCondor status update finished.")
         return htcondor_status
 
 
@@ -136,11 +138,12 @@ class HTCondorAdapter(BatchSystemAdapter):
             if cef.exit_code == 1:
                 # exit code 1: HTCondor can't connect to StartD of Drone
                 # https://github.com/htcondor/htcondor/blob/master/src/condor_tools/drain.cpp  # noqa: B950
-                logging.debug(f"Draining failed with: {str(cef)}")
-                logging.debug(
-                    f"Probably drone {drone_uuid} is not available or already drained."
+                logger.warning(
+                    f"Draining failed with: {str(cef)}. Probably drone {drone_uuid}"
+                    " is not available or already drained."
                 )
                 return
+            logger.critical(f"Draining failed with: {str(cef)}.")
             raise cef
 
     async def integrate_machine(self, drone_uuid: str) -> None:
diff --git a/tardis/adapters/sites/cloudstack.py b/tardis/adapters/sites/cloudstack.py
index cc0e246..0cc02eb 100644
--- a/tardis/adapters/sites/cloudstack.py
+++ b/tardis/adapters/sites/cloudstack.py
@@ -20,6 +20,8 @@ from functools import partial
 import asyncio
 import logging
 
+logger = logging.getLogger("cobald.runtime.tardis.adapters.sites.cloudstack")
+
 
 class CloudStackAdapter(SiteAdapter):
     def __init__(self, machine_type: str, site_name: str):
@@ -61,7 +63,7 @@ class CloudStackAdapter(SiteAdapter):
         response = await self.cloud_stack_client.deployVirtualMachine(
             name=resource_attributes.drone_uuid, **self.machine_type_configuration
         )
-        logging.debug(f"{self.site_name} deployVirtualMachine returned {response}")
+        logger.debug(f"{self.site_name} deployVirtualMachine returned {response}")
         return self.handle_response(response["virtualmachine"])
 
     async def resource_status(
@@ -70,21 +72,21 @@ class CloudStackAdapter(SiteAdapter):
         response = await self.cloud_stack_client.listVirtualMachines(
             id=resource_attributes.remote_resource_uuid
         )
-        logging.debug(f"{self.site_name} listVirtualMachines returned {response}")
+        logger.debug(f"{self.site_name} listVirtualMachines returned {response}")
         return self.handle_response(response["virtualmachine"][0])
 
     async def stop_resource(self, resource_attributes: AttributeDict):
         response = await self.cloud_stack_client.stopVirtualMachine(
             id=resource_attributes.remote_resource_uuid
         )
-        logging.debug(f"{self.site_name} stopVirtualMachine returned {response}")
+        logger.debug(f"{self.site_name} stopVirtualMachine returned {response}")
         return response
 
     async def terminate_resource(self, resource_attributes: AttributeDict):
         response = await self.cloud_stack_client.destroyVirtualMachine(
             id=resource_attributes.remote_resource_uuid
         )
-        logging.debug(f"{self.site_name} destroyVirtualMachine returned {response}")
+        logger.debug(f"{self.site_name} destroyVirtualMachine returned {response}")
         return response
 
     @contextmanager
@@ -94,30 +96,26 @@ class CloudStackAdapter(SiteAdapter):
         except asyncio.TimeoutError as te:
             raise TardisTimeout from te
         except ClientConnectionError:
-            logging.info("Connection reset error")
+            logger.warning("Connection reset error")
             raise TardisResourceStatusUpdateFailed
         except CloudStackClientException as ce:
+            log_msg = (
+                f"Error code: {ce.error_code}, error text: {ce.error_text}, "
+                f"response: {ce.response}"
+            )
             if ce.error_code == 535:
-                logging.info("Quota exceeded")
-                logging.debug(str(ce))
+                logger.warning(f"Quota exceeded: {log_msg}")
                 raise TardisQuotaExceeded
             elif ce.error_code == 500:
-                logging.info(
-                    f"Error code: {ce.error_code}, error text: {ce.error_text}, "
-                    f"response: {ce.response}"
-                )
                 if "timed out" in ce.response["message"]:
-                    logging.debug(f"Timed out: {ce.response}")
+                    logger.warning(f"Timed out: {log_msg}")
                     raise TardisTimeout from ce
                 elif "connection was closed" in ce.response["message"]:
-                    logging.debug(f"Connection was closed: {ce.response}")
+                    logger.warning(f"Connection was closed: {log_msg}")
                     raise TardisResourceStatusUpdateFailed from ce
                 else:
-                    logging.debug(f"CloudStackClient response: {ce.response}")
+                    logger.critical(log_msg)
                     raise TardisError from ce
             else:
-                logging.info(
-                    f"Error code: {ce.error_code}, error text: {ce.error_text}, "
-                    f"response: {ce.response}"
-                )
+                logger.critical(log_msg)
                 raise TardisError from ce
diff --git a/tardis/adapters/sites/htcondor.py b/tardis/adapters/sites/htcondor.py
index 9042971..b2b67e0 100644
--- a/tardis/adapters/sites/htcondor.py
+++ b/tardis/adapters/sites/htcondor.py
@@ -18,6 +18,8 @@ from string import Template
 import logging
 import re
 
+logger = logging.getLogger("cobald.runtime.tardis.adapters.sites.htcondor")
+
 
 async def htcondor_queue_updater(executor):
     attributes = dict(
@@ -30,7 +32,7 @@ async def htcondor_queue_updater(executor):
     try:
         condor_queue = await executor.run_command(queue_command)
     except CommandExecutionFailure as cf:
-        logging.error(f"htcondor_queue_update failed: {cf}")
+        logger.warning(f"htcondor_queue_update failed: {cf}")
         raise
     else:
         for row in htcondor_csv_parser(
@@ -105,7 +107,7 @@ class HTCondorAdapter(SiteAdapter):
                 for key, value in self.machine_meta_data.items()
             }
         except KeyError as ke:
-            logging.error(f"deploy_resource failed: no translation known for {ke}")
+            logger.critical(f"deploy_resource failed: no translation known for {ke}")
             raise
         else:
             translated_meta_data["Uuid"] = resource_attributes.drone_uuid
diff --git a/tardis/adapters/sites/moab.py b/tardis/adapters/sites/moab.py
index cec43d0..fe2f889 100644
--- a/tardis/adapters/sites/moab.py
+++ b/tardis/adapters/sites/moab.py
@@ -22,10 +22,12 @@ import re
 import warnings
 from xml.dom import minidom
 
+logger = logging.getLogger("cobald.runtime.tardis.adapters.sites.moab")
+
 
 async def moab_status_updater(executor):
     cmd = "showq --xml -w user=$(whoami) && showq -c --xml -w user=$(whoami)"
-    logging.debug("Moab status update is running.")
+    logger.debug("Moab status update is running.")
     response = await executor.run_command(cmd)
     # combine two XML outputs to one
     xml_output = minidom.parseString(
@@ -41,7 +43,7 @@ async def moab_status_updater(executor):
                 "JobID": line.attributes["JobID"].value,
                 "State": line.attributes["State"].value,
             }
-    logging.debug("Moab status update completed")
+    logger.debug("Moab status update completed")
     return moab_resource_status
 
 
@@ -126,7 +128,7 @@ class MoabAdapter(SiteAdapter):
             f"{self._startup_command}"
         )
         result = await self._executor.run_command(request_command)
-        logging.debug(f"{self.site_name} servers create returned {result}")
+        logger.debug(f"{self.site_name} servers create returned {result}")
 
         remote_resource_uuid = int(result.stdout)
         resource_attributes.update(
@@ -172,7 +174,7 @@ class MoabAdapter(SiteAdapter):
                     "JobID": resource_attributes.remote_resource_uuid,
                     "State": "Completed",
                 }
-        logging.debug(f"{self.site_name} has status {resource_status}.")
+        logger.debug(f"{self.site_name} has status {resource_status}.")
         resource_attributes.update(updated=datetime.now())
         return convert_to_attribute_dict(
             {**resource_attributes, **self.handle_response(resource_status)}
@@ -184,7 +186,7 @@ class MoabAdapter(SiteAdapter):
             response = await self._executor.run_command(request_command)
         except CommandExecutionFailure as cf:
             if cf.exit_code == 1:
-                logging.debug(
+                logger.warning(
                     f"{self.site_name} servers terminate returned {cf.stdout}"
                 )
                 remote_resource_uuid = self.check_remote_resource_uuid(
@@ -195,7 +197,7 @@ class MoabAdapter(SiteAdapter):
             else:
                 raise cf
         else:
-            logging.debug(f"{self.site_name} servers terminate returned {response}")
+            logger.debug(f"{self.site_name} servers terminate returned {response}")
             remote_resource_uuid = self.check_remote_resource_uuid(
                 resource_attributes, r"^job \'(\d*)\' cancelled", response.stdout
             )
@@ -205,7 +207,7 @@ class MoabAdapter(SiteAdapter):
         )
 
     async def stop_resource(self, resource_attributes: AttributeDict):
-        logging.debug("MOAB jobs cannot be stopped gracefully. Terminating instead.")
+        logger.debug("MOAB jobs cannot be stopped gracefully. Terminating instead.")
         return await self.terminate_resource(resource_attributes)
 
     @contextmanager
@@ -215,7 +217,7 @@ class MoabAdapter(SiteAdapter):
         except TimeoutError as te:
             raise TardisTimeout from te
         except asyncssh.Error as exc:
-            logging.info("SSH connection failed: " + str(exc))
+            logger.warning("SSH connection failed: " + str(exc))
             raise TardisResourceStatusUpdateFailed
         except IndexError as ide:
             raise TardisResourceStatusUpdateFailed from ide
diff --git a/tardis/adapters/sites/openstack.py b/tardis/adapters/sites/openstack.py
index 6b5e0dc..177382c 100644
--- a/tardis/adapters/sites/openstack.py
+++ b/tardis/adapters/sites/openstack.py
@@ -22,6 +22,8 @@ from functools import partial
 
 import logging
 
+logger = logging.getLogger("cobald.runtime.tardis.adapters.sites.openstack")
+
 
 class OpenStackAdapter(SiteAdapter):
     def __init__(self, machine_type: str, site_name: str):
@@ -68,7 +70,7 @@ class OpenStackAdapter(SiteAdapter):
         specs.update(self.machine_type_configuration)
         await self.nova.init_api(timeout=60)
         response = await self.nova.servers.create(server=specs)
-        logging.debug(f"{self.site_name} servers create returned {response}")
+        logger.debug(f"{self.site_name} servers create returned {response}")
         return self.handle_response(response["server"])
 
     async def resource_status(
@@ -76,7 +78,7 @@ class OpenStackAdapter(SiteAdapter):
     ) -> AttributeDict:
         await self.nova.init_api(timeout=60)
         response = await self.nova.servers.get(resource_attributes.remote_resource_uuid)
-        logging.debug(f"{self.site_name} servers get returned {response}")
+        logger.debug(f"{self.site_name} servers get returned {response}")
         return self.handle_response(response["server"])
 
     async def stop_resource(self, resource_attributes: AttributeDict):
@@ -85,7 +87,7 @@ class OpenStackAdapter(SiteAdapter):
         response = await self.nova.servers.run_action(
             resource_attributes.remote_resource_uuid, **params
         )
-        logging.debug(f"{self.site_name} servers stop returned {response}")
+        logger.debug(f"{self.site_name} servers stop returned {response}")
         return response
 
     async def terminate_resource(self, resource_attributes: AttributeDict):
@@ -93,7 +95,7 @@ class OpenStackAdapter(SiteAdapter):
         response = await self.nova.servers.force_delete(
             resource_attributes.remote_resource_uuid
         )
-        logging.debug(f"{self.site_name} servers terminate returned {response}")
+        logger.debug(f"{self.site_name} servers terminate returned {response}")
         return response
 
     @contextmanager
@@ -105,13 +107,13 @@ class OpenStackAdapter(SiteAdapter):
         except AuthError as ae:
             raise TardisAuthError from ae
         except ContentTypeError:
-            logging.info("OpenStack: content Type Error")
+            logger.warning("OpenStack: content Type Error")
             raise TardisResourceStatusUpdateFailed
         except ClientError:
-            logging.info("REST client error")
+            logger.warning("REST client error")
             raise TardisDroneCrashed
         except ClientConnectionError:
-            logging.info("Connection reset error")
+            logger.warning("Connection reset error")
             raise TardisResourceStatusUpdateFailed
         except Exception as ex:
             raise TardisError from ex
diff --git a/tardis/adapters/sites/slurm.py b/tardis/adapters/sites/slurm.py
index bde12c0..a3a8fb5 100644
--- a/tardis/adapters/sites/slurm.py
+++ b/tardis/adapters/sites/slurm.py
@@ -21,6 +21,8 @@ import logging
 import re
 import warnings
 
+logger = logging.getLogger("cobald.runtime.tardis.adapters.sites.slurm")
+
 
 async def slurm_status_updater(executor):
     attributes = dict(JobId="%A", Host="%N", State="%T")
@@ -28,11 +30,11 @@ async def slurm_status_updater(executor):
     cmd = f'squeue -o "{attributes_string}" -h -t all'
 
     slurm_resource_status = {}
-    logging.debug("Slurm status update is started.")
+    logger.debug("Slurm status update is started.")
     try:
         slurm_status = await executor.run_command(cmd)
     except CommandExecutionFailure as cf:
-        logging.error(f"Slurm status update has failed due to {cf}.")
+        logger.warning(f"Slurm status update has failed due to {cf}.")
         raise
     else:
         for row in htcondor_csv_parser(
@@ -40,7 +42,7 @@ async def slurm_status_updater(executor):
         ):
             row["State"] = row["State"].strip()
             slurm_resource_status[row["JobId"]] = row
-        logging.debug("Slurm status update finished.")
+        logger.debug("Slurm status update finished.")
         return slurm_resource_status
 
 
@@ -115,7 +117,7 @@ class SlurmAdapter(SiteAdapter):
             f"{self._startup_command}"
         )
         result = await self._executor.run_command(request_command)
-        logging.debug(f"{self.site_name} sbatch returned {result}")
+        logger.debug(f"{self.site_name} sbatch returned {result}")
         pattern = re.compile(r"^Submitted batch job (\d*)", flags=re.MULTILINE)
         remote_resource_uuid = int(pattern.findall(result.stdout)[0])
         resource_attributes.update(
@@ -147,7 +149,7 @@ class SlurmAdapter(SiteAdapter):
                     "JobID": resource_attributes.remote_resource_uuid,
                     "State": "COMPLETED",
                 }
-        logging.debug(f"{self.site_name} has status {resource_status}.")
+        logger.debug(f"{self.site_name} has status {resource_status}.")
         resource_attributes.update(updated=datetime.now())
         return convert_to_attribute_dict(
             {**resource_attributes, **self.handle_response(resource_status)}
@@ -164,7 +166,7 @@ class SlurmAdapter(SiteAdapter):
         )
 
     async def stop_resource(self, resource_attributes: AttributeDict):
-        logging.debug("Slurm jobs cannot be stopped gracefully. Terminating instead.")
+        logger.debug("Slurm jobs cannot be stopped gracefully. Terminating instead.")
         return await self.terminate_resource(resource_attributes)
 
     @contextmanager
@@ -172,7 +174,7 @@ class SlurmAdapter(SiteAdapter):
         try:
             yield
         except CommandExecutionFailure as ex:
-            logging.info("Execute command failed: %s" % str(ex))
+            logger.warning("Execute command failed: %s" % str(ex))
             raise TardisResourceStatusUpdateFailed
         except TardisResourceStatusUpdateFailed:
             raise
diff --git a/tardis/plugins/prometheusmonitoring.py b/tardis/plugins/prometheusmonitoring.py
index 35e8968..b79b3b1 100644
--- a/tardis/plugins/prometheusmonitoring.py
+++ b/tardis/plugins/prometheusmonitoring.py
@@ -7,6 +7,8 @@ from ..utilities.attributedict import AttributeDict
 import logging
 from aioprometheus import Service, Gauge
 
+logger = logging.getLogger("cobald.runtime.tardis.plugins.prometheusmonitoring")
+
 
 class PrometheusMonitoring(Plugin):
     """
@@ -15,10 +17,6 @@ class PrometheusMonitoring(Plugin):
     """
 
     def __init__(self):
-        self.logger = logging.getLogger(
-            "cobald.runtime.tardis.plugins.prometheusmonitoring"
-        )
-        self.logger.setLevel(logging.DEBUG)
         config = Configuration().Plugins.PrometheusMonitoring
 
         self._port = config.port
@@ -43,7 +41,7 @@ class PrometheusMonitoring(Plugin):
 
     async def start(self):
         await self._svr.start(addr=self._addr, port=self._port)
-        self.logger.debug(f"Serving Prometheus metrics on {self._svr.metrics_url}")
+        logger.debug(f"Serving Prometheus metrics on {self._svr.metrics_url}")
         self._svr_started = True
 
     async def notify(self, state: State, resource_attributes: AttributeDict) -> None:
@@ -60,9 +58,7 @@ class PrometheusMonitoring(Plugin):
         if not self._svr_started:
             await self.start()
 
-        self.logger.debug(
-            f"Drone: {str(resource_attributes)} has changed state to {state}"
-        )
+        logger.debug(f"Drone: {str(resource_attributes)} has changed state to {state}")
 
         if resource_attributes.drone_uuid in self._drones:
             old_status = self._drones[resource_attributes.drone_uuid]
diff --git a/tardis/plugins/sqliteregistry.py b/tardis/plugins/sqliteregistry.py
index 1164c67..5371cd8 100644
--- a/tardis/plugins/sqliteregistry.py
+++ b/tardis/plugins/sqliteregistry.py
@@ -8,6 +8,8 @@ import asyncio
 import logging
 import sqlite3
 
+logger = logging.getLogger("cobald.runtime.tardis.plugins.sqliteregistry")
+
 
 class SqliteRegistry(Plugin):
     def __init__(self):
@@ -17,8 +19,6 @@ class SqliteRegistry(Plugin):
         of this module is recommended in order to recover the last state of
         TARDIS in case the service has to be restarted.
         """
-        self.logger = logging.getLogger("sqliteregistry")
-        self.logger.setLevel(logging.DEBUG)
         configuration = Configuration()
         self._db_file = configuration.Plugins.SqliteRegistry.db_file
         self._deploy_db_schema()
@@ -113,7 +113,7 @@ class SqliteRegistry(Plugin):
             }
             cursor = connection.cursor()
             cursor.execute(sql_query, bind_parameters)
-            logging.debug(f"{sql_query},{bind_parameters} executed")
+            logger.debug(f"{sql_query},{bind_parameters} executed")
             return cursor.fetchall()
 
     def get_resources(self, site_name: str, machine_type: str):
@@ -144,9 +144,7 @@ class SqliteRegistry(Plugin):
 
     async def notify(self, state: State, resource_attributes: AttributeDict) -> None:
         state = str(state)
-        self.logger.debug(
-            f"Drone: {str(resource_attributes)} has changed state to {state}"
-        )
+        logger.debug(f"Drone: {str(resource_attributes)} has changed state to {state}")
         bind_parameters = dict(state=state)
         bind_parameters.update(resource_attributes)
         await self._dispatch_on_state.get(state, self.update_resource)(bind_parameters)
diff --git a/tardis/plugins/telegrafmonitoring.py b/tardis/plugins/telegrafmonitoring.py
index 24dfd61..3f7ea6f 100644
--- a/tardis/plugins/telegrafmonitoring.py
+++ b/tardis/plugins/telegrafmonitoring.py
@@ -8,6 +8,8 @@ from datetime import datetime
 import logging
 import platform
 
+logger = logging.getLogger("cobald.runtime.tardis.plugins.telegrafmonitoring")
+
 
 class TelegrafMonitoring(Plugin):
     """
@@ -17,8 +19,6 @@ class TelegrafMonitoring(Plugin):
     """
 
     def __init__(self):
-        self.logger = logging.getLogger("telegrafmonitoring")
-        self.logger.setLevel(logging.DEBUG)
         config = Configuration().Plugins.TelegrafMonitoring
 
         host = config.host
@@ -40,9 +40,7 @@ class TelegrafMonitoring(Plugin):
         :type resource_attributes: AttributeDict
         :return: None
         """
-        self.logger.debug(
-            f"Drone: {str(resource_attributes)} has changed state to {state}"
-        )
+        logger.debug(f"Drone: {str(resource_attributes)} has changed state to {state}")
         await self.client.connect()
         data = dict(
             state=str(state),
diff --git a/tardis/resources/drone.py b/tardis/resources/drone.py
index 8fa452d..e38324c 100644
--- a/tardis/resources/drone.py
+++ b/tardis/resources/drone.py
@@ -16,6 +16,8 @@ import asyncio
 import logging
 import uuid
 
+logger = logging.getLogger("cobald.runtime.tardis.resources.drone")
+
 
 @service(flavour=asyncio)
 class Drone(Pool):
@@ -90,7 +92,7 @@ class Drone(Pool):
             current_state = self.state
             await current_state.run(self)
             if isinstance(current_state, DownState):
-                logging.debug(
+                logger.debug(
                     f"Garbage Collect Drone: {self.resource_attributes.drone_uuid}"
                 )
                 self._demand = 0
diff --git a/tardis/resources/dronestates.py b/tardis/resources/dronestates.py
index a505189..087c22d 100644
--- a/tardis/resources/dronestates.py
+++ b/tardis/resources/dronestates.py
@@ -19,6 +19,8 @@ from ..utilities.pipeline import StopProcessing
 if TYPE_CHECKING:
     from tardis.resources.drone import Drone
 
+logger = logging.getLogger("cobald.runtime.tardis.resources.dronestates")
+
 
 async def batchsystem_machine_status(
     state_transition, drone: "Drone", current_state: Type[State]
@@ -56,7 +58,7 @@ async def resource_status(state_transition, drone: "Drone", current_state: Type[
         drone.resource_attributes.update(
             await drone.site_agent.resource_status(drone.resource_attributes)
         )
-        logging.info(f"Resource attributes: {drone.resource_attributes}")
+        logger.debug(f"Resource attributes: {drone.resource_attributes}")
     except (TardisAuthError, TardisTimeout, TardisResourceStatusUpdateFailed):
         #  Retry to get current state of the resource
         raise StopProcessing(last_result=current_state())
@@ -70,7 +72,7 @@ async def resource_status(state_transition, drone: "Drone", current_state: Type[
 class RequestState(State):
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in RequestState")
+        logger.info(f"Drone {drone.resource_attributes} in RequestState")
         try:
             drone.resource_attributes.update(
                 await drone.site_agent.deploy_resource(drone.resource_attributes)
@@ -101,14 +103,14 @@ class BootingState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in BootingState")
+        logger.info(f"Drone {drone.resource_attributes} in BootingState")
         await drone.set_state(await cls.run_processing_pipeline(drone))
 
 
 class IntegrateState(State):
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in IntegrateState")
+        logger.info(f"Drone {drone.resource_attributes} in IntegrateState")
         await drone.batch_system_agent.integrate_machine(
             drone_uuid=drone.resource_attributes["drone_uuid"]
         )
@@ -133,7 +135,7 @@ class IntegratingState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in IntegratingState")
+        logger.info(f"Drone {drone.resource_attributes} in IntegratingState")
         await drone.set_state(await cls.run_processing_pipeline(drone))
 
 
@@ -160,7 +162,7 @@ class AvailableState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in AvailableState")
+        logger.info(f"Drone {drone.resource_attributes} in AvailableState")
 
         new_state = await cls.run_processing_pipeline(drone)
 
@@ -179,7 +181,7 @@ class AvailableState(State):
 class DrainState(State):
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in DrainState")
+        logger.info(f"Drone {drone.resource_attributes} in DrainState")
         await drone.batch_system_agent.drain_machine(
             drone_uuid=drone.resource_attributes["drone_uuid"]
         )
@@ -206,14 +208,14 @@ class DrainingState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in DrainingState")
+        logger.info(f"Drone {drone.resource_attributes} in DrainingState")
         await drone.set_state(await cls.run_processing_pipeline(drone))
 
 
 class DisintegrateState(State):
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in DisintegrateState")
+        logger.info(f"Drone {drone.resource_attributes} in DisintegrateState")
         await drone.batch_system_agent.disintegrate_machine(
             drone_uuid=drone.resource_attributes["drone_uuid"]
         )
@@ -235,8 +237,8 @@ class ShutDownState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in ShutDownState")
-        logging.info(
+        logger.info(f"Drone {drone.resource_attributes} in ShutDownState")
+        logger.debug(
             f"Stopping VM with ID {drone.resource_attributes.remote_resource_uuid}"
         )
 
@@ -245,7 +247,7 @@ class ShutDownState(State):
             try:
                 await drone.site_agent.stop_resource(drone.resource_attributes)
             except TardisResourceStatusUpdateFailed:
-                logging.warning(
+                logger.warning(
                     f"Calling stop_resource failed for drone "
                     f"{drone.resource_attributes.drone_uuid}"
                 )
@@ -267,9 +269,9 @@ class ShuttingDownState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in ShuttingDownState")
-        logging.info(
-            f"Checking Status of VM with ID "
+        logger.info(f"Drone {drone.resource_attributes} in ShuttingDownState")
+        logger.debug(
+            f"Checking Status of drone with ID "
             f"{drone.resource_attributes.remote_resource_uuid}"
         )
         await drone.set_state(await cls.run_processing_pipeline(drone))
@@ -287,25 +289,25 @@ class CleanupState(State):
 
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in CleanupState")
+        logger.info(f"Drone {drone.resource_attributes} in CleanupState")
 
         new_state = await cls.run_processing_pipeline(drone)
 
         if isinstance(new_state, CleanupState):
             try:
-                logging.info(
+                logger.debug(
                     f"Destroying VM with ID "
                     f"{drone.resource_attributes.remote_resource_uuid}"
                 )
                 await drone.site_agent.terminate_resource(drone.resource_attributes)
             except TardisDroneCrashed:
-                logging.warning(
+                logger.warning(
                     f"Calling terminate_resource failed for drone "
                     f"{drone.resource_attributes.drone_uuid}. Drone crashed!"
                 )
                 new_state = DownState()
             except TardisResourceStatusUpdateFailed:
-                logging.warning(
+                logger.warning(
                     f"Calling terminate_resource failed for drone "
                     f"{drone.resource_attributes.drone_uuid}. Will retry later!"
                 )
@@ -316,5 +318,5 @@ class CleanupState(State):
 class DownState(State):
     @classmethod
     async def run(cls, drone: "Drone"):
-        logging.info(f"Drone {drone.resource_attributes} in DownState")
+        logger.info(f"Drone {drone.resource_attributes} in DownState")
         drone.demand = 0
diff --git a/tardis/utilities/asynccachemap.py b/tardis/utilities/asynccachemap.py
index ef1babe..2b1733b 100644
--- a/tardis/utilities/asynccachemap.py
+++ b/tardis/utilities/asynccachemap.py
@@ -7,6 +7,8 @@ import asyncio
 import logging
 import json
 
+logger = logging.getLogger("cobald.runtime.tardis.utilities.asynccachemap")
+
 
 class AsyncCacheMap(Mapping):
     def __init__(self, update_coroutine, max_age: int = 60 * 15):
@@ -36,11 +38,11 @@ class AsyncCacheMap(Mapping):
                 try:
                     data = await self._update_coroutine()
                 except json.decoder.JSONDecodeError as je:
-                    logging.error(
+                    logger.warning(
                         f"AsyncMap update_status failed: Could not decode json {je}"
                     )
                 except CommandExecutionFailure as cf:
-                    logging.error(f"AsyncMap update_status failed: {cf}")
+                    logger.warning(f"AsyncMap update_status failed: {cf}")
                 else:
                     self._data = data
                     self._last_update = current_time


Test patch:
diff --git a/tests/adapters_t/batchsystems_t/test_htcondor.py b/tests/adapters_t/batchsystems_t/test_htcondor.py
index 9f1f9bb..a6dc122 100644
--- a/tests/adapters_t/batchsystems_t/test_htcondor.py
+++ b/tests/adapters_t/batchsystems_t/test_htcondor.py
@@ -10,6 +10,8 @@ from shlex import quote
 from unittest.mock import patch
 from unittest import TestCase
 
+import logging
+
 
 class TestHTCondorAdapter(TestCase):
     @classmethod
@@ -100,17 +102,19 @@ class TestHTCondorAdapter(TestCase):
         self.mock_async_run_command.side_effect = CommandExecutionFailure(
             message="Does not exists", exit_code=1, stderr="Does not exists"
         )
-        self.assertIsNone(
-            run_async(self.htcondor_adapter.drain_machine, drone_uuid="test")
-        )
+        with self.assertLogs(level=logging.WARNING):
+            self.assertIsNone(
+                run_async(self.htcondor_adapter.drain_machine, drone_uuid="test")
+            )
 
         self.mock_async_run_command.side_effect = CommandExecutionFailure(
             message="Unhandled error", exit_code=2, stderr="Unhandled error"
         )
         with self.assertRaises(CommandExecutionFailure):
-            self.assertIsNone(
-                run_async(self.htcondor_adapter.drain_machine, drone_uuid="test")
-            )
+            with self.assertLogs(level=logging.CRITICAL):
+                self.assertIsNone(
+                    run_async(self.htcondor_adapter.drain_machine, drone_uuid="test")
+                )
 
         self.mock_async_run_command.side_effect = None
 
@@ -217,7 +221,7 @@ class TestHTCondorAdapter(TestCase):
         self.mock_async_run_command.side_effect = CommandExecutionFailure(
             message="Test", exit_code=123, stderr="Test"
         )
-        with self.assertLogs(level="ERROR"):
+        with self.assertLogs(level=logging.WARNING):
             with self.assertRaises(CommandExecutionFailure):
                 attributes = {
                     "Machine": "Machine",
diff --git a/tests/adapters_t/sites_t/test_cloudstack.py b/tests/adapters_t/sites_t/test_cloudstack.py
index b9ac692..0c9f155 100644
--- a/tests/adapters_t/sites_t/test_cloudstack.py
+++ b/tests/adapters_t/sites_t/test_cloudstack.py
@@ -15,6 +15,7 @@ from unittest import TestCase
 from unittest.mock import patch
 
 import asyncio
+import logging
 
 
 class TestCloudStackAdapter(TestCase):
@@ -157,8 +158,9 @@ class TestCloudStackAdapter(TestCase):
     def test_exception_handling(self):
         def test_exception_handling(to_raise, to_catch):
             with self.assertRaises(to_catch):
-                with self.cloudstack_adapter.handle_exceptions():
-                    raise to_raise
+                with self.assertLogs(level=logging.WARNING):
+                    with self.cloudstack_adapter.handle_exceptions():
+                        raise to_raise
 
         matrix = [
             (
diff --git a/tests/adapters_t/sites_t/test_htcondorsiteadapter.py b/tests/adapters_t/sites_t/test_htcondorsiteadapter.py
index 53d658a..b28d9ca 100644
--- a/tests/adapters_t/sites_t/test_htcondorsiteadapter.py
+++ b/tests/adapters_t/sites_t/test_htcondorsiteadapter.py
@@ -185,7 +185,7 @@ class TestHTCondorSiteAdapter(TestCase):
     )
     def test_resource_status_raise_future(self):
         future_timestamp = datetime.now() + timedelta(minutes=1)
-        with self.assertLogs(logging.getLogger(), logging.ERROR):
+        with self.assertLogs(level=logging.WARNING):
             with self.assertRaises(TardisResourceStatusUpdateFailed):
                 run_async(
                     self.adapter.resource_status,
@@ -207,7 +207,7 @@ class TestHTCondorSiteAdapter(TestCase):
         self.adapter._htcondor_queue._last_update = datetime.now() - timedelta(
             minutes=11
         )
-        with self.assertLogs(logging.getLogger(), logging.ERROR):
+        with self.assertLogs(level=logging.WARNING):
             response = run_async(
                 self.adapter.resource_status,
                 AttributeDict(remote_resource_uuid="1351043", created=past_timestamp),
diff --git a/tests/adapters_t/sites_t/test_moab.py b/tests/adapters_t/sites_t/test_moab.py
index 49174ca..b15bf3c 100644
--- a/tests/adapters_t/sites_t/test_moab.py
+++ b/tests/adapters_t/sites_t/test_moab.py
@@ -16,6 +16,7 @@ from warnings import filterwarnings
 
 import asyncio
 import asyncssh
+import logging
 
 __all__ = ["TestMoabAdapter"]
 
@@ -349,10 +350,11 @@ class TestMoabAdapter(TestCase):
         expected_resource_attributes.update(
             updated=datetime.now(), resource_status=ResourceStatus.Stopped
         )
-        return_resource_attributes = run_async(
-            self.moab_adapter.terminate_resource,
-            resource_attributes=self.resource_attributes,
-        )
+        with self.assertLogs(level=logging.WARNING):
+            return_resource_attributes = run_async(
+                self.moab_adapter.terminate_resource,
+                resource_attributes=self.resource_attributes,
+            )
         self.assertEqual(
             return_resource_attributes["resource_status"], ResourceStatus.Stopped
         )
@@ -407,8 +409,9 @@ class TestMoabAdapter(TestCase):
     def test_exception_handling(self):
         def test_exception_handling(to_raise, to_catch):
             with self.assertRaises(to_catch):
-                with self.moab_adapter.handle_exceptions():
-                    raise to_raise
+                with self.assertLogs(level=logging.WARNING):
+                    with self.moab_adapter.handle_exceptions():
+                        raise to_raise
 
         matrix = [
             (asyncio.TimeoutError(), TardisTimeout),
diff --git a/tests/adapters_t/sites_t/test_openstack.py b/tests/adapters_t/sites_t/test_openstack.py
index c49dfd4..e71ba25 100644
--- a/tests/adapters_t/sites_t/test_openstack.py
+++ b/tests/adapters_t/sites_t/test_openstack.py
@@ -18,6 +18,7 @@ from unittest import TestCase
 from unittest.mock import patch
 
 import asyncio
+import logging
 
 
 class TestOpenStackAdapter(TestCase):
@@ -163,8 +164,9 @@ class TestOpenStackAdapter(TestCase):
     def test_exception_handling(self):
         def test_exception_handling(to_raise, to_catch):
             with self.assertRaises(to_catch):
-                with self.openstack_adapter.handle_exceptions():
-                    raise to_raise
+                with self.assertLogs(level=logging.WARNING):
+                    with self.openstack_adapter.handle_exceptions():
+                        raise to_raise
 
         matrix = [
             (asyncio.TimeoutError(), TardisTimeout),
diff --git a/tests/adapters_t/sites_t/test_slurm.py b/tests/adapters_t/sites_t/test_slurm.py
index 814955c..a8f0355 100644
--- a/tests/adapters_t/sites_t/test_slurm.py
+++ b/tests/adapters_t/sites_t/test_slurm.py
@@ -341,7 +341,7 @@ class TestSlurmAdapter(TestCase):
             "1390065": {"JobId": "1390065", "Host": "fh2n1552", "State": "RUNNING"}
         }
 
-        with self.assertLogs(logging.getLogger(), logging.ERROR):
+        with self.assertLogs(level=logging.WARNING):
             response = run_async(
                 self.slurm_adapter.resource_status,
                 AttributeDict(remote_resource_uuid="1390065"),
@@ -386,8 +386,9 @@ class TestSlurmAdapter(TestCase):
     def test_exception_handling(self):
         def test_exception_handling(to_raise, to_catch):
             with self.assertRaises(to_catch):
-                with self.slurm_adapter.handle_exceptions():
-                    raise to_raise
+                with self.assertLogs(level=logging.WARNING):
+                    with self.slurm_adapter.handle_exceptions():
+                        raise to_raise
 
         matrix = [
             (asyncio.TimeoutError(), TardisTimeout),
diff --git a/tests/resources_t/test_dronestates.py b/tests/resources_t/test_dronestates.py
index c9c956e..861cab1 100644
--- a/tests/resources_t/test_dronestates.py
+++ b/tests/resources_t/test_dronestates.py
@@ -314,6 +314,8 @@ class TestDroneStates(TestCase):
 
         self.run_the_matrix(matrix, initial_state=CleanupState)
 
+        log_channel = "cobald.runtime.tardis.resources.dronestates"
+
         with self.assertLogs(level=logging.WARNING) as msg:
             self.run_side_effects(
                 CleanupState(),
@@ -324,7 +326,7 @@ class TestDroneStates(TestCase):
             self.assertEqual(
                 msg.output,
                 [
-                    "WARNING:root:Calling terminate_resource failed for"
+                    f"WARNING:{log_channel}:Calling terminate_resource failed for"
                     " drone test-923ABF. Drone crashed!"
                 ],
             )
@@ -339,7 +341,7 @@ class TestDroneStates(TestCase):
             self.assertEqual(
                 msg.output,
                 [
-                    "WARNING:root:Calling terminate_resource failed for"
+                    f"WARNING:{log_channel}:Calling terminate_resource failed for"
                     " drone test-923ABF. Will retry later!"
                 ],
             )
diff --git a/tests/utilities_t/test_asynccachemap.py b/tests/utilities_t/test_asynccachemap.py
index 6726533..53939f1 100644
--- a/tests/utilities_t/test_asynccachemap.py
+++ b/tests/utilities_t/test_asynccachemap.py
@@ -55,12 +55,12 @@ class TestAsyncCacheMap(TestCase):
             self.assertEqual(value, self.test_data.get(key))
 
     def test_json_failing_update(self):
-        with self.assertLogs(logging.getLogger(), logging.ERROR):
+        with self.assertLogs(level=logging.WARNING):
             run_async(self.json_failing_async_cache_map.update_status)
             self.assertEqual(len(self.json_failing_async_cache_map), 0)
 
     def test_command_failing_update(self):
-        with self.assertLogs(logging.getLogger(), logging.ERROR):
+        with self.assertLogs(level=logging.WARNING):
             run_async(self.json_failing_async_cache_map.update_status)
             self.assertEqual(len(self.json_failing_async_cache_map), 0)