From 07d9b2724010e13662f9a370d7406d3f6d57bb04 Mon Sep 17 00:00:00 2001 From: Bartosz Mikulski Date: Mon, 15 Jul 2024 08:29:47 +0200 Subject: [PATCH] feat: Add OpenTelemetry event handler (#70) --- docs/assets/otel_handler_jeager.png | Bin 0 -> 110440 bytes docs/how-to/trace_runs_with_otel.md | 126 ++++++++++ docs/reference/event_handlers/otel_handler.md | 3 + mkdocs.yml | 2 + setup.cfg | 1 + src/dbally/audit/__init__.py | 5 +- .../event_handlers/otel_event_handler.py | 220 ++++++++++++++++++ tests/unit/audit/__init__.py | 0 tests/unit/audit/event_handlers/__init__.py | 0 .../event_handlers/test_otel_event_handler.py | 117 ++++++++++ 10 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 docs/assets/otel_handler_jeager.png create mode 100644 docs/how-to/trace_runs_with_otel.md create mode 100644 docs/reference/event_handlers/otel_handler.md create mode 100644 src/dbally/audit/event_handlers/otel_event_handler.py create mode 100644 tests/unit/audit/__init__.py create mode 100644 tests/unit/audit/event_handlers/__init__.py create mode 100644 tests/unit/audit/event_handlers/test_otel_event_handler.py diff --git a/docs/assets/otel_handler_jeager.png b/docs/assets/otel_handler_jeager.png new file mode 100644 index 0000000000000000000000000000000000000000..5f00f81f8408ee57680ee33ff5fcf3b768f9d309 GIT binary patch literal 110440 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.9.0 click~=8.1.7 numpy>=1.24.0 + opentelemetry-api>=1.0.0 [options.extras_require] litellm = diff --git a/src/dbally/audit/__init__.py b/src/dbally/audit/__init__.py index 73253f71..96f57f0e 100644 --- a/src/dbally/audit/__init__.py +++ b/src/dbally/audit/__init__.py @@ -7,14 +7,15 @@ except ImportError: pass +from .event_handlers.otel_event_handler import OtelEventHandler from .event_tracker import EventTracker -from .events import Event, LLMEvent, RequestEnd, RequestStart, SimilarityEvent +from .events import LLMEvent, RequestEnd, RequestStart, SimilarityEvent from .spans import EventSpan __all__ = [ "CLIEventHandler", "LangSmithEventHandler", - "Event", + "OtelEventHandler", "EventHandler", "EventTracker", "EventSpan", diff --git a/src/dbally/audit/event_handlers/otel_event_handler.py b/src/dbally/audit/event_handlers/otel_event_handler.py new file mode 100644 index 00000000..00a106a2 --- /dev/null +++ b/src/dbally/audit/event_handlers/otel_event_handler.py @@ -0,0 +1,220 @@ +import json +from dataclasses import dataclass +from typing import Any, Callable, Optional + +from opentelemetry import trace +from opentelemetry.trace import Span, SpanKind, StatusCode, TracerProvider +from opentelemetry.util.types import AttributeValue + +from dbally.audit.event_handlers.base import EventHandler +from dbally.audit.events import Event, LLMEvent, RequestEnd, RequestStart, SimilarityEvent + +TRACER_NAME = "db-ally.events" +FORBIDDEN_CONTEXT_KEYS = {"filter_mask"} + +TransformFn = Optional[Callable[[Any], Optional[AttributeValue]]] + + +def _optional_str(value: Optional[any]) -> Optional[str]: + return None if value is None else str(value) + + +@dataclass +class SpanHandler: + """Handles span attributes and lifecycle""" + + span: Span + record_inputs: bool + record_outputs: bool + + def set(self, key: str, value: Optional[Any], transform: TransformFn = None) -> "SpanHandler": + """ + Sets a value as span attribute under given key if the value exists. Optionally one can add transform function to + change value from any to valid OpenTelemetry attribute type. + + Args: + key: attribute name + value: attribute value. If None, the value is not set + transform: optional function to transform from Any to valid OTel AttributeValue + + Returns: + self, for chaining calls + """ + value = value if transform is None else transform(value) + if value is not None: + self.span.set_attribute(key, value) + + return self + + def set_input(self, key: str, value: Optional[Any], transform: TransformFn = None) -> "SpanHandler": + """ + Sets a value, that is used as model input, under given key if the value exists. If the class does not record + inputs, then the value is not set. Optionally one can add transform function to change value from any to valid + OpenTelemetry attribute type. + + Args: + key: attribute name + value: attribute value. If None, the value is not set. If record_inputs is False, the value is not set. + transform: optional function to transform from Any to valid OTel AttributeValue + + Returns: + self, for chaining calls + """ + value = value if transform is None else transform(value) + if value is not None and self.record_inputs: + self.span.set_attribute(key, value) + + return self + + def set_output(self, key: str, value: Optional[Any], transform: TransformFn = None) -> "SpanHandler": + """ + Sets a value, that is the model output under, given key if the value exists. If the class does not record + inputs, then the value is not set. Optionally one can add transform function to change value from any to valid + OpenTelemetry attribute type. + + Args: + key: attribute name + value: attribute value. If None, the value is not set. If record_output is False, the value is not set. + transform: optional function to transform from Any to valid OTel AttributeValue + + Returns: + self, for chaining calls + """ + value = value if transform is None else transform(value) + if value is not None and self.record_outputs: + self.span.set_attribute(key, value) + + return self + + def end_succesfully(self) -> None: + """Sets status of the span to OK and ends the span with current time""" + self.span.set_status(StatusCode.OK) + self.span.end() + + +class OtelEventHandler(EventHandler[SpanHandler, SpanHandler]): + """ + This handler emits OpenTelemetry spans for recorded events. + """ + + def __init__( + self, provider: Optional[TracerProvider] = None, record_inputs: bool = True, record_outputs: bool = True + ) -> None: + """ + Initialize OtelEventHandler. By default, it will try to use globaly configured TracerProvider. Pass it + explicitly if you want custom implementation, or you do not use OTel auto-instrumentation. + + To comply with the + [OTel Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/llm-spans/#configuration) + recording of inputs and outputs can be disabled. + + Args: + provider: Optional tracer provider. By default global provider is used. + record_inputs: if true (default) all inputs are recorded as span attributes. Depending on usecase it maybe + turned off, to save resources and improve performance. + record_outputs: if true (default) all outputs are recorded as span attributes. Depending on usecase it + maybe turned off, to save resources and improve performance. + """ + self.record_inputs = record_inputs + self.record_outputs = record_outputs + if provider is None: + self.tracer = trace.get_tracer(TRACER_NAME) + else: + self.tracer = provider.get_tracer(TRACER_NAME) + + def _handle_span(self, span: Span) -> SpanHandler: + return SpanHandler(span, self.record_inputs, self.record_outputs) + + async def request_start(self, user_request: RequestStart) -> SpanHandler: + """ + Initializes new OTel Span as a parent. + + Args: + user_request: The start of the request. + + Returns: + span object as a parent for all subsequent events for this request + """ + with self.tracer.start_as_current_span("request", end_on_exit=False, kind=SpanKind.SERVER) as span: + return ( + self._handle_span(span) + .set("db-ally.user.collection", user_request.collection_name) + .set_input("db-ally.user.question", user_request.question) + ) + + async def event_start(self, event: Event, request_context: SpanHandler) -> SpanHandler: + """ + Starts a new event in a system as a span. Uses request span as a parent. + + Args: + event: Event to register + request_context: Parent span for this event + + Returns: + span object capturing start of execution for this event + + Raises: + ValueError: it is thrown when unknown event type is passed as argument + """ + if isinstance(event, LLMEvent): + with self._new_child_span(request_context, "llm") as span: + return ( + self._handle_span(span) + .set("db-ally.llm.type", event.type) + .set_input("db-ally.llm.prompts", json.dumps(event.prompt)) + ) + + if isinstance(event, SimilarityEvent): + with self._new_child_span(request_context, "similarity") as span: + return ( + self._handle_span(span) + .set("db-ally.similarity.store", event.store) + .set("db-ally.similarity.fetcher", event.fetcher) + .set_input("db-ally.similarity.input", event.input_value) + ) + + raise ValueError(f"Unsuported event: {type(event)}") + + async def event_end(self, event: Optional[Event], request_context: SpanHandler, event_context: SpanHandler) -> None: + """ + Finalizes execution of the event, ending a span for this event. + + Args: + event: optional event information + request_context: parent span + event_context: event span + """ + + if isinstance(event, LLMEvent): + event_context.set("db-ally.llm.response-tokes", event.completion_tokens).set_output( + "db-ally.llm.response", event.response + ) + + if isinstance(event, SimilarityEvent) and self.record_outputs: + event_context.set("db-ally.similarity.output", event.output_value) + + event_context.end_succesfully() + + async def request_end(self, output: RequestEnd, request_context: SpanHandler) -> None: + """ + Finalizes entire request, ending the span for this request. + + Args: + output: output generated for this request + request_context: span to be closed + """ + request_context.set_output("db-ally.result.textual", output.result.textual_response).set( + "db-ally.result.execution-time", output.result.execution_time + ).set("db-ally.result.execution-time-view", output.result.execution_time_view).set( + "db-ally.result.view-name", output.result.view_name + ) + + for key, value in output.result.context.items(): + if key not in FORBIDDEN_CONTEXT_KEYS: + request_context.set(f"db-ally.result.context.{key}", value, transform=_optional_str) + + request_context.end_succesfully() + + def _new_child_span(self, parent: SpanHandler, name: str): + context = trace.set_span_in_context(parent.span) + return self.tracer.start_as_current_span(name, context=context, end_on_exit=False, kind=SpanKind.CLIENT) diff --git a/tests/unit/audit/__init__.py b/tests/unit/audit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/audit/event_handlers/__init__.py b/tests/unit/audit/event_handlers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/audit/event_handlers/test_otel_event_handler.py b/tests/unit/audit/event_handlers/test_otel_event_handler.py new file mode 100644 index 00000000..c7a8a7a6 --- /dev/null +++ b/tests/unit/audit/event_handlers/test_otel_event_handler.py @@ -0,0 +1,117 @@ +from typing import Dict, Mapping, Optional, Union + +from opentelemetry import trace +from opentelemetry.trace import Span, StatusCode +from opentelemetry.util.types import AttributeValue + +from dbally.audit.event_handlers.otel_event_handler import SpanHandler + + +class MockSpan(Span): + def __init__(self) -> None: + super().__init__() + self.attributes = {} + self.status = StatusCode.UNSET + self.is_finished = False + + def end(self, end_time: Optional[int] = None) -> None: + self.is_finished = True + + def get_span_context(self) -> trace.SpanContext: + raise NotImplementedError + + def set_attributes(self, attributes: Dict[str, AttributeValue]) -> None: + self.attributes.update(attributes) + + def set_attribute(self, key: str, value: AttributeValue) -> None: + self.attributes[key] = value + + def add_event( + self, name: str, attributes: Optional[Mapping[str, AttributeValue]] = None, timestamp: Optional[int] = None + ) -> None: + raise NotImplementedError + + def update_name(self, name: str) -> None: + raise NotImplementedError + + def is_recording(self) -> bool: + raise NotImplementedError + + def set_status(self, status: Union[trace.Status, StatusCode], description: Optional[str] = None) -> None: + self.status = status.status_code if isinstance(status, trace.Status) else status + + def record_exception( + self, + exception: BaseException, + attributes: Optional[Mapping[str, AttributeValue]] = None, + timestamp: Optional[int] = None, + escaped: bool = False, + ) -> None: + raise NotImplementedError + + +def test_span_handler_sets_all(): + span = MockSpan() + + handler = SpanHandler(span, record_inputs=True, record_outputs=True) + handler.set("standard", "1") + handler.set_input("inputs", "2") + handler.set_output("outputs", "3") + handler.end_succesfully() + + assert span.attributes.get("standard") == "1" + assert span.attributes.get("inputs") == "2" + assert span.attributes.get("outputs") == "3" + assert span.status == StatusCode.OK + assert span.is_finished + + +def test_span_handler_sets_without_input(): + span = MockSpan() + + handler = SpanHandler(span, record_inputs=False, record_outputs=True) + handler.set("standard", "1") + handler.set_input("inputs", "2") + handler.set_output("outputs", "3") + handler.end_succesfully() + + assert span.attributes.get("standard") == "1" + assert span.attributes.get("inputs") is None + assert span.attributes.get("outputs") == "3" + assert span.status == StatusCode.OK + assert span.is_finished + + +def test_span_handler_sets_without_outputs(): + span = MockSpan() + + handler = SpanHandler(span, record_inputs=True, record_outputs=False) + handler.set("standard", "1") + handler.set_input("inputs", "2") + handler.set_output("outputs", "3") + handler.end_succesfully() + + assert span.attributes.get("standard") == "1" + assert span.attributes.get("inputs") == "2" + assert span.attributes.get("outputs") is None + assert span.status == StatusCode.OK + assert span.is_finished + + +def test_span_handler_sets_with_transformation(): + span = MockSpan() + + def transform_fn(x: str): + return None if x == "foo" else x.upper() + + handler = SpanHandler(span, record_inputs=True, record_outputs=True) + handler.set("standard", "foo", transform=transform_fn) + handler.set_input("inputs", "bar", transform=transform_fn) + handler.set_output("outputs", "baz", transform=transform_fn) + handler.end_succesfully() + + assert span.attributes.get("standard") is None + assert span.attributes.get("inputs") == "BAR" + assert span.attributes.get("outputs") == "BAZ" + assert span.status == StatusCode.OK + assert span.is_finished