Skip to content

Commit ba99033

Browse files
authored
[mongo] collect mongodb activity lsid and transaction (#19553)
* collect mongodb activity lsid and transaction * add changelog
1 parent ac2e30f commit ba99033

File tree

9 files changed

+109
-9
lines changed

9 files changed

+109
-9
lines changed

mongo/changelog.d/19553.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Collect `lsid` and `transaction` details from `$currentOp` for MongoDB activity sampling.

mongo/datadog_checks/mongo/dbm/operation_samples.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under a 3-clause BSD style license (see LICENSE)
44

55

6+
import binascii
67
import time
78
from typing import List, Optional
89

@@ -259,6 +260,28 @@ def _get_operation_cursor(self, operation: dict) -> Optional[OperationSampleOper
259260
"operation_using_cursor_id": cursor.get("operationUsingCursorId"),
260261
}
261262

263+
def _get_operation_lsid(self, operation: dict) -> Optional[dict]:
264+
lsid = operation.get("lsid")
265+
if not lsid or not lsid.get("id"):
266+
return None
267+
268+
return {
269+
"id": binascii.hexlify(lsid['id']).decode(),
270+
}
271+
272+
def _get_operation_transaction(self, operation: dict) -> Optional[dict]:
273+
transaction = operation.get("transaction")
274+
if not transaction:
275+
return None
276+
277+
return {
278+
"txn_number": transaction.get("parameters", {}).get("txnNumber"),
279+
"txn_retry_counter": transaction.get("parameters", {}).get("txnRetryCounter"),
280+
"time_open_micros": transaction.get("timeOpenMicros"),
281+
"time_active_micros": transaction.get("timeActiveMicros"),
282+
"time_inactive_micros": transaction.get("timeInactiveMicros"),
283+
}
284+
262285
def _get_operation_stats(self, operation: dict) -> OperationSampleOperationStats:
263286
return {
264287
"active": operation.get("active", False), # bool
@@ -269,7 +292,6 @@ def _get_operation_stats(self, operation: dict) -> OperationSampleOperationStats
269292
"query_framework": operation.get("queryFramework"), # str
270293
"current_op_time": operation.get("currentOpTime"), # str start time of the operation
271294
"microsecs_running": operation.get("microsecs_running"), # int
272-
"transaction_time_open_micros": operation.get("transaction", {}).get("timeOpenMicros"), # int
273295
# Conflicts
274296
"prepare_read_conflicts": operation.get("prepareReadConflicts", 0), # int
275297
"write_conflicts": operation.get("writeConflicts", 0), # int
@@ -291,6 +313,8 @@ def _get_operation_stats(self, operation: dict) -> OperationSampleOperationStats
291313
), # dict
292314
# cursor
293315
"cursor": self._get_operation_cursor(operation), # dict
316+
"transaction": self._get_operation_transaction(operation), # dict
317+
"lsid": self._get_operation_lsid(operation), # dict
294318
}
295319

296320
def _get_query_signature(self, obfuscated_command: str) -> str:

mongo/datadog_checks/mongo/dbm/slow_operations.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under a 3-clause BSD style license (see LICENSE)
44

55

6+
import binascii
67
import time
78
from datetime import datetime
89

@@ -353,6 +354,7 @@ def _create_slow_operation_explain_plan_payload(self, slow_operation: dict, expl
353354
"lock_stats": self._get_slow_operation_lock_stats(slow_operation),
354355
"flow_control_stats": self._get_slow_operation_flow_control_stats(slow_operation),
355356
"cursor": self._get_slow_operation_cursor(slow_operation),
357+
"lsid": self._get_slow_operation_lsid(slow_operation["command"]),
356358
}
357359
),
358360
}
@@ -378,6 +380,15 @@ def _get_slow_operation_cursor(self, slow_operation):
378380
}
379381
return None
380382

383+
def _get_slow_operation_lsid(self, command):
384+
lsid = command.get("lsid")
385+
if not lsid or not lsid.get("id"):
386+
return None
387+
388+
return {
389+
"id": binascii.hexlify(lsid['id']).decode(),
390+
}
391+
381392
def _get_slow_operation_lock_stats(self, slow_operation):
382393
lock_stats = slow_operation.get("locks")
383394
if lock_stats:

