Repository: dbt-labs/dbt-core

Issue:
[CT-2347] [Bug] Petite laideur in v1.5 logging: datetimes
Since the switch to the new proto library, datetimes are ugly-rendered in text-formatted logging, and they take up more space than they should:
```
Timing info for seed.test.my_seed (execute): seconds: 1680366677
nanos: 785534000
 => seconds: 1680366680
nanos: 375668000
```
```
Command `dbt clone` succeeded at seconds: 1680366681
nanos: 79572000
 after 7.66 seconds
```

From looking at the JSON-formatted logs, this also shows up in the `message` field. Let's pretty-stringify these datetime values wherever they're being f-string formatted into `message`.


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
@@ -10,6 +10,7 @@
 import traceback
 from typing import Any, Callable, List, Optional, TextIO
 from uuid import uuid4
+from dbt.events.format import timestamp_to_datetime_string
 
 from dbt.events.base_types import BaseEvent, EventLevel, msg_from_base_event, EventMsg
 
@@ -219,8 +220,3 @@ def add_callbacks(self, callbacks: List[Callable[[EventMsg], None]]):
     def flush(self):
         for logger in self.loggers:
             logger.flush()
-
-
-def timestamp_to_datetime_string(ts):
-    timestamp_dt = datetime.fromtimestamp(ts.seconds + ts.nanos / 1e9)
-    return timestamp_dt.strftime("%H:%M:%S.%f")
diff --git a/core/dbt/events/format.py b/core/dbt/events/format.py
--- a/core/dbt/events/format.py
+++ b/core/dbt/events/format.py
@@ -1,6 +1,7 @@
 from dbt import ui
 from dbt.node_types import NodeType
 from typing import Optional, Union
+from datetime import datetime
 
 
 def format_fancy_output_line(
@@ -48,3 +49,8 @@ def pluralize(count, string: Union[str, NodeType]):
     if count != 1:
         pluralized = _pluralize(string)
     return f"{count} {pluralized}"
+
+
+def timestamp_to_datetime_string(ts):
+    timestamp_dt = datetime.fromtimestamp(ts.seconds + ts.nanos / 1e9)
+    return timestamp_dt.strftime("%H:%M:%S.%f")
diff --git a/core/dbt/events/types.py b/core/dbt/events/types.py
--- a/core/dbt/events/types.py
+++ b/core/dbt/events/types.py
@@ -10,7 +10,7 @@
     ErrorLevel,
     EventLevel,
 )
-from dbt.events.format import format_fancy_output_line, pluralize
+from dbt.events.format import format_fancy_output_line, pluralize, timestamp_to_datetime_string
 
 from dbt.node_types import NodeType
 
@@ -1710,7 +1710,8 @@ def code(self):
 
     def message(self) -> str:
         status = "succeeded" if self.success else "failed"
-        return f"Command `{self.command}` {status} at {self.completed_at} after {self.elapsed:0.2f} seconds"
+        completed_at = timestamp_to_datetime_string(self.completed_at)
+        return f"Command `{self.command}` {status} at {completed_at} after {self.elapsed:0.2f} seconds"
 
 
 class ShowNode(InfoLevel):
@@ -1886,7 +1887,9 @@ def code(self):
         return "Z010"
 
     def message(self) -> str:
-        return f"Timing info for {self.node_info.unique_id} ({self.timing_info.name}): {self.timing_info.started_at} => {self.timing_info.completed_at}"
+        started_at = timestamp_to_datetime_string(self.timing_info.started_at)
+        completed_at = timestamp_to_datetime_string(self.timing_info.completed_at)
+        return f"Timing info for {self.node_info.unique_id} ({self.timing_info.name}): {started_at} => {completed_at}"
 
 
 # This prints the stack trace at the debug level while allowing just the nice exception message


Test patch: