
    Ki\                         d Z ddlZddlZddlZddlmZ ddlmZ ddlZddl	m
Z
 ddlmZ ddlmZ dd	lmZmZmZ  G d
 de      Z G d de      Zy)zFError handling middleware for consistent error responses and tracking.    N)Callable)Any)McpError)	ErrorData)NotFoundError   )CallNext
MiddlewareMiddlewareContextc            	           e Zd ZdZ	 	 	 	 ddej
                  dz  dedeee	gdf   dz  defdZ
ded	e	d
dfdZded
efdZd	e	ded
efdZd
eeef   fdZy)ErrorHandlingMiddlewarea*  Middleware that provides consistent error handling and logging.

    Catches exceptions, logs them appropriately, and converts them to
    proper MCP error responses. Also tracks error patterns for monitoring.

    Example:
        ```python
        from fastmcp.server.middleware.error_handling import ErrorHandlingMiddleware
        import logging

        # Configure logging to see error details
        logging.basicConfig(level=logging.ERROR)

        mcp = FastMCP("MyServer")
        mcp.add_middleware(ErrorHandlingMiddleware())
        ```
    Nloggerinclude_tracebackerror_callbacktransform_errorsc                 x    |xs t        j                  d      | _        || _        || _        || _        i | _        y)a}  Initialize error handling middleware.

        Args:
            logger: Logger instance for error logging. If None, uses 'fastmcp.errors'
            include_traceback: Whether to include full traceback in error logs
            error_callback: Optional callback function called for each error
            transform_errors: Whether to transform non-MCP errors to McpError
        zfastmcp.errorsN)logging	getLoggerr   r   r   r   error_counts)selfr   r   r   r   s        t/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/fastmcp/server/middleware/error_handling.py__init__z ErrorHandlingMiddleware.__init__%   s<     C 1 12B C!2, 0    errorcontextreturnc                 &   t        |      j                  }|j                  xs d}| d| }| j                  j	                  |d      dz   | j                  |<   d| d| d|}| j
                  r3| j                  j                  | dt        j                                 n| j                  j                  |       | j                  r	 | j                  ||       y	y	# t        $ r(}| j                  j                  d|        Y d	}~y	d	}~ww xY w)
