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
|
||
}
|