Skip to content

Commit 75f4e21

Browse files
committed
fixed merge conflict
1 parent bb7a81f commit 75f4e21

14 files changed

Lines changed: 364 additions & 7 deletions

File tree

pymongo/_telemetry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def _emit_log(self, message: _CommandStatusMessage, **extra: Any) -> None:
8686
commandName=self._name,
8787
databaseName=self._dbname,
8888
requestId=self._request_id,
89-
operationId=self._request_id,
89+
operationId=self._op_id if self._op_id is not None else self._request_id,
9090
driverConnectionId=self._conn.id,
9191
serverConnectionId=self._conn.server_connection_id,
9292
serverHost=self._conn.address[0],

pymongo/asynchronous/command_runner.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ async def run_cursor_command(
284284
more_to_come: bool = False,
285285
unpack_res: Optional[Callable[..., Any]] = None,
286286
cursor_id: Optional[int] = None,
287+
op_id: Optional[int] = None,
287288
) -> tuple[list[dict[str, Any]], Optional[_OpMsg], datetime.timedelta]:
288289
"""Run a cursor ``find``/``getMore`` operation over ``conn``.
289290
@@ -304,6 +305,7 @@ async def run_cursor_command(
304305
:param unpack_res: A callable decoding the wire response; when ``None`` the
305306
reply's own ``unpack_response`` is used.
306307
:param cursor_id: The cursor id passed to ``unpack_res``.
308+
:param op_id: The APM operation id; defaults to ``request_id``.
307309
"""
308310
topology_id = client._topology_id if client is not None else None
309311
return await _run_command(
@@ -325,6 +327,7 @@ async def run_cursor_command(
325327
more_to_come=more_to_come,
326328
unpack_res=unpack_res,
327329
cursor_id=cursor_id,
330+
op_id=op_id,
328331
)
329332

330333

@@ -348,6 +351,7 @@ async def run_command(
348351
user_fields: Optional[Mapping[str, Any]] = None,
349352
exhaust_allowed: bool = False,
350353
write_concern: Optional[WriteConcern] = None,
354+
op_id: Optional[int] = None,
351355
) -> _DocumentType:
352356
"""Encode and execute a command over ``conn``, or raise socket.error.
353357
@@ -376,6 +380,7 @@ async def run_command(
376380
passed to ``bson._decode_all_selective``.
377381
:param exhaust_allowed: True if we should enable OP_MSG exhaustAllowed.
378382
:param write_concern: The write concern for this command. Applied via CSOT.
383+
:param op_id: The APM operation id; defaults to ``request_id``.
379384
"""
380385
name = next(iter(spec))
381386

@@ -428,6 +433,7 @@ async def run_command(
428433
codec_options=codec_options,
429434
user_fields=user_fields,
430435
orig=orig,
436+
op_id=op_id,
431437
check=check,
432438
allowable_errors=allowable_errors,
433439
parse_write_concern_error=parse_write_concern_error,

pymongo/asynchronous/mongo_client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
_log_client_error,
9696
_log_or_warn,
9797
)
98-
from pymongo.message import _CursorAddress, _GetMore, _Query
98+
from pymongo.message import _CursorAddress, _GetMore, _Query, _randint
9999
from pymongo.monitoring import ConnectionClosedReason, _EventListeners
100100
from pymongo.operations import (
101101
DeleteMany,
@@ -1837,6 +1837,8 @@ async def _select_server(
18371837
be pinned to a mongos server address.
18381838
- `address` (optional): Address when sending a message
18391839
to a specific server, used for getMore.
1840+
- `operation_id` (optional): Stable operation id shared across retries,
1841+
used for command monitoring.
18401842
"""
18411843
try:
18421844
topology = await self._get_topology()
@@ -1932,6 +1934,7 @@ async def _run_operation(
19321934
async with operation.conn_mgr._lock:
19331935
async with _MongoClientErrorHandler(self, server, operation.session) as err_handler: # type: ignore[arg-type]
19341936
err_handler.contribute_socket(operation.conn_mgr.conn)
1937+
operation.conn_mgr.conn.op_id = _randint()
19351938
return await server.run_operation(
19361939
operation.conn_mgr.conn,
19371940
operation,
@@ -2023,6 +2026,7 @@ async def _retry_internal(
20232026
:param retryable: If the operation should be retried once, defaults to None
20242027
:param is_run_command: If this is a runCommand operation, defaults to False
20252028
:param is_aggregate_write: If this is a aggregate operation with a write, defaults to False.
2029+
:param operation_id: Stable operation id shared across retries, defaults to None
20262030
20272031
:return: Output of the calling func()
20282032
"""
@@ -2069,6 +2073,7 @@ async def _retryable_read(
20692073
(may not always be supported even if supplied), defaults to False
20702074
:param is_run_command: If this is a runCommand operation, defaults to False.
20712075
:param is_aggregate_write: If this is a aggregate operation with a write, defaults to False.
2076+
:param operation_id: Stable operation id shared across retries, defaults to None
20722077
"""
20732078

20742079
# Ensure that the client supports retrying on reads and there is no session in
@@ -2112,6 +2117,7 @@ async def _retryable_write(
21122117
:param session: Client session we will use to execute write operation
21132118
:param operation: The name of the operation that the server is being selected for
21142119
:param bulk: bulk abstraction to execute operations in bulk, defaults to None
2120+
:param operation_id: Stable operation id shared across retries, defaults to None
21152121
"""
21162122
async with self._tmp_session(session) as s:
21172123
return await self._retry_with_session(retryable, func, s, bulk, operation, operation_id)
@@ -2795,7 +2801,7 @@ def __init__(
27952801
self._server: Server = None # type: ignore
27962802
self._deprioritized_servers: list[Server] = []
27972803
self._operation = operation
2798-
self._operation_id = operation_id
2804+
self._operation_id = operation_id if operation_id is not None else _randint()
27992805
self._attempt_number = 0
28002806
self._is_run_command = is_run_command
28012807
self._is_aggregate_write = is_aggregate_write
@@ -3001,6 +3007,7 @@ async def _write(self) -> T:
30013007
is_mongos = False
30023008
self._server = await self._get_server()
30033009
async with self._client._checkout(self._server, self._session) as conn:
3010+
conn.op_id = self._operation_id
30043011
max_wire_version = conn.max_wire_version
30053012
sessions_supported = (
30063013
self._session
@@ -3040,6 +3047,7 @@ async def _read(self) -> T:
30403047
conn,
30413048
read_pref,
30423049
):
3050+
conn.op_id = self._operation_id
30433051
if self._retrying and not self._retryable and not self._always_retryable:
30443052
self._check_last_error()
30453053
if self._retrying:

pymongo/asynchronous/pool.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ def __init__(
177177
self.creation_time = time.monotonic()
178178
# For gossiping $clusterTime from the connection handshake to the client.
179179
self._cluster_time = None
180+
# Stable operation id for the operation currently using this connection.
181+
self.op_id: Optional[int] = None
180182

181183
def set_conn_timeout(self, timeout: Optional[float]) -> None:
182184
"""Cache last timeout to avoid duplicate calls to conn.settimeout."""
@@ -416,6 +418,7 @@ async def command(
416418
user_fields=user_fields,
417419
exhaust_allowed=exhaust_allowed,
418420
write_concern=write_concern,
421+
op_id=self.op_id,
419422
)
420423
except (OperationFailure, NotPrimaryError):
421424
raise
@@ -1319,6 +1322,7 @@ async def checkin(self, conn: AsyncConnection) -> None:
13191322
txn = conn.pinned_txn
13201323
cursor = conn.pinned_cursor
13211324
conn.active = False
1325+
conn.op_id = None
13221326
conn.pinned_txn = False
13231327
conn.pinned_cursor = False
13241328
self.__pinned_sockets.discard(conn)

pymongo/asynchronous/server.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ async def run_operation(
185185
more_to_come=more_to_come,
186186
unpack_res=unpack_res,
187187
cursor_id=operation.cursor_id,
188+
op_id=conn.op_id,
188189
)
189190
assert reply is not None
190191

pymongo/synchronous/command_runner.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def run_cursor_command(
284284
more_to_come: bool = False,
285285
unpack_res: Optional[Callable[..., Any]] = None,
286286
cursor_id: Optional[int] = None,
287+
op_id: Optional[int] = None,
287288
) -> tuple[list[dict[str, Any]], Optional[_OpMsg], datetime.timedelta]:
288289
"""Run a cursor ``find``/``getMore`` operation over ``conn``.
289290
@@ -304,6 +305,7 @@ def run_cursor_command(
304305
:param unpack_res: A callable decoding the wire response; when ``None`` the
305306
reply's own ``unpack_response`` is used.
306307
:param cursor_id: The cursor id passed to ``unpack_res``.
308+
:param op_id: The APM operation id; defaults to ``request_id``.
307309
"""
308310
topology_id = client._topology_id if client is not None else None
309311
return _run_command(
@@ -325,6 +327,7 @@ def run_cursor_command(
325327
more_to_come=more_to_come,
326328
unpack_res=unpack_res,
327329
cursor_id=cursor_id,
330+
op_id=op_id,
328331
)
329332

330333

@@ -348,6 +351,7 @@ def run_command(
348351
user_fields: Optional[Mapping[str, Any]] = None,
349352
exhaust_allowed: bool = False,
350353
write_concern: Optional[WriteConcern] = None,
354+
op_id: Optional[int] = None,
351355
) -> _DocumentType:
352356
"""Encode and execute a command over ``conn``, or raise socket.error.
353357
@@ -376,6 +380,7 @@ def run_command(
376380
passed to ``bson._decode_all_selective``.
377381
:param exhaust_allowed: True if we should enable OP_MSG exhaustAllowed.
378382
:param write_concern: The write concern for this command. Applied via CSOT.
383+
:param op_id: The APM operation id; defaults to ``request_id``.
379384
"""
380385
name = next(iter(spec))
381386

@@ -428,6 +433,7 @@ def run_command(
428433
codec_options=codec_options,
429434
user_fields=user_fields,
430435
orig=orig,
436+
op_id=op_id,
431437
check=check,
432438
allowable_errors=allowable_errors,
433439
parse_write_concern_error=parse_write_concern_error,

pymongo/synchronous/mongo_client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
_log_client_error,
8686
_log_or_warn,
8787
)
88-
from pymongo.message import _CursorAddress, _GetMore, _Query
88+
from pymongo.message import _CursorAddress, _GetMore, _Query, _randint
8989
from pymongo.monitoring import ConnectionClosedReason, _EventListeners
9090
from pymongo.operations import (
9191
DeleteMany,
@@ -1834,6 +1834,8 @@ def _select_server(
18341834
be pinned to a mongos server address.
18351835
- `address` (optional): Address when sending a message
18361836
to a specific server, used for getMore.
1837+
- `operation_id` (optional): Stable operation id shared across retries,
1838+
used for command monitoring.
18371839
"""
18381840
try:
18391841
topology = self._get_topology()
@@ -1929,6 +1931,7 @@ def _run_operation(
19291931
with operation.conn_mgr._lock:
19301932
with _MongoClientErrorHandler(self, server, operation.session) as err_handler: # type: ignore[arg-type]
19311933
err_handler.contribute_socket(operation.conn_mgr.conn)
1934+
operation.conn_mgr.conn.op_id = _randint()
19321935
return server.run_operation(
19331936
operation.conn_mgr.conn,
19341937
operation,
@@ -2020,6 +2023,7 @@ def _retry_internal(
20202023
:param retryable: If the operation should be retried once, defaults to None
20212024
:param is_run_command: If this is a runCommand operation, defaults to False
20222025
:param is_aggregate_write: If this is a aggregate operation with a write, defaults to False.
2026+
:param operation_id: Stable operation id shared across retries, defaults to None
20232027
20242028
:return: Output of the calling func()
20252029
"""
@@ -2066,6 +2070,7 @@ def _retryable_read(
20662070
(may not always be supported even if supplied), defaults to False
20672071
:param is_run_command: If this is a runCommand operation, defaults to False.
20682072
:param is_aggregate_write: If this is a aggregate operation with a write, defaults to False.
2073+
:param operation_id: Stable operation id shared across retries, defaults to None
20692074
"""
20702075

20712076
# Ensure that the client supports retrying on reads and there is no session in
@@ -2109,6 +2114,7 @@ def _retryable_write(
21092114
:param session: Client session we will use to execute write operation
21102115
:param operation: The name of the operation that the server is being selected for
21112116
:param bulk: bulk abstraction to execute operations in bulk, defaults to None
2117+
:param operation_id: Stable operation id shared across retries, defaults to None
21122118
"""
21132119
with self._tmp_session(session) as s:
21142120
return self._retry_with_session(retryable, func, s, bulk, operation, operation_id)
@@ -2786,7 +2792,7 @@ def __init__(
27862792
self._server: Server = None # type: ignore
27872793
self._deprioritized_servers: list[Server] = []
27882794
self._operation = operation
2789-
self._operation_id = operation_id
2795+
self._operation_id = operation_id if operation_id is not None else _randint()
27902796
self._attempt_number = 0
27912797
self._is_run_command = is_run_command
27922798
self._is_aggregate_write = is_aggregate_write
@@ -2992,6 +2998,7 @@ def _write(self) -> T:
29922998
is_mongos = False
29932999
self._server = self._get_server()
29943000
with self._client._checkout(self._server, self._session) as conn:
3001+
conn.op_id = self._operation_id
29953002
max_wire_version = conn.max_wire_version
29963003
sessions_supported = (
29973004
self._session
@@ -3031,6 +3038,7 @@ def _read(self) -> T:
30313038
conn,
30323039
read_pref,
30333040
):
3041+
conn.op_id = self._operation_id
30343042
if self._retrying and not self._retryable and not self._always_retryable:
30353043
self._check_last_error()
30363044
if self._retrying:

pymongo/synchronous/pool.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ def __init__(
177177
self.creation_time = time.monotonic()
178178
# For gossiping $clusterTime from the connection handshake to the client.
179179
self._cluster_time = None
180+
# Stable operation id for the operation currently using this connection.
181+
self.op_id: Optional[int] = None
180182

181183
def set_conn_timeout(self, timeout: Optional[float]) -> None:
182184
"""Cache last timeout to avoid duplicate calls to conn.settimeout."""
@@ -416,6 +418,7 @@ def command(
416418
user_fields=user_fields,
417419
exhaust_allowed=exhaust_allowed,
418420
write_concern=write_concern,
421+
op_id=self.op_id,
419422
)
420423
except (OperationFailure, NotPrimaryError):
421424
raise
@@ -1315,6 +1318,7 @@ def checkin(self, conn: Connection) -> None:
13151318
txn = conn.pinned_txn
13161319
cursor = conn.pinned_cursor
13171320
conn.active = False
1321+
conn.op_id = None
13181322
conn.pinned_txn = False
13191323
conn.pinned_cursor = False
13201324
self.__pinned_sockets.discard(conn)

pymongo/synchronous/server.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ def run_operation(
185185
more_to_come=more_to_come,
186186
unpack_res=unpack_res,
187187
cursor_id=operation.cursor_id,
188+
op_id=conn.op_id,
188189
)
189190
assert reply is not None
190191

test/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ def require_failCommand_fail_point(self, func: Any) -> Any:
699699
func=func,
700700
)
701701

702-
def require_failCommand_appName(self, func):
702+
def require_failCommand_appName(self, func: Any) -> Any:
703703
"""Run a test only if the server supports the failCommand appName."""
704704
# SERVER-47195 and SERVER-49336.
705705
return self._require(

0 commit comments

Comments
 (0)