@@ -6,6 +6,34 @@ import type Request from '@src/types/onyx/Request';
6
6
import type Response from '@src/types/onyx/Response' ;
7
7
import type Middleware from './types' ;
8
8
9
+ function getCircularReplacer ( ) {
10
+ const ancestors : unknown [ ] = [ ] ;
11
+ return function ( this : unknown , key : string , value : unknown ) : unknown {
12
+ if ( typeof value !== 'object' || value === null ) {
13
+ return value ;
14
+ }
15
+ // `this` is the object that value is contained in, i.e the direct parent
16
+ // eslint-disable-next-line no-invalid-this
17
+ while ( ancestors . length > 0 && ancestors . at ( - 1 ) !== this ) {
18
+ ancestors . pop ( ) ;
19
+ }
20
+ if ( ancestors . includes ( value ) ) {
21
+ return '[Circular]' ;
22
+ }
23
+ ancestors . push ( value ) ;
24
+ return value ;
25
+ } ;
26
+ }
27
+
28
+ function serializeLoggingData < T extends Record < string , unknown > | undefined > ( logData : T ) : T | null {
29
+ try {
30
+ return JSON . parse ( JSON . stringify ( logData , getCircularReplacer ( ) ) ) as T ;
31
+ } catch ( error ) {
32
+ Log . hmmm ( 'Failed to serialize log data' , { error} ) ;
33
+ return null ;
34
+ }
35
+ }
36
+
9
37
function logRequestDetails ( message : string , request : Request , response ?: Response | void ) {
10
38
// Don't log about log or else we'd cause an infinite loop
11
39
if ( request . command === 'Log' ) {
@@ -38,7 +66,10 @@ function logRequestDetails(message: string, request: Request, response?: Respons
38
66
* requests because they contain sensitive information.
39
67
*/
40
68
if ( request . command !== 'AuthenticatePusher' ) {
41
- extraData . request = request ;
69
+ extraData . request = {
70
+ ...request ,
71
+ data : serializeLoggingData ( request . data ) ,
72
+ } ;
42
73
extraData . response = response ;
43
74
}
44
75
@@ -125,3 +156,5 @@ const Logging: Middleware = (response, request) => {
125
156
} ;
126
157
127
158
export default Logging ;
159
+
160
+ export { serializeLoggingData } ;
0 commit comments