15
15
import functools
16
16
17
17
from newrelic .api .time_trace import TimeTrace , current_trace
18
- from newrelic .common .async_wrapper import async_wrapper
18
+ from newrelic .common .async_wrapper import async_wrapper as get_async_wrapper
19
19
from newrelic .common .object_wrapper import FunctionWrapper , wrap_object
20
20
from newrelic .core .datastore_node import DatastoreNode
21
21
@@ -82,6 +82,9 @@ def __enter__(self):
82
82
self .product = transaction ._intern_string (self .product )
83
83
self .target = transaction ._intern_string (self .target )
84
84
self .operation = transaction ._intern_string (self .operation )
85
+ self .host = transaction ._intern_string (self .host )
86
+ self .port_path_or_id = transaction ._intern_string (self .port_path_or_id )
87
+ self .database_name = transaction ._intern_string (self .database_name )
85
88
86
89
datastore_tracer_settings = transaction .settings .datastore_tracer
87
90
self .instance_reporting_enabled = datastore_tracer_settings .instance_reporting .enabled
@@ -92,7 +95,14 @@ def __repr__(self):
92
95
return "<%s object at 0x%x %s>" % (
93
96
self .__class__ .__name__ ,
94
97
id (self ),
95
- dict (product = self .product , target = self .target , operation = self .operation ),
98
+ dict (
99
+ product = self .product ,
100
+ target = self .target ,
101
+ operation = self .operation ,
102
+ host = self .host ,
103
+ port_path_or_id = self .port_path_or_id ,
104
+ database_name = self .database_name ,
105
+ ),
96
106
)
97
107
98
108
def finalize_data (self , transaction , exc = None , value = None , tb = None ):
@@ -125,7 +135,7 @@ def create_node(self):
125
135
)
126
136
127
137
128
- def DatastoreTraceWrapper (wrapped , product , target , operation ):
138
+ def DatastoreTraceWrapper (wrapped , product , target , operation , host = None , port_path_or_id = None , database_name = None , async_wrapper = None ):
129
139
"""Wraps a method to time datastore queries.
130
140
131
141
:param wrapped: The function to apply the trace to.
@@ -140,6 +150,16 @@ def DatastoreTraceWrapper(wrapped, product, target, operation):
140
150
or the name of any API function/method in the client
141
151
library.
142
152
:type operation: str or callable
153
+ :param host: The name of the server hosting the actual datastore.
154
+ :type host: str
155
+ :param port_path_or_id: The value passed in can represent either the port,
156
+ path, or id of the datastore being connected to.
157
+ :type port_path_or_id: str
158
+ :param database_name: The name of database where the current query is being
159
+ executed.
160
+ :type database_name: str
161
+ :param async_wrapper: An async trace wrapper from newrelic.common.async_wrapper.
162
+ :type async_wrapper: callable or None
143
163
:rtype: :class:`newrelic.common.object_wrapper.FunctionWrapper`
144
164
145
165
This is typically used to wrap datastore queries such as calls to Redis or
@@ -155,7 +175,7 @@ def DatastoreTraceWrapper(wrapped, product, target, operation):
155
175
"""
156
176
157
177
def _nr_datastore_trace_wrapper_ (wrapped , instance , args , kwargs ):
158
- wrapper = async_wrapper (wrapped )
178
+ wrapper = async_wrapper if async_wrapper is not None else get_async_wrapper (wrapped )
159
179
if not wrapper :
160
180
parent = current_trace ()
161
181
if not parent :
@@ -187,7 +207,33 @@ def _nr_datastore_trace_wrapper_(wrapped, instance, args, kwargs):
187
207
else :
188
208
_operation = operation
189
209
190
- trace = DatastoreTrace (_product , _target , _operation , parent = parent , source = wrapped )
210
+ if callable (host ):
211
+ if instance is not None :
212
+ _host = host (instance , * args , ** kwargs )
213
+ else :
214
+ _host = host (* args , ** kwargs )
215
+ else :
216
+ _host = host
217
+
218
+ if callable (port_path_or_id ):
219
+ if instance is not None :
220
+ _port_path_or_id = port_path_or_id (instance , * args , ** kwargs )
221
+ else :
222
+ _port_path_or_id = port_path_or_id (* args , ** kwargs )
223
+ else :
224
+ _port_path_or_id = port_path_or_id
225
+
226
+ if callable (database_name ):
227
+ if instance is not None :
228
+ _database_name = database_name (instance , * args , ** kwargs )
229
+ else :
230
+ _database_name = database_name (* args , ** kwargs )
231
+ else :
232
+ _database_name = database_name
233
+
234
+ trace = DatastoreTrace (
235
+ _product , _target , _operation , _host , _port_path_or_id , _database_name , parent = parent , source = wrapped
236
+ )
191
237
192
238
if wrapper : # pylint: disable=W0125,W0126
193
239
return wrapper (wrapped , trace )(* args , ** kwargs )
@@ -198,7 +244,7 @@ def _nr_datastore_trace_wrapper_(wrapped, instance, args, kwargs):
198
244
return FunctionWrapper (wrapped , _nr_datastore_trace_wrapper_ )
199
245
200
246
201
- def datastore_trace (product , target , operation ):
247
+ def datastore_trace (product , target , operation , host = None , port_path_or_id = None , database_name = None , async_wrapper = None ):
202
248
"""Decorator allows datastore query to be timed.
203
249
204
250
:param product: The name of the vendor.
@@ -211,6 +257,16 @@ def datastore_trace(product, target, operation):
211
257
or the name of any API function/method in the client
212
258
library.
213
259
:type operation: str
260
+ :param host: The name of the server hosting the actual datastore.
261
+ :type host: str
262
+ :param port_path_or_id: The value passed in can represent either the port,
263
+ path, or id of the datastore being connected to.
264
+ :type port_path_or_id: str
265
+ :param database_name: The name of database where the current query is being
266
+ executed.
267
+ :type database_name: str
268
+ :param async_wrapper: An async trace wrapper from newrelic.common.async_wrapper.
269
+ :type async_wrapper: callable or None
214
270
215
271
This is typically used to decorate datastore queries such as calls to Redis
216
272
or ElasticSearch.
@@ -224,10 +280,21 @@ def datastore_trace(product, target, operation):
224
280
... time.sleep(*args, **kwargs)
225
281
226
282
"""
227
- return functools .partial (DatastoreTraceWrapper , product = product , target = target , operation = operation )
228
-
229
-
230
- def wrap_datastore_trace (module , object_path , product , target , operation ):
283
+ return functools .partial (
284
+ DatastoreTraceWrapper ,
285
+ product = product ,
286
+ target = target ,
287
+ operation = operation ,
288
+ host = host ,
289
+ port_path_or_id = port_path_or_id ,
290
+ database_name = database_name ,
291
+ async_wrapper = async_wrapper ,
292
+ )
293
+
294
+
295
+ def wrap_datastore_trace (
296
+ module , object_path , product , target , operation , host = None , port_path_or_id = None , database_name = None , async_wrapper = None
297
+ ):
231
298
"""Method applies custom timing to datastore query.
232
299
233
300
:param module: Module containing the method to be instrumented.
@@ -244,6 +311,16 @@ def wrap_datastore_trace(module, object_path, product, target, operation):
244
311
or the name of any API function/method in the client
245
312
library.
246
313
:type operation: str
314
+ :param host: The name of the server hosting the actual datastore.
315
+ :type host: str
316
+ :param port_path_or_id: The value passed in can represent either the port,
317
+ path, or id of the datastore being connected to.
318
+ :type port_path_or_id: str
319
+ :param database_name: The name of database where the current query is being
320
+ executed.
321
+ :type database_name: str
322
+ :param async_wrapper: An async trace wrapper from newrelic.common.async_wrapper.
323
+ :type async_wrapper: callable or None
247
324
248
325
This is typically used to time database query method calls such as Redis
249
326
GET.
@@ -256,4 +333,6 @@ def wrap_datastore_trace(module, object_path, product, target, operation):
256
333
... 'sleep')
257
334
258
335
"""
259
- wrap_object (module , object_path , DatastoreTraceWrapper , (product , target , operation ))
336
+ wrap_object (
337
+ module , object_path , DatastoreTraceWrapper , (product , target , operation , host , port_path_or_id , database_name , async_wrapper )
338
+ )
0 commit comments