diff --git a/cmd/server/powerx.go b/cmd/server/powerx.go index 5657ef2d..f8077816 100644 --- a/cmd/server/powerx.go +++ b/cmd/server/powerx.go @@ -4,13 +4,16 @@ import ( "PowerX/internal/middleware/recovery" "PowerX/internal/model" "PowerX/pkg/pluginx" - "PowerX/pkg/zerox" + "PowerX/pkg/zerox/log" + "os" + "context" "flag" "fmt" + "path/filepath" + "github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/rest/httpx" - "path/filepath" "PowerX/internal/config" "PowerX/internal/handler" @@ -20,6 +23,7 @@ import ( zgin "github.com/zeromicro/zero-contrib/router/gin" "github.com/zeromicro/go-zero/core/conf" + "github.com/zeromicro/go-zero/core/logx" ) // 定义了一个全局变量 configFile,用于指定配置文件的路径,默认为 etc/powerx.yaml。 @@ -34,6 +38,23 @@ func main() { var c config.Config conf.MustLoad(*configFile, &c) + // ---------- 设置日志 ---------- + if c.Log.Loki.Enabled { + c.Log.Loki.Labels = map[string]string{ + "project": c.Server.Name, + "host": c.Server.Host, + "env": c.Env, + "region": c.Region, + "version": c.Version, + "filename": c.Log.Logx.Path, + "job": "WebServer", + "node_id": fmt.Sprintf("node_%d", os.Getpid()), + "service_name": c.Log.Logx.ServiceName, + "level": c.Log.Logx.Level, + } + } + log.MustSetupLog(&c.Log) + // 设置配置文件目录 c.EtcDir = filepath.Dir(*configFile) model.PowerXSchema = c.PowerXDatabase.Schema @@ -44,8 +65,8 @@ func main() { r := zgin.NewRouter() // 创建 Go-Zero REST 服务器实例 - server := rest.MustNewServer(c.Server, rest.WithRouter(r)) - + // server := rest.MustNewServer(c.Server, rest.WithRouter(r)) + var server *rest.Server // 设置跨域配置 runOpt := config.SetupCors(&c) if runOpt == nil { @@ -56,9 +77,6 @@ func main() { // 确保服务器关闭 defer server.Stop() - // ---------- 设置日志 ---------- - zerox.MustSetupLog(c.Log) - // ---------- 创建插件管理器实例 ---------- plugin := pluginx.NewManager(context.Background(), r, fmt.Sprintf("%s:%d", "127.0.0.1", c.Server.Port)) // 创建服务上下文 @@ -87,6 +105,6 @@ func main() { httpx.SetErrorHandlerCtx(handler.ErrorHandleCtx) // ---------- 启动服务器 ---------- - fmt.Printf("Starting server at %s:%d...\n", c.Server.Host, c.Server.Port) + logx.Infof("Starting server at %s:%d...\n", c.Server.Host, c.Server.Port) server.Start() } diff --git a/etc/powerx-example.yaml b/etc/powerx-example.yaml index 42b5f53b..92027e93 100644 --- a/etc/powerx-example.yaml +++ b/etc/powerx-example.yaml @@ -1,6 +1,8 @@ Version: v1.0.0 # 版本 +Env: develop # 环境 +Region: global Server: - Name: PowerX后台系统 # 服务器名称 + Name: PowerX后台系统 # 服务器名称 Host: 0.0.0.0 # 服务器地址 Port: 8888 # 服务器端口 Timeout: 30000 # 超时时间 @@ -13,13 +15,29 @@ Cors: # - api.powerx.cn Log: - Path: logs - Split: - - error - Level: info - KeepDays: 30 Console: true - Stat: false + Logx: + ServiceName: powerx + Mode: file + Encoding: plain + TimeFormat: "2006-01-02 15:04:05" + Path: logs + Level: info + MaxContentLength: 10485760 + Compress: false + Stat: false + KeepDays: 30 + StackCooldownMillis: 100 + MaxBackups: 0 + MaxSize: 0 + Rotation: daily # `json:",default=daily,options=[daily,size]"` + + Loki: + Enabled: true + URL: http://localhost:3100/loki/api/v1/push + Labels: + app: powerx + env: develop Root: Account: root # 管理员账号 diff --git a/go.mod b/go.mod index f142e6a6..7a04fd69 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/brianvoe/gofakeit/v6 v6.21.0 github.com/casbin/casbin/v2 v2.60.0 github.com/gin-gonic/gin v1.9.0 - github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang-module/carbon/v2 v2.2.3 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.0 @@ -22,12 +22,12 @@ require ( github.com/minio/minio-go/v7 v7.0.52 github.com/pkg/errors v0.9.1 github.com/robfig/cron/v3 v3.0.1 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/urfave/cli/v2 v2.11.0 - github.com/zeromicro/go-zero v1.7.2 + github.com/zeromicro/go-zero v1.7.6 github.com/zeromicro/go-zero/tools/goctl v1.7.2 github.com/zeromicro/zero-contrib/router/gin v0.0.0-20230708101417-16e73a5d116c - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.31.0 golang.org/x/oauth2 v0.22.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/datatypes v1.1.1 @@ -49,7 +49,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/fatih/color v1.17.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -84,11 +84,11 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.20.2 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.58.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/redis/go-redis/v9 v9.6.1 // indirect + github.com/redis/go-redis/v9 v9.7.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/xid v1.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -110,18 +110,18 @@ require ( go.opentelemetry.io/otel/sdk v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/automaxprocs v1.5.3 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/grpc v1.66.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.36.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index a253270b..bd395fc6 100644 --- a/go.sum +++ b/go.sum @@ -418,8 +418,8 @@ github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGn github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.30.2/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6uH3VlUfb/HS5zKg= -github.com/alicebob/miniredis/v2 v2.33.0 h1:uvTF0EDeu9RLnUEG27Db5I68ESoIxTiXbNUiji6lZrA= -github.com/alicebob/miniredis/v2 v2.33.0/go.mod h1:MhP4a3EU7aENRi9aO+tHfTBZicLqQevyi/DJpoj6mi0= +github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0= +github.com/alicebob/miniredis/v2 v2.34.0/go.mod h1:kWShP4b58T1CW0Y5dViCd5ztzrDqRWqM3nksiyXk5s8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -515,8 +515,8 @@ github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= @@ -578,8 +578,9 @@ github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-module/carbon/v2 v2.2.3 h1:WvGIc5+qzq9drNzH+Gnjh1TZ0JgDY/IA+m2Dvk7Qm4Q= github.com/golang-module/carbon/v2 v2.2.3/go.mod h1:LdzRApgmDT/wt0eNT8MEJbHfJdSqCtT46uZhfF30dqI= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= @@ -897,8 +898,8 @@ github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrb github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= -github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= -github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -925,8 +926,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rabbitmq/amqp091-go v1.5.0/go.mod h1:JsV0ofX5f1nwOGafb8L5rBItt9GyhfQfcJj+oyz0dGg= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= -github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= @@ -973,8 +974,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1004,8 +1005,8 @@ github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7 github.com/zeromicro/antlr v0.0.1 h1:CQpIn/dc0pUjgGQ81y98s/NGOm2Hfru2NNio2I9mQgk= github.com/zeromicro/antlr v0.0.1/go.mod h1:nfpjEwFR6Q4xGDJMcZnCL9tEfQRgszMwu3rDz2Z+p5M= github.com/zeromicro/go-zero v1.5.2/go.mod h1:ndCd1nMMAdEMZgPfdm1fpavHUdBW0ykB6ckCRaSG10w= -github.com/zeromicro/go-zero v1.7.2 h1:a8lyVOG3KXG4LrAy6ZmtJTJtisX4Ostc4Pst4fE704I= -github.com/zeromicro/go-zero v1.7.2/go.mod h1:WFXfF92Exw0O7WECifS6r99JSzv4KEN49x9RhAfgkMc= +github.com/zeromicro/go-zero v1.7.6 h1:SArK4xecdrpVY3ZFJcbc0IZCx+NuWyHNjCv9f1+Gwrc= +github.com/zeromicro/go-zero v1.7.6/go.mod h1:SmGykRm5e0Z4CGNj+GaSKDffaHzQV56fel0FkymTLlE= github.com/zeromicro/go-zero/tools/goctl v1.7.2 h1:8cJ0E0kdatiCyNSPPk1JceRNCtmXMHjKVDWNBVzk0c8= github.com/zeromicro/go-zero/tools/goctl v1.7.2/go.mod h1:gD8pV/JJ7yWC5TBWUVr9P8V852EPCzfr/R2tqk84v1k= github.com/zeromicro/zero-contrib/router/gin v0.0.0-20230708101417-16e73a5d116c h1:cXVQ+uZ7TLLLwyj4dXYOJfcWTR1bzCe5Tp/FAwEozN0= @@ -1059,8 +1060,8 @@ go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= -go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= @@ -1094,8 +1095,8 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1209,8 +1210,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1257,8 +1258,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1357,8 +1358,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1385,8 +1386,8 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1701,8 +1702,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/config/config.go b/internal/config/config.go index a760033d..3ba4f97f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,7 +1,8 @@ package config import ( - "PowerX/pkg/zerox" + "PowerX/pkg/zerox/log" + "github.com/zeromicro/go-zero/rest" ) @@ -16,9 +17,11 @@ type Root struct { type Config struct { Version string + Env string + Region string Server rest.RestConf EtcDir string `json:",optional"` - Log zerox.LogConf + Log log.LogConf Cors Cors JWT struct { JWTSecret string diff --git a/internal/uc/custom.go b/internal/uc/custom.go index 2243d0d1..228244d5 100644 --- a/internal/uc/custom.go +++ b/internal/uc/custom.go @@ -2,10 +2,11 @@ package uc import ( "PowerX/internal/config" - "fmt" + "time" + "github.com/golang-module/carbon/v2" + "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" - "time" ) type CustomUseCase struct { @@ -34,9 +35,9 @@ func (uc *CustomUseCase) CheckSystemTimeZone() { // carbon 的timezone carbonTimezone := carbon.Now().Timezone() - fmt.Printf("check carbon datetime: timezone- %s\n", carbonTimezone) + logx.Infof("check carbon datetime: timezone- %s\n", carbonTimezone) // 输出系统默认时区 defaultTimezone := time.Now().Location() - fmt.Printf("check system datetime: timezone- %s\n", defaultTimezone.String()) + logx.Infof("check system datetime: timezone- %s\n", defaultTimezone.String()) } diff --git a/pkg/pluginx/manager.go b/pkg/pluginx/manager.go index f40b2c09..4ec2595b 100644 --- a/pkg/pluginx/manager.go +++ b/pkg/pluginx/manager.go @@ -5,15 +5,16 @@ import ( "context" "errors" "fmt" - "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/rest/httpx" - "gopkg.in/yaml.v3" "io" "net/http" "os" "path/filepath" "slices" "strings" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest/httpx" + "gopkg.in/yaml.v3" ) // Manager 管理插件的加载、启动和关闭 diff --git a/pkg/zerox/log.go b/pkg/zerox/log.go deleted file mode 100644 index c940e8fc..00000000 --- a/pkg/zerox/log.go +++ /dev/null @@ -1,204 +0,0 @@ -package zerox - -import ( - "encoding/json" - "errors" - "fmt" - "github.com/zeromicro/go-zero/core/logx" - "io" - "os" - "path/filepath" - "slices" - "time" -) - -type LogConf struct { - Path string `json:",default=logs"` - Split []string `json:",optional"` - KeepDays int `json:",default=30"` - Level string `json:",default=info"` - Console bool `json:",default=true"` - Stat bool `json:",default=false"` -} - -type Logger struct { - serverLog io.WriteCloser - errorLog io.WriteCloser - Level LogLevel -} - -type LogLevel int - -const ( - timestampKey = "@timestamp" - levelKey = "level" - contentKey = "content" -) - -const ( - LevelDebug LogLevel = iota - LevelInfo - LevelError -) - -var LogLevelMap = map[string]LogLevel{ - "debug": LevelDebug, - "info": LevelInfo, - "error": LevelError, -} - -func FromString(level string) LogLevel { - if v, ok := LogLevelMap[level]; ok { - return v - } - return LevelInfo -} - -func (l LogLevel) String() string { - switch l { - case LevelDebug: - return "debug" - case LevelInfo: - return "info" - case LevelError: - return "error" - } - return "info" -} - -func MustSetupLog(conf LogConf) { - if !conf.Stat { - logx.DisableStat() - } - if err := os.MkdirAll(conf.Path, os.ModePerm); err != nil { - panic(err) - } - logger := NewLogger(conf) - logx.SetWriter(logger) -} - -type wrapConsoleWriter struct { - console io.Writer - file io.WriteCloser -} - -func (w wrapConsoleWriter) Write(p []byte) (n int, err error) { - if _, err := w.console.Write(p); err != nil { - return 0, err - } - if _, err := w.file.Write(p); err != nil { - return 0, err - } - return len(p), nil -} - -func (w wrapConsoleWriter) Close() error { - return w.file.Close() -} - -func NewLogger(conf LogConf) Logger { - var logger Logger - logger.serverLog = NewRotateLogger(filepath.Join(conf.Path, "server.log"), conf.KeepDays) - if conf.Console { - logger.serverLog = wrapConsoleWriter{ - console: os.Stdout, - file: logger.serverLog, - } - } - if slices.Contains(conf.Split, "error") { - logger.errorLog = NewRotateLogger(filepath.Join(conf.Path, "error.log"), conf.KeepDays) - if conf.Console { - logger.errorLog = wrapConsoleWriter{ - console: os.Stderr, - file: logger.errorLog, - } - } - } else { - logger.errorLog = logger.serverLog - } - logger.Level = FromString(conf.Level) - return logger -} - -func NewRotateLogger(filename string, days int) *logx.RotateLogger { - rule := logx.DefaultRotateRule(filename, "-", days, false) - rotate, err := logx.NewLogger(filename, rule, false) - if err != nil { - panic(err) - } - return rotate -} - -func (l Logger) Alert(v interface{}) { - if l.Level <= LevelError { - output(l.errorLog, LevelInfo, v) - } -} - -func (l Logger) Close() error { - l.errorLog.Close() - l.serverLog.Close() - return nil -} - -func (l Logger) Debug(v interface{}, fields ...logx.LogField) { - if l.Level <= LevelDebug { - output(l.serverLog, LevelDebug, v, fields...) - } -} - -func (l Logger) Error(v interface{}, fields ...logx.LogField) { - if l.Level <= LevelError { - output(l.errorLog, LevelError, v, fields...) - } -} - -func (l Logger) Info(v interface{}, fields ...logx.LogField) { - if l.Level <= LevelInfo { - output(l.serverLog, LevelInfo, v, fields...) - } -} - -func (l Logger) Severe(v interface{}) { - if l.Level <= LevelError { - output(l.serverLog, LevelInfo, v) - } -} - -func (l Logger) Slow(v interface{}, fields ...logx.LogField) { - if l.Level <= LevelError { - output(l.serverLog, LevelInfo, v, fields...) - } -} - -func (l Logger) Stack(v interface{}) { - if l.Level <= LevelError { - output(l.errorLog, LevelError, v) - } -} - -func (l Logger) Stat(v interface{}, fields ...logx.LogField) { - if l.Level <= LevelError { - output(l.serverLog, LevelInfo, v, fields...) - } -} - -func output(writer io.Writer, level LogLevel, v interface{}, fields ...logx.LogField) { - if writer == nil { - return - } - levelStr := level.String() - entry := make(map[string]interface{}) - for _, field := range fields { - entry[field.Key] = field.Value - } - entry[levelKey] = levelStr - entry[timestampKey] = time.Now().Format(time.RFC3339) - entry[contentKey] = v - if result, err := json.Marshal(entry); err != nil { - fmt.Println(errors.New(fmt.Sprintf("marshal log entry failed: %v", err))) - } else { - _, _ = writer.Write(result) - } - writer.Write([]byte("\n")) -} diff --git a/pkg/zerox/log/log.go b/pkg/zerox/log/log.go new file mode 100644 index 00000000..626cd58c --- /dev/null +++ b/pkg/zerox/log/log.go @@ -0,0 +1,58 @@ +package log + +import ( + "os" + + "github.com/zeromicro/go-zero/core/logx" +) + +type LokiConf struct { + Enabled bool `json:",default=false"` // 是否启用 Loki + URL string `json:",optional"` // Loki 的 HTTP API 地址 + Labels map[string]string `json:",optional"` // Loki 的标签 + RetryCount int `json:",default=3"` // 重试次数(如果需要) +} + +type LogConf struct { + Console bool + Logx logx.LogConf `json:",optional"` + Loki LokiConf `json:",optional"` +} + +func MustSetupLog(conf *LogConf) { + + // 禁用统计信息(如果需要) + if !conf.Logx.Stat { + logx.DisableStat() + } + + // 创建日志目录 + if conf.Logx.Path == "" { + conf.Logx.Path = "logs" + } + if err := os.MkdirAll(conf.Logx.Path, os.ModePerm); err != nil { + logx.Errorf("failed to create log directory: %v", err) + panic(err) + } + + // 初始化 logx + logx.MustSetup(conf.Logx) + + // // 追加其他 writer + // var writers []io.Writer + + // Loki 输出 + if conf.Loki.Enabled { + + lokiWriter := NewLokiWriter(conf.Loki) + // writers = append(writers, lokiWriter) + logx.SetWriter(lokiWriter) + } + + // // 如果有额外 writer,则组合为 MultiWriter + // if len(writers) > 0 { + // multiWriter := io.MultiWriter(writers...) + // logx.SetWriter(multiWriter) + // } + +} diff --git a/pkg/zerox/log/loki.go b/pkg/zerox/log/loki.go new file mode 100644 index 00000000..ddc4edbf --- /dev/null +++ b/pkg/zerox/log/loki.go @@ -0,0 +1,163 @@ +package log + +import ( + fmt2 "PowerX/pkg/printx" + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + "github.com/zeromicro/go-zero/core/logx" +) + +type LokiWriter struct { + logx.Writer + url string + labels map[string]string + client *http.Client + retryCount int +} + +// 新增重试次数参数 +func NewLokiWriter(conf LokiConf) *LokiWriter { + if conf.RetryCount <= 0 { + conf.RetryCount = 3 // 默认重试3次 + } + return &LokiWriter{ + url: conf.URL, + labels: conf.Labels, + client: &http.Client{Timeout: 10 * time.Second}, + retryCount: conf.RetryCount, + } +} + +// Write 方法实现 +func (w *LokiWriter) Write(p []byte) (n int, err error) { + // 获取当前时间的 Unix 纳秒时间戳 + timestamp := time.Now().UnixNano() + + entry := map[string]interface{}{ + "streams": []map[string]interface{}{ + { + "stream": w.labels, + "values": [][]string{ + { + fmt.Sprintf("%d", timestamp), // 使用 Unix 纳秒时间戳 + string(p), // 日志内容 + }, + }, + }, + }, + } + + // 将日志转换为 JSON + body, err := json.Marshal(entry) + if err != nil { + return 0, err + } + // fmt2.Dump(string(body)) + + // 发送 HTTP 请求到 Loki,带有重试机制 + for attempt := 1; attempt <= w.retryCount; attempt++ { + resp, err := w.client.Post(w.url, "application/json", bytes.NewBuffer(body)) + if err != nil { + // 在重试次数内失败时,继续尝试 + if attempt == w.retryCount { + return 0, fmt.Errorf("failed to send log to Loki: %v", err) + } + time.Sleep(time.Second * time.Duration(attempt)) // 按照尝试次数递增等待时间 + continue + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusNoContent { + if attempt == w.retryCount { + errorBody, _ := io.ReadAll(resp.Body) // 读取响应体的内容 + fmt2.Dump(string(errorBody)) + return 0, fmt.Errorf("failed to send log to Loki: status %d - %s, response body: %s", resp.StatusCode, resp.Status, string(errorBody)) + } + time.Sleep(time.Second * time.Duration(attempt)) // 按照尝试次数递增等待时间 + continue + } + + return len(p), nil + } + + return 0, fmt.Errorf("failed to send log to Loki after %d attempts", w.retryCount) +} + +// Close 方法 +func (w *LokiWriter) Close() error { + // 可以用于关闭相关资源(如连接池等) + return nil +} + +// 实现 Alert 方法 +func (w *LokiWriter) Alert(v any) { + message := fmt.Sprint(v) + w.log(message) +} + +// 实现 Debug 方法 +func (w *LokiWriter) Debug(v any, fields ...logx.LogField) { + message := fmt.Sprint(v) + w.logWithFields(message, fields...) +} + +// 实现 Error 方法 +func (w *LokiWriter) Error(v any, fields ...logx.LogField) { + message := fmt.Sprint(v) + w.logWithFields(message, fields...) +} + +// 实现 Info 方法 +func (w *LokiWriter) Info(v any, fields ...logx.LogField) { + message := fmt.Sprint(v) + w.logWithFields(message, fields...) +} + +// 实现 Severe 方法 +func (w *LokiWriter) Severe(v any) { + message := fmt.Sprint(v) + w.log(message) +} + +// 实现 Slow 方法 +func (w *LokiWriter) Slow(v any, fields ...logx.LogField) { + message := fmt.Sprint(v) + w.logWithFields(message, fields...) +} + +// 实现 Stack 方法 +func (w *LokiWriter) Stack(v any) { + message := fmt.Sprint(v) + w.log(message) +} + +// 实现 Stat 方法 +func (w *LokiWriter) Stat(v any, fields ...logx.LogField) { + message := fmt.Sprint(v) + w.logWithFields(message, fields...) +} + +// 统一的日志处理函数 +func (w *LokiWriter) log(message string) { + _, err := w.Write([]byte(message)) + if err != nil { + fmt.Printf("failed to send log: %v\n", err) + } +} + +// 处理带有字段的日志 +func (w *LokiWriter) logWithFields(message string, fields ...logx.LogField) { + // 这里可以将字段添加到日志中 + for _, field := range fields { + message = fmt.Sprintf("%s, %s=%v", message, field.Key, field.Value) + } + _, err := w.Write([]byte(message)) + if err != nil { + fmt.Printf("failed to send log with fields: %v\n", err) + } +}