ai-station/.venv/lib/python3.12/site-packages/opentelemetry/instrumentation/llamaindex/utils.py

105 lines
2.7 KiB
Python

import dataclasses
import json
import logging
import os
import traceback
from contextlib import asynccontextmanager
from opentelemetry import context as context_api
from opentelemetry._logs import Logger
from opentelemetry.instrumentation.llamaindex.config import Config
from opentelemetry.semconv_ai import SpanAttributes
TRACELOOP_TRACE_CONTENT = "TRACELOOP_TRACE_CONTENT"
def _with_tracer_wrapper(func):
def _with_tracer(tracer):
def wrapper(wrapped, instance, args, kwargs):
return func(tracer, wrapped, instance, args, kwargs)
return wrapper
return _with_tracer
@asynccontextmanager
async def start_as_current_span_async(tracer, *args, **kwargs):
with tracer.start_as_current_span(*args, **kwargs) as span:
yield span
def should_send_prompts():
return (
os.getenv(TRACELOOP_TRACE_CONTENT) or "true"
).lower() == "true" or context_api.get_value("override_enable_content_tracing")
def dont_throw(func):
"""
A decorator that wraps the passed in function and logs exceptions instead of throwing them.
@param func: The function to wrap
@return: The wrapper function
"""
# Obtain a logger specific to the function's module
logger = logging.getLogger(func.__module__)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
logger.debug(
"OpenLLMetry failed to trace in %s, error: %s",
func.__name__,
traceback.format_exc(),
)
if Config.exception_logger:
Config.exception_logger(e)
return wrapper
class JSONEncoder(json.JSONEncoder):
def default(self, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
elif hasattr(o, "json"):
return o.json()
elif hasattr(o, "to_json"):
return o.to_json()
return super().default(o)
@dont_throw
def process_request(span, args, kwargs):
if should_send_prompts():
span.set_attribute(
SpanAttributes.TRACELOOP_ENTITY_INPUT,
json.dumps({"args": args, "kwargs": kwargs}, cls=JSONEncoder),
)
@dont_throw
def process_response(span, res):
if should_send_prompts():
span.set_attribute(
SpanAttributes.TRACELOOP_ENTITY_OUTPUT,
json.dumps(res, cls=JSONEncoder),
)
def is_role_valid(role: str) -> bool:
return role in ["user", "assistant", "system", "tool"]
def should_emit_events() -> bool:
"""
Checks if the instrumentation isn't using the legacy attributes
and if the event logger is not None.
"""
return not Config.use_legacy_attributes and isinstance(
Config.event_logger, Logger
)