@@ -98,6 +98,35 @@ def set_error(self):
9898 if self .error_code != ErrorCode .EXCEPTION :
9999 self .error_code = ErrorCode .ERROR
100100
101+ def _copy_user_data_safely (self , data ):
102+ # pylint: disable=no-self-use
103+ """
104+ Safely copies user data in order to be able to send it in the trace.
105+ Converts any tuple keys to str (required for json.dumps).
106+ """
107+ if not data or not isinstance (data , (list , tuple , dict )):
108+ return data
109+
110+ if isinstance (data , (list , tuple )):
111+ return [
112+ self ._copy_user_data_safely (item ) for item in data
113+ ]
114+
115+ # data is a dict
116+ copied_dict = data .copy ()
117+ for key in data :
118+ value = self ._copy_user_data_safely (data [key ])
119+ if key is None or not isinstance (key , (
120+ str ,
121+ int ,
122+ float ,
123+ bool ,
124+ )): # the only supported keys
125+ copied_dict .pop (key )
126+ copied_dict [str (key )] = value
127+
128+ return copied_dict
129+
101130 def set_exception (
102131 self ,
103132 exception ,
@@ -119,7 +148,9 @@ def set_exception(
119148 else :
120149 self .exception ['type' ] = 'Unknown'
121150 self .exception ['message' ] = str (exception )
122- self .exception ['traceback' ] = traceback_data
151+ self .exception ['traceback' ] = self ._copy_user_data_safely (
152+ traceback_data
153+ )
123154 self .exception ['time' ] = time .time ()
124155
125156 # Adding python frames (input data of functions in stack) in python 3.
0 commit comments