mirror of
https://github.com/wonli/aqi.git
synced 2024-06-28 09:57:05 +08:00
210 lines
4.2 KiB
Go
210 lines
4.2 KiB
Go
|
package aqi
|
|||
|
|
|||
|
import (
|
|||
|
"fmt"
|
|||
|
"net/http"
|
|||
|
"os"
|
|||
|
"path/filepath"
|
|||
|
"strings"
|
|||
|
"time"
|
|||
|
|
|||
|
"github.com/fatih/color"
|
|||
|
"github.com/fsnotify/fsnotify"
|
|||
|
"github.com/spf13/viper"
|
|||
|
|
|||
|
"github.com/wonli/aqi/config"
|
|||
|
"github.com/wonli/aqi/logger"
|
|||
|
"github.com/wonli/aqi/validate"
|
|||
|
)
|
|||
|
|
|||
|
type AppConfig struct {
|
|||
|
|
|||
|
//运行时数据存储基础路径
|
|||
|
DataPath string
|
|||
|
|
|||
|
//应用日志文件配置路径
|
|||
|
LogPathKey string
|
|||
|
|
|||
|
//默认语言
|
|||
|
Language string
|
|||
|
|
|||
|
//开发模式
|
|||
|
devMode bool
|
|||
|
|
|||
|
//服务名称,support.Version
|
|||
|
//当指定 HttpServerPortFindPath 时,在配置读取之后从配置路径获取http端口
|
|||
|
Servername []string
|
|||
|
ServerPort string
|
|||
|
HttpServerPortFindPath string
|
|||
|
|
|||
|
ConfigType string //配置文件类型
|
|||
|
ConfigPath string //配置文件路径
|
|||
|
ConfigName string //配置文件名称
|
|||
|
|
|||
|
Configs map[string]any
|
|||
|
|
|||
|
HttpServer http.Handler //http server
|
|||
|
|
|||
|
RemoteProvider *RemoteProvider //远程配置支持etcd, consul
|
|||
|
|
|||
|
WatchHandler func()
|
|||
|
}
|
|||
|
|
|||
|
var acf *AppConfig
|
|||
|
|
|||
|
func Init(options ...Option) *AppConfig {
|
|||
|
acf = &AppConfig{
|
|||
|
Language: "zh",
|
|||
|
ConfigType: "yaml",
|
|||
|
ConfigName: "config",
|
|||
|
ServerPort: "1091",
|
|||
|
LogPathKey: "log",
|
|||
|
DataPath: "data",
|
|||
|
}
|
|||
|
|
|||
|
for _, opt := range options {
|
|||
|
if opt != nil {
|
|||
|
err := opt(acf)
|
|||
|
if err != nil {
|
|||
|
color.Red("error %s", err.Error())
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if acf.ConfigPath == "" {
|
|||
|
workerDir, err := os.Getwd()
|
|||
|
if err != nil {
|
|||
|
color.Red("Failed to get the configuration file directory: %s", err.Error())
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
|
|||
|
acf.ConfigPath = workerDir
|
|||
|
}
|
|||
|
|
|||
|
if CommitVersion == "" {
|
|||
|
acf.devMode = true
|
|||
|
acf.ConfigName = fmt.Sprintf("%s-dev", acf.ConfigName)
|
|||
|
}
|
|||
|
|
|||
|
// 设置环境变量的前缀
|
|||
|
// 自动将环境变量绑定到 Viper 配置中
|
|||
|
viper.SetEnvPrefix("")
|
|||
|
viper.AutomaticEnv()
|
|||
|
|
|||
|
//设置配置文件
|
|||
|
viper.SetConfigName(acf.ConfigName)
|
|||
|
viper.SetConfigType(acf.ConfigType)
|
|||
|
|
|||
|
viper.AddConfigPath(acf.ConfigPath)
|
|||
|
err := viper.ReadInConfig()
|
|||
|
if err != nil {
|
|||
|
if acf.RemoteProvider == nil {
|
|||
|
err = acf.WriteDefaultConfig()
|
|||
|
if err != nil {
|
|||
|
color.Red("Error gen default config file: %s", err.Error())
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
|
|||
|
color.Red("failed to read config file: %s", err.Error())
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
|
|||
|
color.Red("Remote configuration will be used: %s", err.Error())
|
|||
|
} else {
|
|||
|
acf.Configs = viper.AllSettings()
|
|||
|
}
|
|||
|
|
|||
|
if acf.LogPathKey == "" {
|
|||
|
color.Red("Please specify LogPathKey")
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
|
|||
|
isSetDevMode := viper.IsSet("devMode")
|
|||
|
if isSetDevMode {
|
|||
|
setDevModel := viper.GetBool("devMode")
|
|||
|
acf.devMode = setDevModel
|
|||
|
}
|
|||
|
|
|||
|
viper.Set("devMode", acf.devMode)
|
|||
|
if acf.RemoteProvider != nil {
|
|||
|
_ = viper.AddRemoteProvider(string(acf.RemoteProvider.Name), acf.RemoteProvider.Endpoint, acf.RemoteProvider.Path)
|
|||
|
viper.SetConfigType(acf.RemoteProvider.Type)
|
|||
|
|
|||
|
err := viper.ReadRemoteConfig()
|
|||
|
if err != nil {
|
|||
|
color.Red("Failed to read remote config")
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
|
|||
|
go func() {
|
|||
|
t := time.NewTicker(time.Minute * 30)
|
|||
|
for range t.C {
|
|||
|
err2 := viper.WatchRemoteConfig()
|
|||
|
if err2 != nil {
|
|||
|
logger.SugarLog.Errorf("unable to read remote config: %v", err2)
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
if acf.WatchHandler != nil {
|
|||
|
acf.WatchHandler()
|
|||
|
}
|
|||
|
}
|
|||
|
}()
|
|||
|
}
|
|||
|
|
|||
|
//处理http服务端口信息
|
|||
|
if acf.HttpServerPortFindPath != "" {
|
|||
|
port := viper.GetString(acf.HttpServerPortFindPath)
|
|||
|
if port == "" {
|
|||
|
port = acf.ServerPort
|
|||
|
}
|
|||
|
|
|||
|
if strings.Contains(port, ":") {
|
|||
|
s := strings.Split(port, ":")
|
|||
|
port = s[len(s)-1]
|
|||
|
}
|
|||
|
|
|||
|
acf.ServerPort = port
|
|||
|
acf.Servername = append(acf.Servername, "is now running at http://0.0.0.0:"+port)
|
|||
|
}
|
|||
|
|
|||
|
//打印系统信息
|
|||
|
if acf.Servername != nil {
|
|||
|
AsciiLogo(acf.Servername...)
|
|||
|
}
|
|||
|
|
|||
|
if CommitVersion == "" {
|
|||
|
color.Green("dev mode -- use config %s", acf.ConfigName+"."+acf.ConfigType)
|
|||
|
}
|
|||
|
|
|||
|
var c config.Logger
|
|||
|
err = viper.UnmarshalKey(acf.LogPathKey, &c)
|
|||
|
if err != nil {
|
|||
|
color.Red("failed to init app log")
|
|||
|
os.Exit(1)
|
|||
|
}
|
|||
|
|
|||
|
if !filepath.IsAbs(c.LogPath) {
|
|||
|
c.LogPath = acf.GetDataPath(c.LogPath)
|
|||
|
}
|
|||
|
|
|||
|
//初始化日志库
|
|||
|
logger.Init(c)
|
|||
|
|
|||
|
//validate语言配置
|
|||
|
validate.InitTranslator(acf.Language)
|
|||
|
|
|||
|
//配置文件更新回调
|
|||
|
viper.OnConfigChange(func(e fsnotify.Event) {
|
|||
|
logger.SugarLog.Infof("config file changed: %s", e.Name)
|
|||
|
if acf.WatchHandler != nil {
|
|||
|
acf.WatchHandler()
|
|||
|
}
|
|||
|
})
|
|||
|
|
|||
|
//监听配置
|
|||
|
viper.WatchConfig()
|
|||
|
return acf
|
|||
|
}
|