Skip to content

Commit fbbba0e

Browse files
committed
trying how this could look like
1 parent dfa422c commit fbbba0e

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

sentry_sdk/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
from sentry_sdk.api import * # noqa
88

9+
from sentry_sdk.tracing import new_trace
10+
911
from sentry_sdk.consts import VERSION # noqa
1012

1113
__all__ = [ # noqa
@@ -43,6 +45,7 @@
4345
"start_span",
4446
"start_transaction",
4547
"trace",
48+
"new_trace",
4649
"monitor",
4750
"logger",
4851
"start_session",

sentry_sdk/tracing.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from __future__ import annotations
22
from datetime import datetime
3+
import functools
4+
import inspect
35
import json
46
import warnings
57

8+
import sentry_sdk
9+
610
from opentelemetry import trace as otel_trace, context
711
from opentelemetry.trace import (
812
format_trace_id,
@@ -20,6 +24,7 @@
2024
DEFAULT_SPAN_NAME,
2125
DEFAULT_SPAN_ORIGIN,
2226
BAGGAGE_HEADER_NAME,
27+
OP,
2328
SENTRY_TRACE_HEADER_NAME,
2429
SPANSTATUS,
2530
SPANDATA,
@@ -574,3 +579,95 @@ async def my_async_function():
574579
return start_child_span_decorator(func)
575580
else:
576581
return start_child_span_decorator
582+
583+
584+
def set_input_attributes(span, as_type, args, kwargs):
585+
# depending on `as_type` set some attributes on the span derived from args and kwargs
586+
pass
587+
588+
589+
def set_output_attributes(span, as_type, result):
590+
# depending on `as_type` set some attributes on the span derived from result
591+
pass
592+
593+
594+
DEFAULT_SPAN_OP = "function"
595+
596+
597+
def new_trace(func=None, *, as_type=None, name=None):
598+
def span_decorator(f, *a, **kw):
599+
@functools.wraps(f)
600+
async def async_wrapper(*args, **kwargs):
601+
op = kw.get("op", DEFAULT_SPAN_OP)
602+
span_name = name or f.__name__
603+
604+
with sentry_sdk.start_span(
605+
op=op,
606+
name=span_name,
607+
) as span:
608+
set_input_attributes(span, as_type, args, kwargs)
609+
610+
# run wrapped function
611+
result = await f(*args, **kwargs)
612+
613+
set_output_attributes(span, as_type, result)
614+
return result
615+
616+
@functools.wraps(f)
617+
def sync_wrapper(*args, **kwargs):
618+
op = kw.get("op", DEFAULT_SPAN_OP)
619+
span_name = name or f.__name__
620+
621+
with sentry_sdk.start_span(
622+
op=op,
623+
name=span_name,
624+
) as span:
625+
set_input_attributes(span, as_type, args, kwargs)
626+
627+
# run wrapped function
628+
result = f(*args, **kwargs)
629+
630+
set_output_attributes(span, as_type, result)
631+
return result
632+
633+
if inspect.iscoroutinefunction(f):
634+
wrapper = async_wrapper
635+
else:
636+
wrapper = sync_wrapper
637+
638+
return wrapper
639+
640+
def ai_chat_decorator(f):
641+
return span_decorator(f, op=OP.GEN_AI_CHAT)
642+
643+
def ai_agent_decorator(f):
644+
return span_decorator(f, op=OP.GEN_AI_INVOKE_AGENT)
645+
646+
def ai_tool_decorator(f):
647+
return span_decorator(f, op=OP.GEN_AI_EXECUTE_TOOL)
648+
649+
decorator_for_type = {
650+
"ai_chat": ai_chat_decorator,
651+
"ai_agent": ai_agent_decorator,
652+
"ai_tool": ai_tool_decorator,
653+
}
654+
decorator = decorator_for_type.get(as_type, span_decorator)
655+
656+
if func:
657+
return decorator(func)
658+
else:
659+
return decorator
660+
661+
662+
def update_current_span(op=None, name=None, attributes=None) -> None:
663+
current_span = sentry_sdk.get_current_span()
664+
665+
if op is not None:
666+
current_span.op = op
667+
668+
if name is not None:
669+
current_span.name = name
670+
671+
if attributes is not None:
672+
for key, value in attributes.items():
673+
current_span.set_attribute(key, value)

0 commit comments

Comments
 (0)