1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15+ import functools
16+
1517from newrelic .api .time_trace import current_trace
1618from newrelic .api .transaction import current_transaction
1719from newrelic .common .async_wrapper import coroutine_wrapper
18- from newrelic .common .object_wrapper import wrap_function_wrapper
20+ from newrelic .common .object_wrapper import wrap_function_wrapper , wrap_object
1921from newrelic .common .signature import bind_args
2022from newrelic .core .context import ContextOf , context_wrapper
2123from newrelic .hooks .mlmodel_langchain import wrap_run_in_executor
@@ -57,33 +59,49 @@ def bind_submit(func, *args, **kwargs):
5759 return func , args , kwargs
5860
5961
60- def wrap_BackgroundExecutor_submit (wrapped , instance , args , kwargs ):
61- trace = current_trace ()
62- if not trace :
63- return wrapped (* args , ** kwargs )
62+ def wrap_BackgroundExecutor_submit (wrapped ):
63+ # We can't use wrapt FuctionWrapper here because the function will be wrapped in a weakref.WeakMethod,
64+ # which isn't compatible with wrapt. Instead, we have to do the wrapping manually. We use functools.wraps
65+ # to preserve the original function's signature, name, and annotations as best as we can.
66+ @functools .wraps (wrapped )
67+ def _wrapper (self , * args , ** kwargs ):
68+ # This will be a bound method, so the first argument must always be self.
69+ trace = current_trace ()
70+ if not trace :
71+ return wrapped (self , * args , ** kwargs )
6472
65- try :
66- func , args , kwargs = bind_submit (* args , ** kwargs )
67- except Exception :
68- return wrapped (* args , ** kwargs )
73+ try :
74+ func , args , kwargs = bind_submit (* args , ** kwargs )
75+ except Exception :
76+ return wrapped (self , * args , ** kwargs )
6977
70- func = context_wrapper (func , trace = trace , strict = True )
71- return wrapped (func , * args , ** kwargs )
78+ func = context_wrapper (func , trace = trace , strict = True )
79+ return wrapped (self , func , * args , ** kwargs )
7280
81+ return _wrapper
7382
74- def wrap_AsyncBackgroundExecutor_submit (wrapped , instance , args , kwargs ):
75- trace = current_trace ()
76- if not trace :
77- return wrapped (* args , ** kwargs )
7883
79- try :
80- func , args , kwargs = bind_submit (* args , ** kwargs )
81- except Exception :
82- return wrapped (* args , ** kwargs )
84+ def wrap_AsyncBackgroundExecutor_submit (wrapped ):
85+ # We can't use wrapt FuctionWrapper here because the function will be wrapped in a weakref.WeakMethod,
86+ # which isn't compatible with wrapt. Instead, we have to do the wrapping manually. We use functools.wraps
87+ # to preserve the original function's signature, name, and annotations as best as we can.
88+ @functools .wraps (wrapped )
89+ def _wrapper (self , * args , ** kwargs ):
90+ # This will be a bound method, so the first argument must always be self.
91+ trace = current_trace ()
92+ if not trace :
93+ return wrapped (self , * args , ** kwargs )
8394
84- context = ContextOf (trace = trace , strict = True )
85- func = coroutine_wrapper (func , context )
86- return wrapped (func , * args , ** kwargs )
95+ try :
96+ func , args , kwargs = bind_submit (* args , ** kwargs )
97+ except Exception :
98+ return wrapped (self , * args , ** kwargs )
99+
100+ context = ContextOf (trace = trace , strict = True )
101+ func = coroutine_wrapper (func , context )
102+ return wrapped (self , func , * args , ** kwargs )
103+
104+ return _wrapper
87105
88106
89107def instrument_langgraph_prebuilt_tool_node (module ):
@@ -96,9 +114,10 @@ def instrument_langgraph_prebuilt_tool_node(module):
96114
97115def instrument_langgraph_pregel_executor (module ):
98116 if hasattr (module , "BackgroundExecutor" ):
99- wrap_function_wrapper (module , "BackgroundExecutor.submit" , wrap_BackgroundExecutor_submit )
117+ wrap_object (module , "BackgroundExecutor.submit" , wrap_BackgroundExecutor_submit )
118+
100119 if hasattr (module , "AsyncBackgroundExecutor" ):
101- wrap_function_wrapper (module , "AsyncBackgroundExecutor.submit" , wrap_AsyncBackgroundExecutor_submit )
120+ wrap_object (module , "AsyncBackgroundExecutor.submit" , wrap_AsyncBackgroundExecutor_submit )
102121
103122
104123def instrument_langgraph_internal_runnable (module ):
0 commit comments