Repository: AcademySoftwareFoundation/rez

Issue:
Update PackageCache Class to respect external logging configuration
Modify the `_init_logging ` method in the `PackageCache` class of the `package_cache.py` module to check for the presence of the `REZ_LOGGING_CONF ` environment variable. If this variable is set, use its value as a logging configuration file and return the configured logger object. This ensures that the custom logging setup can override the default "rez-pkg-cache" logger created by the PackageCache class.

Current code: https://github.com/AcademySoftwareFoundation/rez/blob/4e00cfdf89a59517dfac11111b7d488d2ea83066/src/rez/package_cache.py#L841-L876

Suggestion:

```python
def _init_logging(self):
    """
    Creates logger that logs to file and stdout. Used for:
    - adding variants in daemonized proc;
    - clean(), which would typically be run as a cron, but can also be run
      manually (hence the logging to stdout also)
    """
    logger = logging.getLogger("rez-pkg-cache")
    
    logging_conf = os.getenv("REZ_LOGGING_CONF")
    if logging_conf:
        logging.config.fileConfig(logging_conf, disable_existing_loggers=False)
        return logger
        
    logger.setLevel(logging.INFO)
    logger.propagate = False
    
    [...]
```

**Motivation**
Since the `rez` module has its own `_init_logging` function that implements custom logging functionality 
with the environment variable `REZ_LOGGING_CONF`: https://github.com/AcademySoftwareFoundation/rez/blob/4e00cfdf89a59517dfac11111b7d488d2ea83066/src/rez/__init__.py#L21-L43

It would be wise to implement the same feature in the `_init_logging` method of the `PackageCache` class.

For now, we've set up our own custom handlers on the logger "rez-pkg-cache", but there are still duplicate logs and no way to remove the handlers from "rez-pkg-cache".

# Maintainer note:

There is an opportunity to reduce code duplication.

Hints from issue comments:
@JeanChristopheMorinPerso: Relates to https://github.com/AcademySoftwareFoundation/rez/issues/542@BryceGattis: I'll take a look at this one for Dev Days 👍 

Solution patch:
diff --git a/src/rez/package_cache.py b/src/rez/package_cache.py
index 664a439b..8a4d6f70 100644
--- a/src/rez/package_cache.py
+++ b/src/rez/package_cache.py
@@ -15,6 +15,7 @@ import sys
 import platform
 import time
 import logging
+import logging.config
 import random
 import threading
 from contextlib import contextmanager
@@ -846,6 +847,11 @@ class PackageCache(object):
           manually (hence the logging to stdout also)
         """
         logger = logging.getLogger("rez-pkg-cache")
+        logging_conf = os.getenv("REZ_LOGGING_CONF")
+        if logging_conf:
+            logging.config.fileConfig(logging_conf, disable_existing_loggers=False)
+            return logger
+
         logger.setLevel(logging.INFO)
         logger.propagate = False
 


Test patch:
diff --git a/src/rez/data/tests/config/logging_config_test.conf b/src/rez/data/tests/config/logging_config_test.conf
new file mode 100644
index 00000000..f179b22a
--- /dev/null
+++ b/src/rez/data/tests/config/logging_config_test.conf
@@ -0,0 +1,27 @@
+[loggers]
+keys=root,rez-pkg-cache
+
+[handlers]
+keys=myTestingConsoleHandler
+
+[formatters]
+keys=simpleFormatter
+
+[logger_root]
+level=DEBUG
+handlers=myTestingConsoleHandler
+
+[logger_rez-pkg-cache]
+level=DEBUG
+handlers=myTestingConsoleHandler
+qualname=rez-pkg-cache
+propagate=0
+
+[handler_myTestingConsoleHandler]
+class=StreamHandler
+level=DEBUG
+formatter=simpleFormatter
+args=(sys.stdout,)
+
+[formatter_simpleFormatter]
+format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
\ No newline at end of file
diff --git a/src/rez/tests/test_package_cache.py b/src/rez/tests/test_package_cache.py
index 01f91ff7..a4ad7dbf 100644
--- a/src/rez/tests/test_package_cache.py
+++ b/src/rez/tests/test_package_cache.py
@@ -5,6 +5,12 @@
 """
 Test package caching.
 """
+import logging
+import os
+import os.path
+import time
+import subprocess
+
 from rez.tests.util import TestBase, TempdirMixin, restore_os_environ, \
     install_dependent
 from rez.packages import get_package
@@ -12,10 +18,6 @@ from rez.package_cache import PackageCache
 from rez.resolved_context import ResolvedContext
 from rez.exceptions import PackageCacheError
 from rez.utils.filesystem import canonical_path
-import os
-import os.path
-import time
-import subprocess
 
 
 class TestPackageCache(TestBase, TempdirMixin):
@@ -123,6 +125,18 @@ class TestPackageCache(TestBase, TempdirMixin):
         with self.assertRaises(PackageCacheError):
             pkgcache.add_variant(variant)
 
+    def test_external_logging_config(self):
+        """Test that external logging is respected if configured."""
+        config_file_path = canonical_path(self.data_path("config", "logging_config_test.conf"))
+        with restore_os_environ():
+            os.environ["REZ_LOGGING_CONF"] = config_file_path
+            pkgcache = self._pkgcache()
+            pkgcache._init_logging()
+            logger = logging.getLogger('rez-pkg-cache')
+            self.assertEqual(len(logger.handlers), 1)
+            self.assertEqual(logger.handlers[0].__class__, logging.StreamHandler)
+            self.assertEqual(logger.handlers[0].level, logging.DEBUG)
+
     @install_dependent()
     def test_caching_on_resolve(self):
         """Test that cache is updated as expected on resolved env."""