
    i                         d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZmZmZmZ ddl
mZ dZd	Zd
Zddedz  defdZ	 ddeeef   dz  deeef   dz  fdZdededdfdZdeeef   dz  de	fdZg dZy)a  OpenTelemetry instrumentation for FastMCP.

This module provides native OpenTelemetry integration for FastMCP servers and clients.
It uses only the opentelemetry-api package, so telemetry is a no-op unless the user
installs an OpenTelemetry SDK and configures exporters.

Example usage with SDK:
    ```python
    from opentelemetry import trace
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor

    # Configure the SDK (user responsibility)
    provider = TracerProvider()
    provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
    trace.set_tracer_provider(provider)

    # Now FastMCP will emit traces
    from fastmcp import FastMCP
    mcp = FastMCP("my-server")
    ```
    )Any)context)	propagatetrace)Context)SpanStatus
StatusCodeTracer)
get_tracerfastmcptraceparent
tracestateNversionreturnc                 "    t        t        |       S )zGet the FastMCP tracer for creating spans.

    Args:
        version: Optional version string for the instrumentation

    Returns:
        A tracer instance. Returns a no-op tracer if no SDK is configured.
    )otel_get_tracerINSTRUMENTATION_NAME)r   s    M/mnt/e/genesis-system/.venv/lib/python3.12/site-packages/fastmcp/telemetry.pyr   r   &   s     /99    metac                     i }t        j                  |       i }d|v r|d   |t        <   d|v r|d   |t        <   |r
i | xs i |S | S )a@  Inject current trace context into a meta dict for MCP request propagation.

    Args:
        meta: Optional existing meta dict to merge with trace context

    Returns:
        A new dict containing the original meta (if any) plus trace context keys,
        or None if no trace context to inject and meta was None
    r   r   )r   injectTRACE_PARENT_KEYTRACE_STATE_KEY)r   carrier
trace_metas      r   inject_trace_contextr   2   sg     !GW!#J'.}'=
#$w&-l&;
?#-4:2-*--Kr   span	exceptionc                 v    | j                  |       | j                  t        t        j                               y)z3Record an exception on a span and set error status.N)record_exception
set_statusr	   r
   ERROR)r   r    s     r   record_span_errorr%   L   s'    )$OOF:++,-r   c                    t        j                         }|j                         j                  rt	        j
                         S | st	        j
                         S i }t        | v rt        | t                 |d<   t        | v rt        | t                 |d<   |rt        j                  |      S t	        j
                         S )a  Extract trace context from an MCP request meta dict.

    If already in a valid trace (e.g., from HTTP propagation), the existing
    trace context is preserved and meta is not used.

    Args:
        meta: The meta dict from an MCP request (ctx.request_context.meta)

    Returns:
        An OpenTelemetry Context with the extracted trace context,
        or the current context if no trace context found or already in a trace
    r   r   )r   get_current_spanget_span_contextis_validotel_contextget_currentr   strr   r   extract)r   current_spanr   s      r   extract_trace_contextr/   R   s     ))+L$$&//''))'')) G4!$T*:%;!<$ #D$9 :  ))##%%r   )r   r   r   r/   r   r   r%   )N)__doc__typingr   opentelemetryr   r*   r   r   opentelemetry.contextr   opentelemetry.tracer   r	   r
   r   r   r   r   r   r   r,   dictr   BaseExceptionr%   r/   __all__ r   r   <module>r9      s   .  1 * ) @ @ =    	:d
 	:f 	: #'
sCx.4
	#s(^d4.D .] .t .&S#X 5 &' &@r   