@@ -383,7 +383,10 @@ def _truncate_metadata(metadata: MutableMapping[str, Any]) -> None:
383383
384384
385385def _raise_connection_failure (
386- address : Any , error : Exception , msg_prefix : Optional [str ] = None
386+ address : Any ,
387+ error : Exception ,
388+ msg_prefix : Optional [str ] = None ,
389+ timeout_details : Optional [dict [str , float ]] = None ,
387390) -> NoReturn :
388391 """Convert a socket.error to ConnectionFailure and raise it."""
389392 host , port = address
@@ -394,6 +397,8 @@ def _raise_connection_failure(
394397 msg = f"{ host } : { error } "
395398 if msg_prefix :
396399 msg = msg_prefix + msg
400+ if "configured timeouts" not in msg :
401+ msg += format_timeout_details (timeout_details )
397402 if isinstance (error , socket .timeout ):
398403 raise NetworkTimeout (msg ) from error
399404 elif isinstance (error , SSLError ) and "timed out" in str (error ):
@@ -411,6 +416,32 @@ def _cond_wait(condition: threading.Condition, deadline: Optional[float]) -> boo
411416 return condition .wait (timeout )
412417
413418
419+ def _get_timeout_details (options : PoolOptions ) -> dict [str , float ]:
420+ details = {}
421+ timeout = _csot .get_timeout ()
422+ socket_timeout = options .socket_timeout
423+ connect_timeout = options .connect_timeout
424+ if timeout :
425+ details ["timeoutMS" ] = timeout * 1000
426+ if socket_timeout and not timeout :
427+ details ["socketTimeoutMS" ] = socket_timeout * 1000
428+ if connect_timeout :
429+ details ["connectTimeoutMS" ] = connect_timeout * 1000
430+ return details
431+
432+
433+ def format_timeout_details (details : Optional [dict [str , float ]]) -> str :
434+ result = ""
435+ if details :
436+ result += " (configured timeouts:"
437+ for timeout in ["socketTimeoutMS" , "timeoutMS" , "connectTimeoutMS" ]:
438+ if timeout in details :
439+ result += f" { timeout } : { details [timeout ]} ms,"
440+ result = result [:- 1 ]
441+ result += ")"
442+ return result
443+
444+
414445class PoolOptions :
415446 """Read only connection pool options for a MongoClient.
416447
@@ -740,10 +771,15 @@ def apply_timeout(
740771 rtt = self .connect_rtt
741772 max_time_ms = timeout - rtt
742773 if max_time_ms < 0 :
774+ timeout_details = _get_timeout_details (self .opts )
775+ formatted = format_timeout_details (timeout_details )
743776 # CSOT: raise an error without running the command since we know it will time out.
744- errmsg = f"operation would exceed time limit, remaining timeout:{ timeout :.5f} <= network round trip time:{ rtt :.5f} "
777+ errmsg = f"operation would exceed time limit, remaining timeout:{ timeout :.5f} <= network round trip time:{ rtt :.5f} { formatted } "
745778 raise ExecutionTimeout (
746- errmsg , 50 , {"ok" : 0 , "errmsg" : errmsg , "code" : 50 }, self .max_wire_version
779+ errmsg ,
780+ 50 ,
781+ {"ok" : 0 , "errmsg" : errmsg , "code" : 50 },
782+ self .max_wire_version ,
747783 )
748784 if cmd is not None :
749785 cmd ["maxTimeMS" ] = int (max_time_ms * 1000 )
@@ -1131,7 +1167,8 @@ def _raise_connection_failure(self, error: BaseException) -> NoReturn:
11311167 self .close_conn (reason )
11321168 # SSLError from PyOpenSSL inherits directly from Exception.
11331169 if isinstance (error , (IOError , OSError , SSLError )):
1134- _raise_connection_failure (self .address , error )
1170+ details = _get_timeout_details (self .opts )
1171+ _raise_connection_failure (self .address , error , timeout_details = details )
11351172 else :
11361173 raise
11371174
@@ -1255,7 +1292,8 @@ def _configured_socket(address: _Address, options: PoolOptions) -> Union[socket.
12551292 # We raise AutoReconnect for transient and permanent SSL handshake
12561293 # failures alike. Permanent handshake failures, like protocol
12571294 # mismatch, will be turned into ServerSelectionTimeoutErrors later.
1258- _raise_connection_failure (address , exc , "SSL handshake failed: " )
1295+ details = _get_timeout_details (options )
1296+ _raise_connection_failure (address , exc , "SSL handshake failed: " , timeout_details = details )
12591297 if (
12601298 ssl_context .verify_mode
12611299 and not ssl_context .check_hostname
@@ -1553,7 +1591,8 @@ def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> Connect
15531591 )
15541592
15551593 if isinstance (error , (IOError , OSError , SSLError )):
1556- _raise_connection_failure (self .address , error )
1594+ details = _get_timeout_details (self .opts )
1595+ _raise_connection_failure (self .address , error , timeout_details = details )
15571596
15581597 raise
15591598
@@ -1634,7 +1673,10 @@ def _raise_if_not_ready(self, emit_event: bool) -> None:
16341673 self .opts ._event_listeners .publish_connection_check_out_failed (
16351674 self .address , ConnectionCheckOutFailedReason .CONN_ERROR
16361675 )
1637- _raise_connection_failure (self .address , AutoReconnect ("connection pool paused" ))
1676+ details = _get_timeout_details (self .opts )
1677+ _raise_connection_failure (
1678+ self .address , AutoReconnect ("connection pool paused" ), timeout_details = details
1679+ )
16381680
16391681 def _get_conn (self , handler : Optional [_MongoClientErrorHandler ] = None ) -> Connection :
16401682 """Get or create a Connection. Can raise ConnectionFailure."""
0 commit comments