Skip to content

Commit 07d2199

Browse files
committed
PYTHON-952 - Fix duration measurements.
We weren't including the time to decode responses in a number of places. This commit also fixes an issue with handling "cursor not found" errors from mongos versions older than 2.4.
1 parent fa4a6a3 commit 07d2199

File tree

5 files changed

+34
-25
lines changed

5 files changed

+34
-25
lines changed

pymongo/command_cursor.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414

1515
"""CommandCursor class to iterate over command results."""
1616

17+
import datetime
18+
1719
from collections import deque
1820

1921
from bson.py3compat import integer_types
2022
from pymongo import helpers, monitoring
21-
from pymongo.errors import AutoReconnect, CursorNotFound, NotMasterError
23+
from pymongo.errors import AutoReconnect, NotMasterError, OperationFailure
2224
from pymongo.message import _GetMore
2325

2426

@@ -101,16 +103,19 @@ def __send_message(self, operation):
101103
raise
102104

103105
publish = monitoring.enabled()
104-
duration = response.duration
106+
cmd_duration = response.duration
105107
rqst_id = response.request_id
108+
if publish:
109+
start = datetime.datetime.now()
106110
try:
107111
doc = helpers._unpack_response(response.data,
108112
self.__id,
109113
self.__collection.codec_options)
110-
except CursorNotFound as exc:
114+
except OperationFailure as exc:
111115
self.__killed = True
112116

113117
if publish:
118+
duration = (datetime.datetime.now() - start) + cmd_duration
114119
monitoring.publish_command_failure(
115120
duration, exc.details, "getMore", rqst_id, self.__address)
116121

@@ -121,13 +126,15 @@ def __send_message(self, operation):
121126
self.__killed = True
122127

123128
if publish:
129+
duration = (datetime.datetime.now() - start) + cmd_duration
124130
monitoring.publish_command_failure(
125131
duration, exc.details, "getMore", rqst_id, self.__address)
126132

127133
client._reset_server_and_request_check(self.address)
128134
raise
129135

130136
if publish:
137+
duration = (datetime.datetime.now() - start) + cmd_duration
131138
# Must publish in getMore command response format.
132139
res = {"cursor": {"id": doc["cursor_id"],
133140
"ns": self.__collection.full_name,

pymongo/cursor.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ def __send_message(self, operation):
822822
response.pool)
823823

824824
data = response.data
825-
duration = response.duration
825+
cmd_duration = response.duration
826826
rqst_id = response.request_id
827827
except AutoReconnect:
828828
# Don't try to send kill cursors on another socket
@@ -833,7 +833,6 @@ def __send_message(self, operation):
833833
raise
834834
else:
835835
# Exhaust cursor - no getMore message.
836-
duration = None
837836
rqst_id = 0
838837
cmd_name = 'getMore'
839838
if publish:
@@ -853,8 +852,10 @@ def __send_message(self, operation):
853852
self.__die()
854853
raise
855854
if publish:
856-
duration = datetime.datetime.now() - start
855+
cmd_duration = datetime.datetime.now() - start
857856

857+
if publish:
858+
start = datetime.datetime.now()
858859
try:
859860
doc = helpers._unpack_response(response=data,
860861
cursor_id=self.__id,
@@ -866,6 +867,7 @@ def __send_message(self, operation):
866867
self.__die()
867868

868869
if publish:
870+
duration = (datetime.datetime.now() - start) + cmd_duration
869871
monitoring.publish_command_failure(
870872
duration, exc.details, cmd_name, rqst_id, self.__address)
871873

@@ -885,13 +887,15 @@ def __send_message(self, operation):
885887
self.__die()
886888

887889
if publish:
890+
duration = (datetime.datetime.now() - start) + cmd_duration
888891
monitoring.publish_command_failure(
889892
duration, exc.details, cmd_name, rqst_id, self.__address)
890893

891894
client._reset_server_and_request_check(self.__address)
892895
raise
893896

894897
if publish:
898+
duration = (datetime.datetime.now() - start) + cmd_duration
895899
# Must publish in find / getMore command response format.
896900
res = {"cursor": {"id": doc["cursor_id"],
897901
"ns": self.__collection.full_name},

pymongo/helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ def _unpack_response(response, cursor_id=None, codec_options=CodecOptions()):
112112
raise CursorNotFound(msg, 43, errobj)
113113
elif response_flag & 2:
114114
error_object = bson.BSON(response[20:]).decode()
115+
# Fake the ok field if it doesn't exist.
116+
error_object.setdefault("ok", 0)
115117
if error_object["$err"].startswith("not master"):
116118
raise NotMasterError(error_object["$err"], error_object)
117119
elif error_object.get("code") == 50:

pymongo/network.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,23 @@ def command(sock, dbname, spec, slave_ok, is_mongos,
7373

7474
sock.sendall(msg)
7575
response = receive_message(sock, 1, request_id)
76-
unpacked = helpers._unpack_response(response, codec_options=codec_options)
77-
78-
if publish:
79-
duration = (datetime.datetime.now() - start) + encoding_duration
76+
try:
77+
unpacked = helpers._unpack_response(
78+
response, codec_options=codec_options)
8079

81-
response_doc = unpacked['data'][0]
82-
msg = "command %s on namespace %s failed: %%s" % (
83-
repr(spec).replace("%", "%%"), ns)
84-
if check:
85-
try:
80+
response_doc = unpacked['data'][0]
81+
if check:
82+
msg = "command %s on namespace %s failed: %%s" % (
83+
repr(spec).replace("%", "%%"), ns)
8684
helpers._check_command_response(response_doc, msg, allowable_errors)
87-
except (NotMasterError, OperationFailure) as exc:
88-
if publish:
89-
monitoring.publish_command_failure(
90-
duration, exc.details, name, request_id, address)
91-
raise
85+
except (NotMasterError, OperationFailure) as exc:
86+
if publish:
87+
duration = (datetime.datetime.now() - start) + encoding_duration
88+
monitoring.publish_command_failure(
89+
duration, exc.details, name, request_id, address)
90+
raise
9291
if publish:
92+
duration = (datetime.datetime.now() - start) + encoding_duration
9393
monitoring.publish_command_success(
9494
duration, response_doc, name, request_id, address)
9595
return response_doc

test/test_monitoring.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -293,11 +293,7 @@ def test_get_more_failure(self):
293293
self.assertEqual('getMore', failed.command_name)
294294
self.assertTrue(isinstance(failed.request_id, int))
295295
self.assertEqual(cursor.address, failed.connection_id)
296-
expected_result = {
297-
'errmsg': "Cursor not found, cursor id: 12345",
298-
'code': 43,
299-
'ok': 0}
300-
self.assertEqual(expected_result, failed.failure)
296+
self.assertEqual(0, failed.failure.get("ok"))
301297

302298
@client_context.require_replica_set
303299
def test_not_master_error(self):

0 commit comments

Comments
 (0)