From 458382dd3d10b862a2c1eaf34c6f7ecdb3496d3c Mon Sep 17 00:00:00 2001 From: tobyxdd Date: Tue, 4 Jul 2023 13:06:52 -0700 Subject: [PATCH] feat: logging environment variables --- README.md | 27 ++++++++++++++-- app/cmd/root.go | 86 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c0ef54e..7751031 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,19 @@ # Hysteria 2 Prototype > **Warning** -> The code on this branch is a work-in-progress prototype of what will become Hysteria 2.0. It is currently very unfinished, and unless you know what you are doing, you should stick with the stable 1.x releases for now. **The protocol is also subject to change, so we do not recommend third-party developers use this as a reference for the Hysteria 2 protocol at this time.** +> The code on this branch is a work-in-progress prototype of what will become Hysteria 2.0. It is currently very +> unfinished, and unless you know what you are doing, you should stick with the stable 1.x releases for now. **The +protocol is also subject to change, so we do not recommend third-party developers use this as a reference for the +Hysteria 2 protocol at this time.** > **警告** -> 此分支的代码是 Hysteria 2.0 的原型,目前仍在开发中,完成度十分有限。除非你十分确定自己在做什么,否则请继续使用稳定的 1.x 版本。**协议也可能会发生变化,因此我们不建议第三方开发者在目前使用此分支作为 Hysteria 2 协议的参考。** +> 此分支的代码是 Hysteria 2.0 的原型,目前仍在开发中,完成度十分有限。除非你十分确定自己在做什么,否则请继续使用稳定的 1.x +> 版本。**协议也可能会发生变化,因此我们不建议第三方开发者在目前使用此分支作为 Hysteria 2 协议的参考。** ## Build (编译) -Use the environment variable `HY_APP_PLATFORMS` to control which platforms to build for. For example: `"windows/amd64,linux/amd64,linux/arm"` +Use the environment variable `HY_APP_PLATFORMS` to control which platforms to build for. For +example: `"windows/amd64,linux/amd64,linux/arm"` 用环境变量 `HY_APP_PLATFORMS` 来控制编译哪些平台的可执行文件。例如:`"windows/amd64,linux/amd64,linux/arm"` @@ -21,6 +26,7 @@ Builds will be placed in `./build` (编译输出在 `./build` 目录下) ## Usage (使用) ### Server + ```bash ./hysteria server -c config.yaml ``` @@ -28,12 +34,27 @@ Builds will be placed in `./build` (编译输出在 `./build` 目录下) [Example sever config (示例服务器配置)](app/server.example.yaml) ### Client + ```bash ./hysteria client -c config.yaml ``` [Example client config (示例客户端配置)](app/client.example.yaml) +## Logging (日志) + +The following environment variables for controlling logging are supported: + +- `LOG_LEVEL` - supported values are `debug`, `info`, `warn`, `error` + +- `LOG_FORMAT` - supported values are `console`, `json` + +支持通过以下环境变量来控制日志: + +- `LOG_LEVEL` - 支持的值有 `debug`, `info`, `warn`, `error` + +- `LOG_FORMAT` - 支持的值有 `console`, `json` + ## Test HTTP/3 masquerading (测试 HTTP/3 伪装) ```bash diff --git a/app/cmd/root.go b/app/cmd/root.go index 6445f08..16c8140 100644 --- a/app/cmd/root.go +++ b/app/cmd/root.go @@ -3,10 +3,12 @@ package cmd import ( "fmt" "os" + "strings" "github.com/spf13/cobra" "github.com/spf13/viper" "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) const ( @@ -33,7 +35,11 @@ var ( var logger *zap.Logger // Flags -var cfgFile string +var ( + cfgFile string + logLevel string + logFormat string +) var rootCmd = &cobra.Command{ Use: "hysteria", @@ -42,6 +48,36 @@ var rootCmd = &cobra.Command{ Run: runClient, // Default to client mode } +var logLevelMap = map[string]zapcore.Level{ + "debug": zapcore.DebugLevel, + "info": zapcore.InfoLevel, + "warn": zapcore.WarnLevel, + "error": zapcore.ErrorLevel, +} + +var logFormatMap = map[string]zapcore.EncoderConfig{ + "console": { + TimeKey: "time", + LevelKey: "level", + NameKey: "logger", + MessageKey: "msg", + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.CapitalColorLevelEncoder, + EncodeTime: zapcore.RFC3339TimeEncoder, + EncodeDuration: zapcore.SecondsDurationEncoder, + }, + "json": { + TimeKey: "time", + LevelKey: "level", + NameKey: "logger", + MessageKey: "msg", + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.LowercaseLevelEncoder, + EncodeTime: zapcore.EpochMillisTimeEncoder, + EncodeDuration: zapcore.SecondsDurationEncoder, + }, +} + func Execute() { err := rootCmd.Execute() if err != nil { @@ -50,22 +86,15 @@ func Execute() { } func init() { - initLogger() initFlags() cobra.OnInitialize(initConfig) -} - -func initLogger() { - // TODO: Configurable logging - l, err := zap.NewDevelopment() - if err != nil { - panic(err) - } - logger = l + cobra.OnInitialize(initLogger) // initLogger must come after initConfig as it depends on config } func initFlags() { rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file") + rootCmd.PersistentFlags().StringVarP(&logLevel, "log-level", "l", envOrDefault("LOG_LEVEL", "info"), "log level") + rootCmd.PersistentFlags().StringVarP(&logFormat, "log-format", "f", envOrDefault("LOG_FORMAT", "console"), "log format") } func initConfig() { @@ -79,3 +108,38 @@ func initConfig() { viper.AddConfigPath(".") } } + +func initLogger() { + level, ok := logLevelMap[strings.ToLower(logLevel)] + if !ok { + fmt.Printf("unsupported log level: %s\n", logLevel) + os.Exit(1) + } + enc, ok := logFormatMap[strings.ToLower(logFormat)] + if !ok { + fmt.Printf("unsupported log format: %s\n", logFormat) + os.Exit(1) + } + c := zap.Config{ + Level: zap.NewAtomicLevelAt(level), + DisableCaller: true, + DisableStacktrace: true, + Encoding: strings.ToLower(logFormat), + EncoderConfig: enc, + OutputPaths: []string{"stderr"}, + ErrorOutputPaths: []string{"stderr"}, + } + var err error + logger, err = c.Build() + if err != nil { + fmt.Printf("failed to initialize logger: %s\n", err) + os.Exit(1) + } +} + +func envOrDefault(key, def string) string { + if v := os.Getenv(key); v != "" { + return v + } + return def +}