Improve logging: add structured logs, enrich logs with useful info.

This commit is contained in:
Rustem Kamalov
2026-04-22 03:39:30 +03:00
parent d12a301cf8
commit 0d4e2da960
26 changed files with 657 additions and 247 deletions

View File

@@ -57,6 +57,7 @@ type AppConfig struct {
IsLeaveHead bool `mapstructure:"leave_head"`
IsLeakless bool `mapstructure:"leakless"`
IsStealth bool `mapstructure:"stealth"`
LogFormat string `mapstructure:"log_format"`
}
type EngineConfig struct {
@@ -117,6 +118,7 @@ var flagToConfigKey = map[string]string{
"cb_failures": "circuit_breaker.failures",
"cb_recovery": "circuit_breaker.recovery_seconds",
"cb_successes": "circuit_breaker.successes",
"log_format": "app.log_format",
}
var RootCmd = &cobra.Command{
@@ -131,8 +133,14 @@ var RootCmd = &cobra.Command{
return err
}
core.InitLogger(config.Server.IsVerbose, config.Server.IsDebug)
logrus.Debugf("Final config: %+v", config)
logFormat, err := core.NormalizeLogFormat(config.App.LogFormat)
if err != nil {
return err
}
config.App.LogFormat = logFormat
core.InitLogger(config.Server.IsVerbose, config.Server.IsDebug, config.App.LogFormat)
logrus.WithField("config", fmt.Sprintf("%+v", config)).Debug("Final config")
return nil
},
}
@@ -146,13 +154,13 @@ func bindFlags(cmd *cobra.Command, vpr *viper.Viper) {
}
if err := vpr.BindPFlag(configName, flg); err != nil {
logrus.Errorf("Unable to bind flag %s: %v", flg.Name, err)
logrus.WithError(err).Error(fmt.Sprintf("Unable to bind flag %s: %v", flg.Name, err))
}
if flg.Changed {
val, err := parseFlagValue(flg)
if err != nil {
logrus.Errorf("Unable to parse flag %s: %v", flg.Name, err)
logrus.WithError(err).Error(fmt.Sprintf("Unable to parse flag %s: %v", flg.Name, err))
return
}
vpr.Set(configName, val)
@@ -206,7 +214,7 @@ func initializeConfig(cmd *cobra.Command) error {
envKey := envPrefix + "_" + strings.ToUpper(strings.ReplaceAll(key, ".", "_"))
err := v.BindEnv(key, envKey)
if err != nil {
logrus.Errorf("Unable to bind ENV valye: %v", err)
logrus.WithError(err).Error(fmt.Sprintf("Unable to bind ENV valye: %v", err))
}
}
@@ -302,6 +310,7 @@ func setConfigDefaults(v *viper.Viper) {
v.SetDefault("server.verbose", false)
v.SetDefault("server.raw_requests", false)
v.SetDefault("server.insecure", false)
v.SetDefault("app.log_format", "")
v.SetDefault("app.timeout", 30)
v.SetDefault("app.browser_path", "")
@@ -325,7 +334,7 @@ func setConfigDefaults(v *viper.Viper) {
v.SetDefault("cors.enabled", true)
v.SetDefault("cors.allow_origins", "*")
v.SetDefault("cors.allow_methods", "GET, POST, OPTIONS")
v.SetDefault("cors.allow_headers", "Origin, Content-Type, Accept, Authorization, X-Use-Proxy")
v.SetDefault("cors.allow_headers", "Origin, Content-Type, Accept, Authorization, X-Use-Proxy, X-Request-ID, X-Tenant")
v.SetDefault("cors.max_age", 86400)
v.SetDefault("captcha.solver_enabled", false)
}
@@ -353,4 +362,5 @@ func init() {
RootCmd.PersistentFlags().IntVar(&config.CircuitBreaker.Failures, "cb_failures", 5, "Consecutive failures before circuit breaker opens")
RootCmd.PersistentFlags().IntVar(&config.CircuitBreaker.RecoverySeconds, "cb_recovery", 60, "Seconds before retrying an engine with open circuit")
RootCmd.PersistentFlags().IntVar(&config.CircuitBreaker.Successes, "cb_successes", 2, "Consecutive successful half-open checks needed to close circuit")
RootCmd.PersistentFlags().StringVar(&config.App.LogFormat, "log_format", "", "Log format: json or text (default: json in production, text in debug)")
}

View File

@@ -37,7 +37,7 @@ func search(cmd *cobra.Command, args []string) {
captchaSolverEnabled, captchaSolverAPIKey, err := resolveCaptchaSolverConfig()
if err != nil {
logrus.Errorf("Error validating captcha solver config: %v", err)
logrus.WithError(err).Error(fmt.Sprintf("Error validating captcha solver config: %v", err))
os.Exit(1)
}
@@ -48,7 +48,7 @@ func search(cmd *cobra.Command, args []string) {
proxyCfg, err := buildNormalizedProxyConfig(proxyRuntime)
if err != nil {
logrus.Errorf("Error validating proxy config: %v", err)
logrus.WithError(err).Error(fmt.Sprintf("Error validating proxy config: %v", err))
return
}
@@ -56,7 +56,7 @@ func search(cmd *cobra.Command, args []string) {
selectedProxy, err := selectCLIProxy(proxyCfg, policy)
if err != nil {
logrus.Errorf("Error selecting proxy for %s: %v", engineType, err)
logrus.WithError(err).Error(fmt.Sprintf("Error selecting proxy for %s: %v", engineType, err))
return
}
@@ -64,23 +64,29 @@ func search(cmd *cobra.Command, args []string) {
query.ProxyURL = selectedProxy
}
logrus.Infof("Starting SERP search request using %s engine for query: %s", engineType, query.Text)
logrus.WithFields(logrus.Fields{
"engine": engineType,
"query_hash": core.QueryHashFromQuery(query),
}).Info(fmt.Sprintf("Starting SERP search request using %s engine for query: %s", engineType, query.Text))
var results []core.SearchResult
if config.Server.IsRawRequests {
logrus.Infof("Using raw requests mode for %s search", engineType)
logrus.WithField("engine", engineType).Info(fmt.Sprintf("Using raw requests mode for %s search", engineType))
results, err = searchRaw(engineType, query)
} else {
logrus.Infof("Using browser mode for %s search", engineType)
logrus.WithField("engine", engineType).Info(fmt.Sprintf("Using browser mode for %s search", engineType))
results, err = searchBrowser(engineType, query, selectedProxy, captchaSolverEnabled, captchaSolverAPIKey)
}
if err != nil {
logrus.Errorf("Error during %s search: %s", engineType, err)
logrus.WithError(err).WithField("engine", engineType).Error(fmt.Sprintf("Error during %s search: %s", engineType, err))
return
}
logrus.Infof("Successfully completed SERP search using %s engine, returned %d results", engineType, len(results))
logrus.WithFields(logrus.Fields{
"engine": engineType,
"results_count": len(results),
}).Info(fmt.Sprintf("Successfully completed SERP search using %s engine, returned %d results", engineType, len(results)))
b, err := json.MarshalIndent(results, "", " ")
if err != nil {

View File

@@ -84,7 +84,7 @@ func serve(cmd *cobra.Command, args []string) {
proxyCfg, err := buildNormalizedProxyConfig(proxyRuntime)
if err != nil {
logrus.Errorf("invalid proxy configuration: %v", err)
logrus.WithError(err).Error(fmt.Sprintf("invalid proxy configuration: %v", err))
return
}