mongo/datadog_checks/mongo/dbm/types.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ class OperationSampleOperationStatsCursor(TypedDict, total=False):
125125
operation_using_cursor_id: Optional[str]
126126

127127

128+
class OperationSampleOperationStatsTransaction(TypedDict, total=False):
129+
txn_number: int
130+
txn_retry_counter: int
131+
time_open_micros: int
132+
time_active_micros: int
133+
time_inactive_micros: int
134+
135+
136+
class OperationSampleOperationStatsLsid(TypedDict, total=False):
137+
id: str
138+
139+
128140
class OperationSampleOperationStats(TypedDict, total=False):
129141
active: bool
130142
desc: Optional[str]
@@ -134,7 +146,6 @@ class OperationSampleOperationStats(TypedDict, total=False):
134146
query_framework: Optional[str]
135147
current_op_time: str
136148
microsecs_running: Optional[int]
137-
transaction_time_open_micros: Optional[int]
138149
prepare_read_conflicts: Optional[int]
139150
write_conflicts: Optional[int]
140151
num_yields: Optional[int]
@@ -145,6 +156,8 @@ class OperationSampleOperationStats(TypedDict, total=False):
145156
flow_control_stats: Optional[OperationSampleOperationStatsFlowControlStats]
146157
waiting_for_latch: Optional[OperationSampleOperationStatsWaitingForLatch]
147158
cursor = Optional[OperationSampleOperationStatsCursor]
159+
transaction = Optional[OperationSampleOperationStatsTransaction]
160+
lsid = Optional[OperationSampleOperationStatsLsid]
148161

149162

150163
class OperationSampleActivityBase(TypedDict, total=False):

mongo/tests/fixtures/$currentOp-mongos

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,28 @@
5454
}
5555
}
5656
},
57+
"transaction": {
58+
"parameters": {
59+
"txnNumber": 392,
60+
"txnRetryCounter": 0,
61+
"autocommit": false,
62+
"readConcern": {
63+
"level": "local",
64+
"provenance": "implicitDefault"
65+
}
66+
},
67+
"readTimestamp": {
68+
"$timestamp": {
69+
"t": 0,
70+
"i": 0
71+
}
72+
},
73+
"startWallClockTime": "2025-02-04T18:45:22.915+00:00",
74+
"timeOpenMicros": 1750,
75+
"timeActiveMicros": 435,
76+
"timeInactiveMicros": 1315,
77+
"expiryTime": "2025-02-04T18:46:22.915+00:00"
78+
},
5779
"secs_running": 0,
5880
"microsecs_running": 29232,
5981
"op": "query",

