XrayR/cmd/root.go
Senis 4a234d50e2
Add debug level logging option
This update introduces the ability to enable logging from the caller when the log level is set to "debug". This additional logging feature will provide more specificity and context for debugging tasks, aiding in quicker issue resolution.
2023-12-29 12:25:33 +08:00

122 lines
2.6 KiB
Go

package cmd
import (
"fmt"
"os"
"os/signal"
"path"
"runtime"
"strings"
"syscall"
"time"
log "github.com/sirupsen/logrus"
"github.com/fsnotify/fsnotify"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/XrayR-project/XrayR/panel"
)
var (
cfgFile string
rootCmd = &cobra.Command{
Use: "XrayR",
Run: func(cmd *cobra.Command, args []string) {
if err := run(); err != nil {
log.Fatal(err)
}
},
}
)
func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file for XrayR.")
}
func getConfig() *viper.Viper {
config := viper.New()
// Set custom path and name
if cfgFile != "" {
configName := path.Base(cfgFile)
configFileExt := path.Ext(cfgFile)
configNameOnly := strings.TrimSuffix(configName, configFileExt)
configPath := path.Dir(cfgFile)
config.SetConfigName(configNameOnly)
config.SetConfigType(strings.TrimPrefix(configFileExt, "."))
config.AddConfigPath(configPath)
// Set ASSET Path and Config Path for XrayR
os.Setenv("XRAY_LOCATION_ASSET", configPath)
os.Setenv("XRAY_LOCATION_CONFIG", configPath)
} else {
// Set default config path
config.SetConfigName("config")
config.SetConfigType("yml")
config.AddConfigPath(".")
}
if err := config.ReadInConfig(); err != nil {
log.Panicf("Config file error: %s \n", err)
}
config.WatchConfig() // Watch the config
return config
}
func run() error {
showVersion()
config := getConfig()
panelConfig := &panel.Config{}
if err := config.Unmarshal(panelConfig); err != nil {
return fmt.Errorf("Parse config file %v failed: %s \n", cfgFile, err)
}
if panelConfig.LogConfig.Level == "debug" {
log.SetReportCaller(true)
}
p := panel.New(panelConfig)
lastTime := time.Now()
config.OnConfigChange(func(e fsnotify.Event) {
// Discarding event received within a short period of time after receiving an event.
if time.Now().After(lastTime.Add(3 * time.Second)) {
// Hot reload function
fmt.Println("Config file changed:", e.Name)
p.Close()
// Delete old instance and trigger GC
runtime.GC()
if err := config.Unmarshal(panelConfig); err != nil {
log.Panicf("Parse config file %v failed: %s \n", cfgFile, err)
}
if panelConfig.LogConfig.Level == "debug" {
log.SetReportCaller(true)
}
p.Start()
lastTime = time.Now()
}
})
p.Start()
defer p.Close()
// Explicitly triggering GC to remove garbage from config loading.
runtime.GC()
// Running backend
osSignals := make(chan os.Signal, 1)
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
<-osSignals
return nil
}
func Execute() error {
return rootCmd.Execute()
}