Skip to content

Commit d109be0

Browse files
committed
chore: warn if span()'s caller function is a generator
1 parent 3dd9bb2 commit d109be0

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

logfire/_internal/main.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ def _span(
186186
_span_name: str | None = None,
187187
_level: LevelName | int | None = None,
188188
_links: Sequence[tuple[SpanContext, otel_types.Attributes]] = (),
189+
_warn_if_inside_generator: bool = True,
189190
) -> LogfireSpan:
190191
try:
191192
if _level is not None:
@@ -196,6 +197,20 @@ def _span(
196197
else:
197198
level_attributes = None
198199

200+
# we go two levels back to find the caller frame, as this method is called by logfire.span() method
201+
caller_frame = inspect.currentframe().f_back.f_back # type: ignore
202+
# check if the caller is a generator function by checking the co_flags attribute of the code object
203+
# and doing bit-wise AND checking for CO_GENERATOR or CO_ASYNC_GENERATOR value match
204+
caller_is_generator = bool(
205+
caller_frame and caller_frame.f_code.co_flags & (inspect.CO_GENERATOR | inspect.CO_ASYNC_GENERATOR)
206+
)
207+
208+
if caller_is_generator and _warn_if_inside_generator:
209+
warnings.warn(
210+
'Span is inside a generator function. See https://logfire.pydantic.dev/docs/reference/advanced/generators/#move-the-span-outside-the-generator.',
211+
RuntimeWarning,
212+
)
213+
199214
stack_info = get_user_stack_info()
200215
merged_attributes = {**stack_info, **attributes}
201216

@@ -538,6 +553,7 @@ def span(
538553
_span_name: str | None = None,
539554
_level: LevelName | None = None,
540555
_links: Sequence[tuple[SpanContext, otel_types.Attributes]] = (),
556+
_warn_if_inside_generator: bool = True,
541557
**attributes: Any,
542558
) -> LogfireSpan:
543559
"""Context manager for creating a span.
@@ -557,18 +573,21 @@ def span(
557573
_tags: An optional sequence of tags to include in the span.
558574
_level: An optional log level name.
559575
_links: An optional sequence of links to other spans. Each link is a tuple of a span context and attributes.
576+
_warn_if_inside_generator: Set to `False` to prevent a warning when instrumenting a generator function.
560577
attributes: The arguments to include in the span and format the message template with.
561578
Attributes starting with an underscore are not allowed.
562579
"""
563580
if any(k.startswith('_') for k in attributes):
564581
raise ValueError('Attribute keys cannot start with an underscore.')
582+
565583
return self._span(
566584
msg_template,
567585
attributes,
568586
_tags=_tags,
569587
_span_name=_span_name,
570588
_level=_level,
571589
_links=_links,
590+
_warn_if_inside_generator=_warn_if_inside_generator,
572591
)
573592

574593
@overload

0 commit comments

Comments
 (0)