github.com/status-im/status-go@v1.1.0/mobile/status_request_log.go (about) 1 package statusgo 2 3 import ( 4 "fmt" 5 "reflect" 6 "regexp" 7 "runtime" 8 "runtime/debug" 9 "strings" 10 "time" 11 12 "github.com/ethereum/go-ethereum/log" 13 "github.com/status-im/status-go/logutils/requestlog" 14 ) 15 16 var sensitiveRegex = regexp.MustCompile(`(?i)(".*?(password|mnemonic|openseaAPIKey|poktToken|alchemyArbitrumMainnetToken|raribleTestnetAPIKey|alchemyOptimismMainnetToken|statusProxyBlockchainUser|alchemyEthereumSepoliaToken|alchemyArbitrumSepoliaToken|infuraToken|raribleMainnetAPIKey|alchemyEthereumMainnetToken).*?")\s*:\s*("[^"]*")`) 17 18 func getFunctionName(fn any) string { 19 return runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() 20 } 21 22 func getShortFunctionName(fn any) string { 23 fullName := getFunctionName(fn) 24 parts := strings.Split(fullName, ".") 25 return parts[len(parts)-1] 26 } 27 28 // logAndCall logs request call details and executes the fn function if logging is enabled 29 func logAndCall(fn any, params ...any) any { 30 defer func() { 31 if r := recover(); r != nil { 32 // we're not sure if request logging is enabled here, so we log it use default logger 33 log.Error("panic found in logAndCall", "error", r, "stacktrace", string(debug.Stack())) 34 panic(r) 35 } 36 }() 37 38 var startTime time.Time 39 40 if requestlog.IsRequestLoggingEnabled() { 41 startTime = time.Now() 42 } 43 44 fnValue := reflect.ValueOf(fn) 45 fnType := fnValue.Type() 46 if fnType.Kind() != reflect.Func { 47 panic("fn must be a function") 48 } 49 50 args := make([]reflect.Value, len(params)) 51 for i, param := range params { 52 args[i] = reflect.ValueOf(param) 53 } 54 55 results := fnValue.Call(args) 56 57 var resp any 58 59 if len(results) > 0 { 60 resp = results[0].Interface() 61 } 62 63 if requestlog.IsRequestLoggingEnabled() { 64 duration := time.Since(startTime) 65 methodName := getShortFunctionName(fn) 66 paramsString := removeSensitiveInfo(fmt.Sprintf("%+v", params)) 67 respString := removeSensitiveInfo(fmt.Sprintf("%+v", resp)) 68 requestlog.GetRequestLogger().Debug(methodName, "params", paramsString, "resp", respString, "duration", duration) 69 } 70 71 return resp 72 } 73 74 func logAndCallString(fn any, params ...any) string { 75 resp := logAndCall(fn, params...) 76 if resp == nil { 77 return "" 78 } 79 return resp.(string) 80 } 81 82 func removeSensitiveInfo(jsonStr string) string { 83 // see related test for the usage of this function 84 return sensitiveRegex.ReplaceAllStringFunc(jsonStr, func(match string) string { 85 parts := sensitiveRegex.FindStringSubmatch(match) 86 return fmt.Sprintf(`%s:"***"`, parts[1]) 87 }) 88 }