z(Log error with appropriate detail level.unknown:r   r   z	Error in : 
zError in error callback: N)type__name__methodr   getr   r   r   	traceback
format_excr   	Exception)r   r   r   
error_typer$   	error_keybase_messagecallback_errors           r   
_log_errorz"ErrorHandlingMiddleware._log_error:   s   %[))
,9 "l!F8,	'+'8'8'<'<Y'JQ'N)$"6("ZL5)D!!KKb1E1E1G0HIJKKl+ P##E73   P!!$=n=M"NOOPs   C 	D(DDc                    t        |t              r|S | j                  s|S |j                  rt	        |j                        n
t	        |      }|t
        t        fv rt        t        dd|            S |t        t        t        fv rt        t        dd|            S |t        u rt        t        dd|            S |t        t        j                  fv rt        t        dd|            S t        t        d	d
|            S )z.Transform non-MCP errors to proper MCP errors.izInvalid params: )codemessageizResource not found: i zPermission denied: zRequest timeout: izInternal error: )
isinstancer   r   	__cause__r"   
ValueError	TypeErrorr   FileNotFoundErrorKeyErrorr   PermissionErrorTimeoutErrorasyncio)r   r   r)   s      r   _transform_errorz(ErrorHandlingMiddleware._transform_errorQ   s   eX&L$$L /4ooT%//*4;
*i00v1A%/KL  -xGGv1EeY/OP  ?*v1DUI/NO  L'*>*>??v1B5)/LM  v1A%/KL r   	call_nextc                    K   	  ||       d{   S 7 # t         $ r+}| j                  ||       | j                  |      }||d}~ww xY ww)zHandle errors for all messages.N)r(   r-   r:   )r   r   r;   r   transformed_errors        r   
on_messagez"ErrorHandlingMiddleware.on_messager   sT     	/"7++++ 	/OOE7+ !% 5 5e <#.	/s0   A  A 	A
&AA

Ac                 6    | j                   j                         S )z$Get error statistics for monitoring.)r   copy)r   s    r   get_error_statsz'ErrorHandlingMiddleware.get_error_stats}   s      %%''r   )NFNT)r#   
__module____qualname____doc__r   Loggerboolr   r(   r   r   r-   r:   r	   r   r>   dictstrintrA    r   r   r   r      s    ( )-"'PT!%%   !)->!?!EFM	
 *P	 P4E P$ P.i I B	/(9 	/h 	/SV 	/(c3h (r   r   c                       e Zd ZdZddddeefdfdeded	ed
edee	e
   df   dej                  dz  fdZde
defdZdedefdZdededefdZy)RetryMiddlewareai  Middleware that implements automatic retry logic for failed requests.

    Retries requests that fail with transient errors, using exponential
    backoff to avoid overwhelming the server or external dependencies.

    Example:
        ```python
        from fastmcp.server.middleware.error_handling import RetryMiddleware

        # Retry up to 3 times with exponential backoff
        retry_middleware = RetryMiddleware(
            max_retries=3,
            retry_exceptions=(ConnectionError, TimeoutError)
        )

        mcp = FastMCP("MyServer")
        mcp.add_middleware(retry_middleware)
        ```
       g      ?g      N@g       @Nmax_retries
base_delay	max_delaybackoff_multiplierretry_exceptions.r   c                     || _         || _        || _        || _        || _        |xs t        j                  d      | _        y)a  Initialize retry middleware.

        Args:
            max_retries: Maximum number of retry attempts
            base_delay: Initial delay between retries in seconds
            max_delay: Maximum delay between retries in seconds
            backoff_multiplier: Multiplier for exponential backoff
            retry_exceptions: Tuple of exception types that should trigger retries
            logger: Logger for retry attempts
        zfastmcp.retryN)rN   rO   rP   rQ   rR   r   r   r   )r   rN   rO   rP   rQ   rR   r   s          r   r   zRetryMiddleware.__init__   sA    & '$""4 0B 1 1/ Br   r   r   c                 .    t        || j                        S )z-Determine if an error should trigger a retry.)r1   rR   )r   r   s     r   _should_retryzRetryMiddleware._should_retry   s    %!6!677r   attemptc                 f    | j                   | j                  |z  z  }t        || j                        S )z-Calculate delay for the given attempt number.)rO   rQ   minrP   )r   rV   delays      r   _calculate_delayz RetryMiddleware._calculate_delay   s,    4#:#:G#CD5$..))r   r   r;   c                   K   d}t        | j                  dz         D ]  }	  ||       d{   c S  |r|y7 # t        $ r}|}|| j                  k(  s| j                  |      sY d}~ 8| j	                  |      }| j
                  j                  d|j                   d|dz    d| j                  dz    dt        |      j                   d|d|d	d
       t        j                  |       d{  7   Y d}~d}~ww xY ww)z#Implement retry logic for requests.Nr   zRequest z failed (attempt /z): r    z. Retrying in z.1fzs...)rangerN   r(   rU   rZ   r   warningr$   r"   r#   anyiosleep)r   r   r;   
last_errorrV   r   rY   s          r   
on_requestzRetryMiddleware.on_request   s    
T--12 	)G)&w///	)&  # 0 )"
 d...d6H6H6O--g6##w~~..?!}AdN^N^abNbMccfE{++,Bui~eC[PTV
 kk%((()sP   D;9;	D;	D"C<&D,BC<1C42C<7D<DD)r#   rB   rC   rD   ConnectionErrorr8   rI   floattupler"   r(   r   rE   r   rF   rU   rZ   r   r	   r   rb   rJ   r   r   rL   rL      s    , $'9H,8W(,CC C 	C
 "C  Y 45C %C489 8 8* * *
(9 h SV r   rL   )rD   r9   r   r&   collections.abcr   typingr   r_   mcpr   	mcp.typesr   fastmcp.exceptionsr   
middlewarer	   r
   r   r   rL   rJ   r   r   <module>rl      sF    L    $     , ? ?m(j m(`Pj Pr   