mongo/tests/results/operation-activities-mongos.json

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
"query_framework": null,
2828
"current_op_time": "2024-05-20T14:36:56.231+00:00",
2929
"microsecs_running": 29232,
30-
"transaction_time_open_micros": null,
3130
"prepare_read_conflicts": 0,
3231
"write_conflicts": 0,
3332
"num_yields": 0,
3433
"waiting_for_lock": false,
34+
"lsid": {
35+
"id": "ff95bad791504c36ab749ae8c640d54e"
36+
},
3537
"locks": {
3638
"feature_compatibility_version": "r",
3739
"global": "r"
@@ -63,6 +65,13 @@
6365
"type": "op",
6466
"op": "query",
6567
"shard": "shard04",
68+
"transaction": {
69+
"time_active_micros": 435,
70+
"time_inactive_micros": 1315,
71+
"time_open_micros": 1750,
72+
"txn_number": 392,
73+
"txn_retry_counter": 0
74+
},
6675
"dbname": "integration",
6776
"application": null,
6877
"collection": "users",
@@ -96,11 +105,13 @@
96105
"query_framework": "classic",
97106
"current_op_time": "2024-06-13T20:50:10.834+00:00",
98107
"microsecs_running": 26789,
99-
"transaction_time_open_micros": null,
100108
"prepare_read_conflicts": 0,
101109
"write_conflicts": 0,
102110
"num_yields": 1,
103111
"waiting_for_lock": false,
112+
"lsid": {
113+
"id": "ccb77e0cda6441daa458dd4067cdbc48"
114+
},
104115
"locks": {
105116
"feature_compatibility_version": "r",
106117
"global": "r"
@@ -142,6 +153,7 @@
142153
"type": "op",
143154
"op": "getmore",
144155
"shard": null,
156+
"transaction": null,
145157
"dbname": "integration",
146158
"application": "orders-mongo",
147159
"collection": "movies",
@@ -173,11 +185,11 @@
173185
"query_framework": "classic",
174186
"current_op_time": "2024-08-06T20:59:35.394+00:00",
175187
"microsecs_running": 13134,
176-
"transaction_time_open_micros": null,
177188
"prepare_read_conflicts": 0,
178189
"write_conflicts": 0,
179190
"num_yields": 2,
180191
"waiting_for_lock": false,
192+
"lsid": null,
181193
"locks": {},
182194
"lock_stats": {
183195
"feature_compatibility_version": {
@@ -211,6 +223,7 @@
211223
"type": "op",
212224
"op": "getmore",
213225
"shard": null,
226+
"transaction": null,
214227
"dbname": "local",
215228
"application": "OplogFetcher",
216229
"collection": "oplog.rs",

mongo/tests/results/operation-activities-standalone.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
"query_framework": null,
2727
"current_op_time": "2024-05-16T18:06:38.419+00:00",
2828
"microsecs_running": 167,
29-
"transaction_time_open_micros": null,
3029
"prepare_read_conflicts": 0,
3130
"write_conflicts": 0,
3231
"num_yields": 0,
3332
"waiting_for_lock": false,
33+
"lsid": {
34+
"id": "fe7f64529521475ca6263130bc2c926e"
35+
},
3436
"locks": {
3537
"feature_compatibility_version": "r",
3638
"global": "r"
@@ -64,6 +66,7 @@
6466
"type": "op",
6567
"op": "query",
6668
"shard": null,
69+
"transaction": null,
6770
"dbname": "integration",
6871
"application": null,
6972
"collection": "products",
@@ -97,12 +100,12 @@
97100
"query_framework": "classic",
98101
"current_op_time": "2024-08-06T20:59:35.394+00:00",
99102
"microsecs_running": 13134,
100-
"transaction_time_open_micros": null,
101103
"prepare_read_conflicts": 0,
102104
"write_conflicts": 0,
103105
"num_yields": 2,
104106
"waiting_for_lock": false,
105107
"locks": {},
108+
"lsid": null,
106109
"lock_stats": {
107110
"feature_compatibility_version": {
108111
"acquire_count": {
@@ -135,6 +138,7 @@
135138
"type": "op",
136139
"op": "getmore",
137140
"shard": null,
141+
"transaction": null,
138142
"dbname": "local",
139143
"application": "OplogFetcher",
140144
"collection": "oplog.rs",

mongo/tests/results/operation-samples-mongos.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,11 +723,20 @@
723723
"query_framework": null,
724724
"current_op_time": "2024-05-20T14:36:56.231+00:00",
725725
"microsecs_running": 29232,
726-
"transaction_time_open_micros": null,
726+
"transaction": {
727+
"time_active_micros": 435,
728+
"time_inactive_micros": 1315,
729+
"time_open_micros": 1750,
730+
"txn_number": 392,
731+
"txn_retry_counter": 0
732+
},
727733
"prepare_read_conflicts": 0,
728734
"write_conflicts": 0,
729735
"num_yields": 0,
730736
"waiting_for_lock": false,
737+
"lsid": {
738+
"id": "ff95bad791504c36ab749ae8c640d54e"
739+
},
731740
"locks": {
732741
"feature_compatibility_version": "r",
733742
"global": "r"

mongo/tests/results/operation-samples-standalone.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,13 @@
144144
"query_framework": null,
145145
"current_op_time": "2024-05-16T18:06:38.419+00:00",
146146
"microsecs_running": 167,
147-
"transaction_time_open_micros": null,
148147
"prepare_read_conflicts": 0,
149148
"write_conflicts": 0,
150149
"num_yields": 0,
151150
"waiting_for_lock": false,
151+
"lsid": {
152+
"id": "fe7f64529521475ca6263130bc2c926e"
153+
},
152154
"locks": {
153155
"feature_compatibility_version": "r",
154156
"global": "r"
@@ -182,6 +184,7 @@
182184
"type": "op",
183185
"op": "query",
184186
"shard": null,
187+
"transaction": null,
185188
"collection": "products",
186189
"comment": "find",
187190
"truncated": "not_truncated"

0 commit comments

Comments
 (0)