Skip to content
This repository was archived by the owner on Jun 13, 2023. It is now read-only.

Commit 937bd16

Browse files
authored
fix(pymongo): extend support for more operations (#394)
1 parent 15ab5c9 commit 937bd16

2 files changed

Lines changed: 95 additions & 25 deletions

File tree

epsagon/events/pymongo.py

Lines changed: 80 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from __future__ import absolute_import
66
from uuid import uuid4
77
import traceback
8-
from past.builtins import range
98

109
from epsagon.utils import add_data_if_needed
1110
from ..event import BaseEvent
@@ -19,6 +18,10 @@ class PyMongoEvent(BaseEvent):
1918

2019
ORIGIN = 'pymongo'
2120
RESOURCE_TYPE = 'pymongo'
21+
INSERT_ONE = 'insert_one'
22+
INSERT_MANY = 'insert_many'
23+
INSERT_OPERATIONS = (INSERT_ONE, INSERT_MANY)
24+
FILTER_OPERATIONS = ('find', 'update_one', 'delete_many')
2225

2326
#pylint: disable=W0613
2427
def __init__(self, wrapped, instance, args, kwargs, start_time, response,
@@ -33,30 +36,25 @@ def __init__(self, wrapped, instance, args, kwargs, start_time, response,
3336
:param response: response data
3437
:param exception: Exception (if happened)
3538
"""
36-
3739
super(PyMongoEvent, self).__init__(start_time)
3840

39-
documents = args[0]
41+
self.resource['operation'] = getattr(wrapped, '__name__')
4042

4143
self.event_id = 'mongo-{}'.format(str(uuid4()))
42-
self.resource['name'] = instance.full_name
43-
44-
self.resource['operation'] = \
45-
'insert_many' if isinstance(documents, list) else 'insert_one'
44+
self.resource['name'] = instance.name
4645
address = list(getattr(
4746
instance.database.client,
4847
'_topology_settings'
49-
).seeds)[0]
50-
51-
if self.resource['operation'] == 'insert_one':
52-
documents = [documents]
48+
).seeds)[0]
5349

5450
self.resource['metadata'] = {
55-
'DB URL': ':'.join([str(x) for x in address]),
56-
'DB Name': str(instance.database.name),
57-
'Collection Name': str(instance.name),
58-
}
59-
add_data_if_needed(self.resource['metadata'], 'Items', documents)
51+
'DB URL': ':'.join([str(x) for x in address]),
52+
'DB Name': str(instance.database.name),
53+
'Collection Name': str(instance.collection.name),
54+
}
55+
56+
if args:
57+
self.handle_request_payload(args)
6058

6159
if response is not None:
6260
self.update_response(response)
@@ -70,17 +68,74 @@ def update_response(self, response):
7068
:param response: Response from botocore
7169
:return: None
7270
"""
73-
for i in range(len(self.resource['metadata'].get('items', []))):
74-
self.resource['metadata']['items'][i]['_id'] = str(
75-
self.resource['metadata']['items'][i]['_id']
76-
)
7771

78-
if self.resource['operation'] == 'insert_many':
79-
self.resource['metadata']['inserted_ids'] = \
80-
[str(x) for x in response.inserted_ids]
81-
elif self.resource['operation'] == 'insert_one':
72+
if self.resource['operation'] in PyMongoEvent.INSERT_OPERATIONS:
73+
self.handle_insert_operations_response(response)
74+
75+
elif self.resource['operation'] in PyMongoEvent.FILTER_OPERATIONS:
76+
self.handle_filter_operations_response(response)
77+
78+
79+
def handle_request_payload(self, input_args):
80+
"""
81+
Handle input data before add to event.
82+
:param input_args: input from botocore
83+
:return: None
84+
"""
85+
86+
if self.resource['operation'] == PyMongoEvent.INSERT_MANY:
87+
add_data_if_needed(self.resource['metadata'], 'Items',
88+
input_args[0])
89+
90+
elif self.resource['operation'] == PyMongoEvent.INSERT_ONE:
91+
add_data_if_needed(self.resource['metadata'], 'Item',
92+
input_args[0])
93+
94+
elif self.resource['operation'] in PyMongoEvent.FILTER_OPERATIONS:
95+
add_data_if_needed(self.resource['metadata'], 'Filter',
96+
input_args[0])
97+
98+
if self.resource['operation'] == 'update_one':
99+
add_data_if_needed(self.resource['metadata'], 'New Values',
100+
input_args[1])
101+
102+
103+
def handle_insert_operations_response(self, response):
104+
"""
105+
Handle response data before add to event.
106+
:param response: response from botocore
107+
:return: None
108+
"""
109+
110+
if self.resource['operation'] == PyMongoEvent.INSERT_MANY:
82111
self.resource['metadata']['inserted_ids'] = \
83-
[str(response.inserted_id)]
112+
[str(x) for x in response.inserted_ids]
113+
114+
elif self.resource['operation'] == PyMongoEvent.INSERT_ONE:
115+
self.resource['metadata']['inserted_id'] = \
116+
[str(response.inserted_id)]
117+
118+
119+
def handle_filter_operations_response(self, response):
120+
"""
121+
Handle response data before add to event.
122+
:param response: response from botocore
123+
:return: None
124+
"""
125+
126+
if self.resource['operation'] == 'find':
127+
self.resource['metadata']['Results'] = \
128+
list(response)
129+
130+
elif self.resource['operation'] == 'update_one':
131+
self.resource['metadata']['matched_count'] = \
132+
response.matched_count
133+
self.resource['metadata']['modified_count'] = \
134+
response.modified_count
135+
136+
elif self.resource['operation'] == 'delete_many':
137+
self.resource['metadata']['deleted_count'] = \
138+
response.deleted_count
84139

85140

86141
class PyMongoEventFactory(object):

epsagon/modules/pymongo.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,18 @@ def patch():
3737
'Collection.insert_many',
3838
_wrapper
3939
)
40+
wrapt.wrap_function_wrapper(
41+
'pymongo.collection',
42+
'Collection.find',
43+
_wrapper
44+
)
45+
wrapt.wrap_function_wrapper(
46+
'pymongo.collection',
47+
'Collection.update_one',
48+
_wrapper
49+
)
50+
wrapt.wrap_function_wrapper(
51+
'pymongo.collection',
52+
'Collection.delete_many',
53+
_wrapper
54+
)

0 commit comments

Comments
 (0)