Skip to content

Commit 3dc091f

Browse files
🐛 Fix verbose console formatting for enum types (#1073) (#1096)
Co-authored-by: rahul-netomi <[email protected]>
1 parent 68c34e7 commit 3dc091f

File tree

6 files changed

+57
-23
lines changed

6 files changed

+57
-23
lines changed

logfire/_internal/json_formatter.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import io
4-
from datetime import timedelta
4+
from datetime import date, datetime, time, timedelta
55
from functools import partial
66
from typing import Any, Callable, cast
77

@@ -30,9 +30,9 @@ def __init__(self, *, indent: int):
3030
'generator': partial(self._format_list_like, 'generator((', '))'),
3131
'bytes': self._format_bytes,
3232
'Decimal': partial(self._write, 'Decimal(', ')', True),
33-
'date': partial(self._write, 'date(', ')', True),
34-
'datetime': partial(self._write, 'datetime(', ')', True),
35-
'time': partial(self._write, 'time(', ')', True),
33+
'date': self._format_date,
34+
'datetime': self._format_datetime,
35+
'time': self._format_time,
3636
'timedelta': self._format_timedelta,
3737
'Enum': partial(self._write, '(', ')', True),
3838
'IPv4Address': partial(self._write, 'IPv4Address(', ')', True),
@@ -273,6 +273,15 @@ def _format_data_frame(self, _indent_current: int, value: list[Any], schema: JSO
273273
real_row_count=schema.get('x-row-count', 0),
274274
)
275275

276+
def _format_date(self, _indent_current: int, value: Any, schema: JSONSchema | None) -> None:
277+
self._write('', '', True, 0, date.fromisoformat(value) if isinstance(value, str) else value, schema)
278+
279+
def _format_datetime(self, _indent_current: int, value: Any, schema: JSONSchema | None) -> None:
280+
self._write('', '', True, 0, datetime.fromisoformat(value) if isinstance(value, str) else value, schema)
281+
282+
def _format_time(self, _indent_current: int, value: Any, schema: JSONSchema | None) -> None:
283+
self._write('', '', True, 0, time.fromisoformat(value) if isinstance(value, str) else value, schema)
284+
276285

277286
json_args_value_formatter = JsonArgsValueFormatter(indent=4)
278287
json_args_value_formatter_compact = JsonArgsValueFormatter(indent=0)

logfire/_internal/json_schema.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ def type_to_schema() -> dict[type[Any], JsonDict | Callable[[Any, set[int]], Jso
4343
bytes: _bytes_schema,
4444
bytearray: _bytearray_schema,
4545
Enum: _enum_schema,
46-
Decimal: {'type': 'string', 'format': 'decimal'},
47-
datetime.datetime: {'type': 'string', 'format': 'date-time'},
48-
datetime.date: {'type': 'string', 'format': 'date'},
49-
datetime.time: {'type': 'string', 'format': 'time'},
46+
Decimal: {'type': 'string', 'format': 'decimal', 'x-python-datatype': 'Decimal'},
47+
datetime.datetime: {'type': 'string', 'format': 'date-time', 'x-python-datatype': 'datetime'},
48+
datetime.date: {'type': 'string', 'format': 'date', 'x-python-datatype': 'date'},
49+
datetime.time: {'type': 'string', 'format': 'time', 'x-python-datatype': 'time'},
5050
datetime.timedelta: {'type': 'string', 'x-python-datatype': 'timedelta'},
5151
GeneratorType: _generator_schema,
5252
IPv4Address: {'type': 'string', 'format': 'ipv4'},

logfire/_internal/main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import sys
77
import warnings
88
from contextvars import Token
9+
from enum import Enum
910
from functools import cached_property
1011
from time import time
1112
from typing import (
@@ -2450,7 +2451,9 @@ def prepare_otlp_attributes(attributes: dict[str, Any]) -> dict[str, otel_types.
24502451

24512452
def prepare_otlp_attribute(value: Any) -> otel_types.AttributeValue:
24522453
"""Convert a user attribute to an OpenTelemetry compatible type."""
2453-
if isinstance(value, int):
2454+
if isinstance(value, Enum):
2455+
return logfire_json_dumps(value)
2456+
elif isinstance(value, int):
24542457
if value > OTLP_MAX_INT_SIZE:
24552458
warnings.warn(
24562459
f'Integer value {value} is larger than the maximum OTLP integer size of {OTLP_MAX_INT_SIZE} (64-bits), '

tests/test_console_exporter.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from __future__ import annotations
33

44
import decimal
5+
import enum
56
import io
67
import sys
78
from datetime import datetime
@@ -943,19 +944,40 @@ def test_other_json_schema_types(capsys: pytest.CaptureFixture[str]) -> None:
943944
console=ConsoleOptions(verbose=True, colors='never', include_timestamps=False),
944945
)
945946

947+
class MyEnum(enum.Enum):
948+
"""Enum with string values."""
949+
950+
ABC = 'abc'
951+
952+
class MyStrEnum(str, enum.Enum):
953+
"""String-based Enum."""
954+
955+
STR = 'str_val'
956+
957+
class MyIntEnum(int, enum.Enum):
958+
"""Integer-based Enum."""
959+
960+
INT = 1
961+
946962
logfire.info(
947963
'hi',
948964
d=datetime(2020, 12, 31, 12, 34, 56),
949965
x=None,
950966
v=decimal.Decimal('1.0'),
967+
e=MyEnum.ABC,
968+
se=MyStrEnum.STR,
969+
ie=MyIntEnum.INT,
951970
)
952971

953972
assert capsys.readouterr().out.splitlines() == snapshot(
954973
[
955974
'hi',
956975
IsStr(),
957-
'│ d=2020-12-31T12:34:56',
976+
'│ d=datetime.datetime(2020, 12, 31, 12, 34, 56)',
958977
'│ x=None',
959-
'│ v=1.0',
978+
"│ v=Decimal('1.0')",
979+
"│ e=MyEnum('abc')",
980+
"│ se=MyStrEnum('str_val')",
981+
'│ ie=MyIntEnum(1)',
960982
]
961983
)

tests/test_json_args.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,28 +317,28 @@ class StrSubclass(str):
317317
Decimal('1.7'),
318318
'1.7',
319319
'"1.7"',
320-
{'type': 'string', 'format': 'decimal'},
320+
{'type': 'string', 'format': 'decimal', 'x-python-datatype': 'Decimal'},
321321
id='decimal',
322322
),
323323
pytest.param(
324324
date(2023, 1, 1),
325325
'2023-01-01',
326326
'"2023-01-01"',
327-
{'type': 'string', 'format': 'date'},
327+
{'type': 'string', 'format': 'date', 'x-python-datatype': 'date'},
328328
id='date',
329329
),
330330
pytest.param(
331331
datetime(2023, 1, 1, 10, 10),
332332
'2023-01-01 10:10:00',
333333
'"2023-01-01T10:10:00"',
334-
{'type': 'string', 'format': 'date-time'},
334+
{'type': 'string', 'format': 'date-time', 'x-python-datatype': 'datetime'},
335335
id='datetime',
336336
),
337337
pytest.param(
338338
time(12, 10),
339339
'12:10:00',
340340
'"12:10:00"',
341-
{'type': 'string', 'format': 'time'},
341+
{'type': 'string', 'format': 'time', 'x-python-datatype': 'time'},
342342
id='time',
343343
),
344344
pytest.param(
@@ -973,7 +973,7 @@ class MyPydanticDataclass:
973973
'...'
974974
'og_non_scalar_complex_args.<locals>.MyPydanticDataclass(p=20)}'
975975
),
976-
'logfire.json_schema': '{"type":"object","properties":{"a":{},"complex_list":{"type":"array","prefixItems":[{},{},{"type":"object","title":"MyModel","x-python-datatype":"PydanticModel","properties":{"y":{"type":"string","format":"date-time"}}},{"type":"object","title":"MyDataclass","x-python-datatype":"dataclass"},{"type":"object","title":"MyPydanticDataclass","x-python-datatype":"dataclass"}]},"complex_dict":{"type":"object","properties":{"model":{"type":"object","title":"MyModel","x-python-datatype":"PydanticModel","properties":{"y":{"type":"string","format":"date-time"}}},"dataclass":{"type":"object","title":"MyDataclass","x-python-datatype":"dataclass"},"pydantic_dataclass":{"type":"object","title":"MyPydanticDataclass","x-python-datatype":"dataclass"}}}}}',
976+
'logfire.json_schema': '{"type":"object","properties":{"a":{},"complex_list":{"type":"array","prefixItems":[{},{},{"type":"object","title":"MyModel","x-python-datatype":"PydanticModel","properties":{"y":{"type":"string","format":"date-time","x-python-datatype":"datetime"}}},{"type":"object","title":"MyDataclass","x-python-datatype":"dataclass"},{"type":"object","title":"MyPydanticDataclass","x-python-datatype":"dataclass"}]},"complex_dict":{"type":"object","properties":{"model":{"type":"object","title":"MyModel","x-python-datatype":"PydanticModel","properties":{"y":{"type":"string","format":"date-time","x-python-datatype":"datetime"}}},"dataclass":{"type":"object","title":"MyDataclass","x-python-datatype":"dataclass"},"pydantic_dataclass":{"type":"object","title":"MyPydanticDataclass","x-python-datatype":"dataclass"}}}}}',
977977
'code.filepath': 'test_json_args.py',
978978
'code.lineno': 123,
979979
'code.function': 'test_log_non_scalar_complex_args',

tests/test_json_args_formatting.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,19 @@
148148
pytest.param(
149149
'2023-01-01',
150150
{'type': 'string', 'x-python-datatype': 'date'},
151-
"date('2023-01-01')",
151+
'datetime.date(2023, 1, 1)',
152152
id='date',
153153
),
154154
pytest.param(
155155
'2023-01-01T10:10:00',
156156
{'type': 'string', 'x-python-datatype': 'datetime'},
157-
"datetime('2023-01-01T10:10:00')",
157+
'datetime.datetime(2023, 1, 1, 10, 10)',
158158
id='datetime',
159159
),
160160
pytest.param(
161161
'12:10:00',
162162
{'type': 'string', 'x-python-datatype': 'time'},
163-
"time('12:10:00')",
163+
'datetime.time(12, 10)',
164164
id='time',
165165
),
166166
pytest.param(
@@ -494,7 +494,7 @@ def test_nested_json_args_value_formatting():
494494
1,
495495
MyModel(
496496
x='x',
497-
y=datetime('2023-01-01T00:00:00'),
497+
y=datetime.datetime(2023, 1, 1, 0, 0),
498498
),
499499
MyDataclass(
500500
t=10,
@@ -554,19 +554,19 @@ def test_nested_json_args_value_formatting():
554554
pytest.param(
555555
'2023-01-01',
556556
{'type': 'string', 'x-python-datatype': 'date'},
557-
"date('2023-01-01')",
557+
'datetime.date(2023, 1, 1)',
558558
id='date',
559559
),
560560
pytest.param(
561561
'2023-01-01T10:10:00',
562562
{'type': 'string', 'x-python-datatype': 'datetime'},
563-
"datetime('2023-01-01T10:10:00')",
563+
'datetime.datetime(2023, 1, 1, 10, 10)',
564564
id='datetime',
565565
),
566566
pytest.param(
567567
'12:10:00',
568568
{'type': 'string', 'x-python-datatype': 'time'},
569-
"time('12:10:00')",
569+
'datetime.time(12, 10)',
570570
id='time',
571571
),
572572
pytest.param(

0 commit comments

Comments
 (0)