Skip to content

Commit c9e1d15

Browse files
committed
fix: use Z suffix for UTC timestamps and omit null trace_id
- LogEntry.__post_init__: use strftime with Z suffix instead of isoformat() which produces +00:00. The server's Zod schema (z.string().datetime()) only accepts the Z suffix. - Normalize caller-supplied +00:00 offset to Z as well. - LogEntry.to_dict(): only include trace_id when it is not None. The server's Zod schema (z.string().optional()) rejects null; only undefined (omitted) or a string value are valid.
1 parent a0b0aa4 commit c9e1d15

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

logtide_sdk/models.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,22 @@ class LogEntry:
3131
def __post_init__(self) -> None:
3232
"""Initialize default values."""
3333
if self.time is None:
34-
self.time = datetime.now(timezone.utc).isoformat()
34+
self.time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
35+
elif self.time.endswith("+00:00"):
36+
self.time = self.time[:-6] + "Z"
3537

3638
def to_dict(self) -> Dict[str, Any]:
3739
"""Convert to dictionary for JSON serialization."""
38-
return {
40+
result: Dict[str, Any] = {
3941
"service": self.service,
4042
"level": self.level.value,
4143
"message": self.message,
4244
"time": self.time,
4345
"metadata": self.metadata,
44-
"trace_id": self.trace_id,
4546
}
47+
if self.trace_id is not None:
48+
result["trace_id"] = self.trace_id
49+
return result
4650

4751

4852
@dataclass

tests/test_v084.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,50 @@ def test_error_method_uses_exception_key():
202202
# ---------------------------------------------------------------------------
203203

204204

205-
def test_log_entry_time_is_timezone_aware():
206-
"""LogEntry.time must include timezone offset (not naive UTC)."""
205+
def test_log_entry_time_uses_z_suffix():
206+
"""LogEntry.time must use Z suffix for UTC (required by server schema)."""
207207
entry = LogEntry(service="svc", level=LogLevel.INFO, message="hello")
208208
assert entry.time is not None
209-
# timezone.utc isoformat produces '+00:00' suffix
210-
assert "+00:00" in entry.time or "Z" in entry.time
209+
assert entry.time.endswith("Z")
210+
assert "+00:00" not in entry.time
211+
212+
213+
def test_log_entry_normalizes_offset_to_z():
214+
"""Caller-supplied +00:00 offset must be normalized to Z."""
215+
entry = LogEntry(
216+
service="svc",
217+
level=LogLevel.INFO,
218+
message="hello",
219+
time="2026-04-05T10:00:00.123456+00:00",
220+
)
221+
assert entry.time == "2026-04-05T10:00:00.123456Z"
222+
223+
224+
def test_log_entry_preserves_non_utc_offset():
225+
"""Non-UTC offsets must be left as-is (caller's responsibility)."""
226+
entry = LogEntry(
227+
service="svc",
228+
level=LogLevel.INFO,
229+
message="hello",
230+
time="2026-04-05T10:00:00+03:00",
231+
)
232+
assert entry.time == "2026-04-05T10:00:00+03:00"
233+
234+
235+
def test_to_dict_omits_none_trace_id():
236+
"""to_dict() must omit trace_id when None (server rejects null)."""
237+
entry = LogEntry(service="svc", level=LogLevel.INFO, message="hello")
238+
d = entry.to_dict()
239+
assert "trace_id" not in d
240+
241+
242+
def test_to_dict_includes_trace_id_when_set():
243+
"""to_dict() must include trace_id when it has a value."""
244+
entry = LogEntry(
245+
service="svc", level=LogLevel.INFO, message="hello", trace_id="abc-123"
246+
)
247+
d = entry.to_dict()
248+
assert d["trace_id"] == "abc-123"
211249

212250

213251
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)