85742ab165
Deploy Documentation / deploy (push) Has been cancelled
CPU Test / Test (Utilities, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (LLM proxy, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Others, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Store, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Utilities, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Weave, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (AgentOps, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (LLM proxy, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Others, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Weave, latest, Python 3.13) (push) Has been cancelled
Dashboard / Chromatic (push) Has been cancelled
CPU Test / Lint - fast (push) Has been cancelled
CPU Test / Lint - next (push) Has been cancelled
CPU Test / Lint - slow (push) Has been cancelled
CPU Test / Lint - JavaScript (push) Has been cancelled
CPU Test / Build documentation (push) Has been cancelled
CPU Test / Test (AgentOps, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (LLM proxy, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Others, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Store, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Weave, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (AgentOps, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Store, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Utilities, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Weave, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (AgentOps, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (LLM proxy, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Others, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Store, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Utilities, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (JavaScript) (push) Has been cancelled
62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
# Copyright (c) Microsoft. All rights reserved.
|
|
|
|
import logging
|
|
from typing import Any, Dict, Optional
|
|
|
|
from agentlightning.semconv import AGL_MESSAGE, LightningSpanAttributes
|
|
from agentlightning.tracer.base import get_active_tracer
|
|
from agentlightning.tracer.dummy import DummyTracer
|
|
from agentlightning.types import Attributes, SpanLike
|
|
from agentlightning.utils.otel import flatten_attributes, sanitize_attributes
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def emit_message(message: str, attributes: Optional[Dict[str, Any]] = None, propagate: bool = True) -> None:
|
|
"""Emit a textual message as an OpenTelemetry span.
|
|
|
|
Commonly used for sending debugging and logging messages.
|
|
|
|
Args:
|
|
message: Human readable message to attach as a span attribute.
|
|
attributes: Additional attributes to attach to the message span.
|
|
propagate: Whether to propagate the span to exporters automatically.
|
|
|
|
!!! note
|
|
OpenTelemetry distinguishes between logs and spans. Emitting the message as a
|
|
span keeps all Agent Lightning telemetry in a single data store for analysis.
|
|
"""
|
|
if not isinstance(message, str): # type: ignore
|
|
raise TypeError(f"Message must be a string or list of strings, got: {type(message)}.")
|
|
|
|
if propagate:
|
|
tracer = get_active_tracer()
|
|
if tracer is None:
|
|
raise RuntimeError("No active tracer found. Cannot emit message span.")
|
|
else:
|
|
tracer = DummyTracer()
|
|
span_attributes: Attributes = {LightningSpanAttributes.MESSAGE_BODY.value: message}
|
|
if attributes:
|
|
flattened = flatten_attributes(attributes, expand_leaf_lists=False)
|
|
span_attributes.update(sanitize_attributes(flattened))
|
|
logger.debug("Emitting message span with message: %s", message)
|
|
tracer.create_span(
|
|
AGL_MESSAGE,
|
|
attributes=span_attributes,
|
|
)
|
|
|
|
|
|
def get_message_value(span: SpanLike) -> Optional[str]:
|
|
"""Extract the message string from a message span.
|
|
|
|
Args:
|
|
span: Span-like object to extract the message from.
|
|
"""
|
|
span_attributes = span.attributes or {}
|
|
if LightningSpanAttributes.MESSAGE_BODY.value not in span_attributes:
|
|
return None
|
|
message = span_attributes[LightningSpanAttributes.MESSAGE_BODY.value]
|
|
if isinstance(message, str):
|
|
return message
|
|
raise TypeError(f"Message must be a string, got: {type(message)}.")
|