Spaces:
Paused
Paused
| import traceback | |
| from litellm._logging import verbose_logger | |
| class TraceloopLogger: | |
| """ | |
| WARNING: DEPRECATED | |
| Use the OpenTelemetry standard integration instead | |
| """ | |
| def __init__(self): | |
| try: | |
| from traceloop.sdk import Traceloop | |
| from traceloop.sdk.tracing.tracing import TracerWrapper | |
| except ModuleNotFoundError as e: | |
| verbose_logger.error( | |
| f"Traceloop not installed, try running 'pip install traceloop-sdk' to fix this error: {e}\n{traceback.format_exc()}" | |
| ) | |
| raise e | |
| Traceloop.init( | |
| app_name="Litellm-Server", | |
| disable_batch=True, | |
| ) | |
| self.tracer_wrapper = TracerWrapper() | |
| def log_event( | |
| self, | |
| kwargs, | |
| response_obj, | |
| start_time, | |
| end_time, | |
| user_id, | |
| print_verbose, | |
| level="DEFAULT", | |
| status_message=None, | |
| ): | |
| from opentelemetry.semconv.ai import SpanAttributes | |
| from opentelemetry.trace import SpanKind, Status, StatusCode | |
| try: | |
| print_verbose( | |
| f"Traceloop Logging - Enters logging function for model {kwargs}" | |
| ) | |
| tracer = self.tracer_wrapper.get_tracer() | |
| optional_params = kwargs.get("optional_params", {}) | |
| start_time = int(start_time.timestamp()) | |
| end_time = int(end_time.timestamp()) | |
| span = tracer.start_span( | |
| "litellm.completion", kind=SpanKind.CLIENT, start_time=start_time | |
| ) | |
| if span.is_recording(): | |
| span.set_attribute( | |
| SpanAttributes.LLM_REQUEST_MODEL, kwargs.get("model") | |
| ) | |
| if "stop" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_CHAT_STOP_SEQUENCES, | |
| optional_params.get("stop"), | |
| ) | |
| if "frequency_penalty" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_FREQUENCY_PENALTY, | |
| optional_params.get("frequency_penalty"), | |
| ) | |
| if "presence_penalty" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_PRESENCE_PENALTY, | |
| optional_params.get("presence_penalty"), | |
| ) | |
| if "top_p" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_REQUEST_TOP_P, optional_params.get("top_p") | |
| ) | |
| if "tools" in optional_params or "functions" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_REQUEST_FUNCTIONS, | |
| optional_params.get("tools", optional_params.get("functions")), | |
| ) | |
| if "user" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_USER, optional_params.get("user") | |
| ) | |
| if "max_tokens" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_REQUEST_MAX_TOKENS, | |
| kwargs.get("max_tokens"), | |
| ) | |
| if "temperature" in optional_params: | |
| span.set_attribute( | |
| SpanAttributes.LLM_REQUEST_TEMPERATURE, # type: ignore | |
| kwargs.get("temperature"), | |
| ) | |
| for idx, prompt in enumerate(kwargs.get("messages")): | |
| span.set_attribute( | |
| f"{SpanAttributes.LLM_PROMPTS}.{idx}.role", | |
| prompt.get("role"), | |
| ) | |
| span.set_attribute( | |
| f"{SpanAttributes.LLM_PROMPTS}.{idx}.content", | |
| prompt.get("content"), | |
| ) | |
| span.set_attribute( | |
| SpanAttributes.LLM_RESPONSE_MODEL, response_obj.get("model") | |
| ) | |
| usage = response_obj.get("usage") | |
| if usage: | |
| span.set_attribute( | |
| SpanAttributes.LLM_USAGE_TOTAL_TOKENS, | |
| usage.get("total_tokens"), | |
| ) | |
| span.set_attribute( | |
| SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, | |
| usage.get("completion_tokens"), | |
| ) | |
| span.set_attribute( | |
| SpanAttributes.LLM_USAGE_PROMPT_TOKENS, | |
| usage.get("prompt_tokens"), | |
| ) | |
| for idx, choice in enumerate(response_obj.get("choices")): | |
| span.set_attribute( | |
| f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.finish_reason", | |
| choice.get("finish_reason"), | |
| ) | |
| span.set_attribute( | |
| f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.role", | |
| choice.get("message").get("role"), | |
| ) | |
| span.set_attribute( | |
| f"{SpanAttributes.LLM_COMPLETIONS}.{idx}.content", | |
| choice.get("message").get("content"), | |
| ) | |
| if ( | |
| level == "ERROR" | |
| and status_message is not None | |
| and isinstance(status_message, str) | |
| ): | |
| span.record_exception(Exception(status_message)) | |
| span.set_status(Status(StatusCode.ERROR, status_message)) | |
| span.end(end_time) | |
| except Exception as e: | |
| print_verbose(f"Traceloop Layer Error - {e}") | |