Skip to content

Commit f2e3cd6

Browse files
committed
fix(instigation logger): stringify non-json objects
1 parent 97073e7 commit f2e3cd6

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

python_modules/dagster/dagster/_core/definitions/instigation_logger.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from contextlib import ExitStack
88
from typing import IO, TYPE_CHECKING, Any, Optional
99

10-
from dagster_shared import seven
11-
1210
from dagster._core.log_manager import LOG_RECORD_METADATA_ATTR
1311
from dagster._core.storage.compute_log_manager import ComputeIOType, ComputeLogManager
1412
from dagster._core.utils import coerce_valid_log_level
@@ -73,10 +71,12 @@ def emit(self, record: logging.LogRecord):
7371
record_dict["exc_info"] = "".join(traceback.format_exception(*exc_info))
7472

7573
try:
76-
self._write_stream.write(seven.json.dumps(record_dict) + "\n")
74+
self._write_stream.write(json.dumps(record_dict, default=str, sort_keys=True) + "\n")
7775
except Exception:
7876
sys.stderr.write(
79-
f"Exception writing to logger event stream: {serializable_error_info_from_exc_info(sys.exc_info())}\n"
77+
f"Exception writing to logger event stream: {serializable_error_info_from_exc_info(sys.exc_info())}."
78+
f" The originating log call was made at: {record.pathname}:{record.funcName} (line {record.lineno})."
79+
"\n"
8080
)
8181

8282

@@ -179,7 +179,7 @@ def get_instigation_log_records(
179179
continue
180180

181181
try:
182-
records.append(seven.json.loads(line))
182+
records.append(json.loads(line, strict=False))
183183
except json.JSONDecodeError:
184184
continue
185185
return records

python_modules/dagster/dagster_tests/storage_tests/test_instigation_logger.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from unittest import mock
33

44
import dagster as dg
5-
from dagster._core.definitions.instigation_logger import InstigationLogger
5+
from dagster._core.definitions.instigation_logger import InstigationLogger, get_instigation_log_records
66
from dagster._core.storage.noop_compute_log_manager import NoOpComputeLogManager
77

88

@@ -74,3 +74,42 @@ def test_instigation_logger_log_failure(capsys):
7474
captured.err.count("Exception closing logger write stream: Exception: OOPS ON EXIT")
7575
== 1
7676
)
77+
78+
79+
def test_instigation_logger_logs_weird_record_ok(capsys):
80+
class NonJsonSerializable:
81+
"""A class that json.dumps doesn't know what to do with (by default)."""
82+
def __str__(self):
83+
return "non-jsonable-object"
84+
85+
log_key = ["test-repo", "test-instigator", "123"]
86+
87+
with dg.instance_for_test() as instance: # pyright: ignore[reportAttributeAccessIssue]
88+
with InstigationLogger(
89+
log_key=log_key,
90+
instance=instance,
91+
repository_name="test-repo",
92+
instigator_name="test-instigator",
93+
) as logger:
94+
logger.info("log without extras")
95+
logger.info("log with extras", extra={"non_json": NonJsonSerializable()})
96+
97+
assert logger.has_captured_logs()
98+
99+
captured = capsys.readouterr()
100+
101+
assert "Exception initializing logger write stream" not in captured.err
102+
assert "Exception writing to logger event stream" not in captured.err
103+
assert "Exception closing logger write stream" not in captured.err
104+
assert "NonJsonSerializable is not JSON serializable" not in captured.err
105+
106+
records = get_instigation_log_records(instance, log_key)
107+
108+
assert len(records) >= 2
109+
assert "test-repo - test-instigator - log with extras" in {
110+
record.get("msg") for record in records if record.get("msg")
111+
}
112+
matching_records = [record for record in records if record.get("non_json")]
113+
assert matching_records and matching_records[0]["non_json"] == "non-jsonable-object"
114+
115+
instance.compute_log_manager.delete_logs(log_key=log_key)

0 commit comments

Comments
 (0)