Repository: dbt-labs/dbt-core

Issue:
[CT-1658] Logging changes break dbt-rpc
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

Due to recent changes, logs are now written to the logbook GLOBAL_LOGGER using the same numeric priority as used for native Python logs, but they are not compatible. Furthermore, the GLOBAL_LOGGER is not written to by default, and dbt-rpc does not do its own log set up. We need to correct both issues so that dbt-core logging behavior with respect to the legacy logbook code remains the same in 1.4 as it was in 1.3.

### Expected Behavior

When DBT_ENABLE_LEGACY_LOGGING is true, dbt-core should exhibit the same log output behaviors as it did in 1.3.

### Steps To Reproduce

The issue can be seen in the GitHub actions for the dbt-rpc build, which are currently failing.



Discussion:

Resolving patch:
diff --git a/core/dbt/events/eventmgr.py b/core/dbt/events/eventmgr.py
--- a/core/dbt/events/eventmgr.py
+++ b/core/dbt/events/eventmgr.py
@@ -47,6 +47,33 @@ class LineFormat(Enum):
 }
 
 
+# We should consider fixing the problem, but log_level() can return a string for
+# DynamicLevel events, even thought it is supposed to return an EventLevel. This
+# function gets a string for the level, no matter what.
+def _get_level_str(e: BaseEvent) -> str:
+    return e.log_level().value if isinstance(e.log_level(), EventLevel) else str(e.log_level())
+
+
+# We need this function for now because the numeric log severity levels in
+# Python do not match those for logbook, so we have to explicitly call the
+# correct function by name.
+def send_to_logger(l, level: str, log_line: str):
+    if level == "test":
+        l.debug(log_line)
+    elif level == "debug":
+        l.debug(log_line)
+    elif level == "info":
+        l.info(log_line)
+    elif level == "warn":
+        l.warning(log_line)
+    elif level == "error":
+        l.error(log_line)
+    else:
+        raise AssertionError(
+            f"While attempting to log {log_line}, encountered the unhandled level: {level}"
+        )
+
+
 @dataclass
 class LoggerConfig:
     name: str
@@ -93,7 +120,7 @@ def write_line(self, e: BaseEvent):
         line = self.create_line(e)
         python_level = _log_level_map[e.log_level()]
         if self._python_logger is not None:
-            self._python_logger.log(python_level, line)
+            send_to_logger(self._python_logger, _get_level_str(e), line)
         elif self._stream is not None and _log_level_map[self.level] <= python_level:
             self._stream.write(line + "\n")
 
@@ -128,8 +155,7 @@ def create_debug_line(self, e: BaseEvent) -> str:
             log_line = f"\n\n{separator} {datetime.utcnow()} | {self.event_manager.invocation_id} {separator}\n"
         ts: str = datetime.utcnow().strftime("%H:%M:%S.%f")
         scrubbed_msg: str = self.scrubber(e.message())  # type: ignore
-        # log_level() for DynamicLevel events returns str instead of EventLevel
-        level = e.log_level().value if isinstance(e.log_level(), EventLevel) else e.log_level()
+        level = _get_level_str(e)
         log_line += (
             f"{self._get_color_tag()}{ts} [{level:<5}]{self._get_thread_name()} {scrubbed_msg}"
         )
diff --git a/core/dbt/events/functions.py b/core/dbt/events/functions.py
--- a/core/dbt/events/functions.py
+++ b/core/dbt/events/functions.py
@@ -18,10 +18,6 @@
 LOG_VERSION = 3
 metadata_vars: Optional[Dict[str, str]] = None
 
-# The default event manager will not log anything, but some tests run code that
-# generates events, without configuring the event manager.
-EVENT_MANAGER: EventManager = EventManager()
-
 
 def setup_event_logger(log_path: str, level_override: Optional[EventLevel] = None):
     cleanup_event_logger()
@@ -114,6 +110,16 @@ def cleanup_event_logger():
     EVENT_MANAGER.callbacks.clear()
 
 
+# The default event manager will not log anything, but some tests run code that
+# generates events, without configuring the event manager, so we create an empty
+# manager here until there is a better testing strategy in place.
+EVENT_MANAGER: EventManager = EventManager()
+
+# Since dbt-rpc does not do its own log setup, we set up logbook if legacy
+# logging is enabled.
+if flags.ENABLE_LEGACY_LOGGER:
+    EVENT_MANAGER.add_logger(_get_logbook_log_config(None))
+
 # This global, and the following two functions for capturing stdout logs are
 # an unpleasant hack we intend to remove as part of API-ification. The GitHub
 # issue #6350 was opened for that work.


Test patch: