|
1 | 1 | import contextlib |
| 2 | +import sys |
2 | 3 | from collections import ChainMap |
3 | 4 | from types import SimpleNamespace |
4 | 5 | from typing import Any, Mapping |
5 | 6 |
|
6 | 7 | import pytest |
7 | 8 | from inline_snapshot import snapshot |
8 | 9 |
|
| 10 | +import logfire |
9 | 11 | from logfire._internal.formatter import FormattingFailedWarning, chunks_formatter, logfire_format |
10 | 12 | from logfire._internal.scrubbing import NOOP_SCRUBBER, JsonPath, Scrubber |
| 13 | +from logfire.testing import TestExporter |
11 | 14 |
|
12 | 15 |
|
13 | 16 | def chunks(format_string: str, kwargs: Mapping[str, Any]): |
@@ -178,3 +181,50 @@ def test_internal_exception_formatting(caplog: pytest.LogCaptureFixture): |
178 | 181 | assert len(caplog.records) == 1 |
179 | 182 | assert caplog.records[0].message.startswith('Caught an internal error in Logfire.') |
180 | 183 | assert str(caplog.records[0].exc_info[1]) == 'bad scrubber' # type: ignore |
| 184 | + |
| 185 | + |
| 186 | +@pytest.mark.skipif(sys.version_info[:2] == (3, 8), reason='fstring magic is only for 3.9+') |
| 187 | +@pytest.mark.anyio |
| 188 | +async def test_await_in_fstring(exporter: TestExporter): |
| 189 | + """Test that logfire.info(f'{foo(await bar())}') evaluates the await expression and logs a warning.""" |
| 190 | + |
| 191 | + async def bar() -> str: |
| 192 | + return 'content data' |
| 193 | + |
| 194 | + def foo(x: str) -> str: |
| 195 | + return x |
| 196 | + |
| 197 | + with pytest.warns(FormattingFailedWarning) as warnings: |
| 198 | + logfire.info(f'{foo(await bar())}') |
| 199 | + [warning] = warnings |
| 200 | + assert str(warning.message) == snapshot( |
| 201 | + '\n' |
| 202 | + ' Cannot evaluate await expression in f-string. Pre-evaluate the expression before logging.\n' |
| 203 | + ' For example, change:\n' |
| 204 | + ' logfire.info(f"{await get_value()}")\n' |
| 205 | + ' To:\n' |
| 206 | + ' value = await get_value()\n' |
| 207 | + ' logfire.info(f"{value}")\n' |
| 208 | + ' The problematic f-string value was: foo(await bar())' |
| 209 | + ) |
| 210 | + |
| 211 | + assert exporter.exported_spans_as_dict() == snapshot( |
| 212 | + [ |
| 213 | + { |
| 214 | + 'name': f'{foo(await bar())}', |
| 215 | + 'context': {'trace_id': 1, 'span_id': 1, 'is_remote': False}, |
| 216 | + 'parent': None, |
| 217 | + 'start_time': 1000000000, |
| 218 | + 'end_time': 1000000000, |
| 219 | + 'attributes': { |
| 220 | + 'logfire.span_type': 'log', |
| 221 | + 'logfire.level_num': 9, |
| 222 | + 'logfire.msg_template': f'{foo(await bar())}', |
| 223 | + 'logfire.msg': 'content data', |
| 224 | + 'code.filepath': 'test_formatter.py', |
| 225 | + 'code.lineno': 123, |
| 226 | + 'code.function': 'test_await_in_fstring', |
| 227 | + }, |
| 228 | + } |
| 229 | + ] |
| 230 | + ) |
0 commit comments