From c3909f7f0b077104b8af31852c70d3645354a9d3 Mon Sep 17 00:00:00 2001 From: Igor Sirotin Date: Fri, 22 Nov 2024 16:26:05 +0000 Subject: [PATCH] feat_: init logs in `InitializeApplication` --- api/defaults.go | 12 +++-- logutils/override.go | 3 +- mobile/callog/status_request_log.go | 54 +++++++++++--------- mobile/status.go | 56 +++++++++++++++++++-- protocol/requests/initialize_application.go | 8 +++ 5 files changed, 99 insertions(+), 34 deletions(-) diff --git a/api/defaults.go b/api/defaults.go index eff89e401..4982bda98 100644 --- a/api/defaults.go +++ b/api/defaults.go @@ -27,11 +27,13 @@ const ( shardsTestClusterID = 16 walletAccountDefaultName = "Account 1" - DefaultKeystoreRelativePath = "keystore" - DefaultKeycardPairingDataFile = "/ethereum/mainnet_rpc/keycard/pairings.json" - DefaultDataDir = "/ethereum/mainnet_rpc" - DefaultNodeName = "StatusIM" - DefaultLogFile = "geth.log" + DefaultKeystoreRelativePath = "keystore" + DefaultKeycardPairingDataFile = "/ethereum/mainnet_rpc/keycard/pairings.json" + DefaultDataDir = "/ethereum/mainnet_rpc" + DefaultNodeName = "StatusIM" + DefaultLogFile = "geth.log" + DefaultAPILogFile = "api.log" + DefaultLogLevel = "ERROR" DefaultMaxPeers = 20 DefaultMaxPendingPeers = 20 diff --git a/logutils/override.go b/logutils/override.go index 65e68c16f..75cf9913f 100644 --- a/logutils/override.go +++ b/logutils/override.go @@ -10,7 +10,8 @@ import ( ) type LogSettings struct { - Enabled bool `json:"Enabled"` + Enabled bool `json:"Enabled"` + // Deprecated: MobileSystem should not be used and will be removed in the future. MobileSystem bool `json:"MobileSystem"` Level string `json:"Level"` File string `json:"File"` diff --git a/mobile/callog/status_request_log.go b/mobile/callog/status_request_log.go index a0ee4454d..e80574fae 100644 --- a/mobile/callog/status_request_log.go +++ b/mobile/callog/status_request_log.go @@ -61,20 +61,9 @@ func getShortFunctionName(fn any) string { // 4. If request logging is enabled, logs method name, parameters, response, and execution duration // 5. Removes sensitive information before logging func Call(logger, requestLogger *zap.Logger, fn any, params ...any) any { - defer func() { - if r := recover(); r != nil { - logger.Error("panic found in call", zap.Any("error", r), zap.Stack("stacktrace")) - panic(r) - } - }() - - var startTime time.Time - - requestLoggingEnabled := requestLogger != nil - if requestLoggingEnabled { - startTime = time.Now() - } + defer Recover(logger) + startTime := time.Now() fnValue := reflect.ValueOf(fn) fnType := fnValue.Type() if fnType.Kind() != reflect.Func { @@ -94,18 +83,9 @@ func Call(logger, requestLogger *zap.Logger, fn any, params ...any) any { resp = results[0].Interface() } - if requestLoggingEnabled { - duration := time.Since(startTime) + if requestLogger != nil { methodName := getShortFunctionName(fn) - paramsString := removeSensitiveInfo(fmt.Sprintf("%+v", params)) - respString := removeSensitiveInfo(fmt.Sprintf("%+v", resp)) - - requestLogger.Debug("call", - zap.String("method", methodName), - zap.String("params", paramsString), - zap.String("resp", respString), - zap.Duration("duration", duration), - ) + Log(requestLogger, methodName, params, resp, startTime) } return resp @@ -126,3 +106,29 @@ func removeSensitiveInfo(jsonStr string) string { return fmt.Sprintf(`%s:"***"`, parts[1]) }) } + +func Recover(logger *zap.Logger) { + err := recover() + if err == nil { + return + } + + logger.Error("panic found in call", + zap.Any("error", err), + zap.Stack("stacktrace")) + + panic(err) +} + +func Log(logger *zap.Logger, method string, params any, resp any, startTime time.Time) { + if logger == nil { + return + } + duration := time.Since(startTime) + logger.Debug("call", + zap.String("method", method), + zap.String("params", removeSensitiveInfo(fmt.Sprintf("%+v", params))), + zap.String("resp", removeSensitiveInfo(fmt.Sprintf("%+v", resp))), + zap.Duration("duration", duration), + ) +} diff --git a/mobile/status.go b/mobile/status.go index 113045f32..60c75a616 100644 --- a/mobile/status.go +++ b/mobile/status.go @@ -49,6 +49,9 @@ import ( "github.com/status-im/status-go/services/wallet/wallettypes" "github.com/status-im/status-go/signal" + "path" + "time" + "github.com/status-im/status-go/mobile/callog" ) @@ -66,7 +69,21 @@ type InitializeApplicationResponse struct { } func InitializeApplication(requestJSON string) string { - return callWithResponse(initializeApplication, requestJSON) + // NOTE: InitializeApplication is logs the call on its own rather than using `callWithResponse`, + // because the API logging is enabled during this exact call. + defer callog.Recover(logutils.ZapLogger()) + + startTime := time.Now() + response := initializeApplication(requestJSON) + callog.Log( + requestlog.GetRequestLogger(), + "InitializeApplication", + requestJSON, + response, + startTime, + ) + + return response } func initializeApplication(requestJSON string) string { @@ -80,28 +97,58 @@ func initializeApplication(requestJSON string) string { return makeJSONResponse(err) } + // Initialize logs + if request.LogDir == "" { + request.LogDir = request.DataDir + } + logSettings := logutils.LogSettings{ + Enabled: request.LogEnabled, + MobileSystem: false, + Level: request.LogLevel, + File: path.Join(request.LogDir, api.DefaultLogFile), + } + if err = logutils.OverrideRootLoggerWithConfig(logSettings); err == nil { + logutils.ZapLogger().Info("logging initialised", zap.Any("logSettings", logSettings)) + } else { + return makeJSONResponse(err) + } + + if request.APILoggingEnabled { + logRequestsFile := path.Join(request.LogDir, api.DefaultAPILogFile) + err = requestlog.ConfigureAndEnableRequestLogging(logRequestsFile) + if err != nil { + return makeJSONResponse(err) + } + } + // initialize metrics providers.MixpanelAppID = request.MixpanelAppID providers.MixpanelToken = request.MixpanelToken statusBackend.StatusNode().SetMediaServerEnableTLS(request.MediaServerEnableTLS) - statusBackend.UpdateRootDataDir(request.DataDir) + + // Read available accounts err = statusBackend.OpenAccounts() if err != nil { return makeJSONResponse(err) } + accs, err := statusBackend.GetAccounts() if err != nil { return makeJSONResponse(err) } - centralizedMetricsInfo, err := statusBackend.CentralizedMetricsInfo() + + // Read centralized metrics info + metricsInfo, err := statusBackend.CentralizedMetricsInfo() if err != nil { return makeJSONResponse(err) } + + // Prepare response response := &InitializeApplicationResponse{ Accounts: accs, - CentralizedMetricsInfo: centralizedMetricsInfo, + CentralizedMetricsInfo: metricsInfo, } data, err := json.Marshal(response) if err != nil { @@ -2152,6 +2199,7 @@ type InitLoggingRequest struct { // InitLogging The InitLogging function should be called when the application starts. // This ensures that we can capture logs before the user login. Subsequent calls will update the logger settings. // Before this, we can only capture logs after user login since we will only configure the logging after the login process. +// Deprecated: Use InitializeApplication instead func InitLogging(logSettingsJSON string) string { var logSettings InitLoggingRequest var err error diff --git a/protocol/requests/initialize_application.go b/protocol/requests/initialize_application.go index 39fa3aa14..7c111dfad 100644 --- a/protocol/requests/initialize_application.go +++ b/protocol/requests/initialize_application.go @@ -14,6 +14,14 @@ type InitializeApplication struct { MixpanelToken string `json:"mixpanelToken"` // MediaServerEnableTLS is optional, if not provided, media server will use TLS by default MediaServerEnableTLS *bool `json:"mediaServerEnableTLS"` + + // LogDir specifies the directory where logs are stored. + // If empty, logs are stored in the `DataDir`. + LogDir string `json:"logDir"` + + LogEnabled bool `json:"logEnabled"` + LogLevel string `json:"logLevel"` + APILoggingEnabled bool `json:"apiLoggingEnabled"` } func (i *InitializeApplication) Validate() error {