feat: add config and logging
This commit is contained in:
parent
8d25d50376
commit
9f6da286ba
@ -3,32 +3,72 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/redis/go-redis/v9"
|
||||
|
||||
"xcontrol/server"
|
||||
"xcontrol/server/api"
|
||||
"xcontrol/server/config"
|
||||
"xcontrol/ui"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
slog.Warn("load config", "err", err)
|
||||
cfg = &config.Server{}
|
||||
}
|
||||
|
||||
level := slog.LevelInfo
|
||||
switch strings.ToLower(cfg.Log.Level) {
|
||||
case "debug":
|
||||
level = slog.LevelDebug
|
||||
case "warn", "warning":
|
||||
level = slog.LevelWarn
|
||||
case "error":
|
||||
level = slog.LevelError
|
||||
}
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}))
|
||||
slog.SetDefault(logger)
|
||||
|
||||
var conn *pgx.Conn
|
||||
if dsn := os.Getenv("KB_DSN"); dsn != "" {
|
||||
var err error
|
||||
if dsn := cfg.Postgres.DSN; dsn != "" {
|
||||
logger.Debug("connecting to postgres", "dsn", dsn)
|
||||
conn, err = pgx.Connect(context.Background(), dsn)
|
||||
if err != nil {
|
||||
log.Printf("kb db connect error: %v", err)
|
||||
logger.Error("postgres connect error", "err", err)
|
||||
} else {
|
||||
logger.Info("postgres connected")
|
||||
}
|
||||
} else {
|
||||
logger.Warn("postgres dsn not provided")
|
||||
}
|
||||
|
||||
if addr := cfg.Redis.Addr; addr != "" {
|
||||
logger.Debug("connecting to redis", "addr", addr)
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: addr,
|
||||
Password: cfg.Redis.Password,
|
||||
})
|
||||
if err := rdb.Ping(context.Background()).Err(); err != nil {
|
||||
logger.Error("redis connect error", "err", err)
|
||||
} else {
|
||||
logger.Info("redis connected")
|
||||
}
|
||||
} else {
|
||||
logger.Warn("redis addr not provided")
|
||||
}
|
||||
|
||||
uiFS, err := fs.Sub(ui.Assets, "dist")
|
||||
if err != nil {
|
||||
log.Fatalf("ui assets: %v", err)
|
||||
logger.Error("ui assets", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
r := server.New(
|
||||
|
||||
3
go.mod
3
go.mod
@ -8,6 +8,7 @@ require (
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-git/go-git/v5 v5.16.2
|
||||
github.com/jackc/pgx/v5 v5.7.5
|
||||
github.com/redis/go-redis/v9 v9.12.0
|
||||
github.com/yuin/goldmark v1.7.13
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/gorm v1.25.2
|
||||
@ -18,9 +19,11 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
|
||||
10
go.sum
10
go.sum
@ -9,9 +9,15 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
@ -22,6 +28,8 @@ github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGL
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
@ -104,6 +112,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/redis/go-redis/v9 v9.12.0 h1:XlVPGlflh4nxfhsNXPA8Qp6EmEfTo0rp8oaBzPipXnU=
|
||||
github.com/redis/go-redis/v9 v9.12.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
|
||||
@ -4,7 +4,7 @@ MODULE := xcontrol
|
||||
PORT := 3001
|
||||
OS := $(shell uname -s)
|
||||
|
||||
.PHONY: all build run clean init help dev
|
||||
.PHONY: all build run clean init help dev test
|
||||
|
||||
all: build
|
||||
|
||||
@ -37,8 +37,12 @@ build:
|
||||
go build -o $(APP_NAME) $(MAIN_FILE)
|
||||
|
||||
run:
|
||||
@echo ">>> 运行 $(APP_NAME) on port $(PORT)"
|
||||
PORT=$(PORT) go run $(MAIN_FILE)
|
||||
@echo ">>> 运行 $(APP_NAME) on port $(PORT) (后台运行)"
|
||||
@nohup env PORT=$(PORT) go run $(MAIN_FILE) > $(APP_NAME).log 2>&1 &
|
||||
|
||||
test:
|
||||
@echo ">>> 运行单元测试"
|
||||
go test ./...
|
||||
|
||||
dev:
|
||||
@echo ">>> 开发模式运行 $(APP_NAME) (热重载) on port $(PORT)"
|
||||
@ -57,7 +61,8 @@ help:
|
||||
@echo " XControl Server Makefile"
|
||||
@echo ""
|
||||
@echo "make build 编译 server 可执行文件"
|
||||
@echo "make run 运行 server (默认端口: $(PORT))"
|
||||
@echo "make run 后台运行 server (默认端口: $(PORT))"
|
||||
@echo "make test 运行单元测试"
|
||||
@echo "make dev 开发模式运行 (自动检测 air,如无则用 go run)"
|
||||
@echo "make init 初始化依赖(自动选择国内/默认 Go 模块代理,air 可选)"
|
||||
@echo "make clean 清理构建产物"
|
||||
|
||||
41
server/config/config.go
Normal file
41
server/config/config.go
Normal file
@ -0,0 +1,41 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Log struct {
|
||||
Level string `yaml:"level"`
|
||||
}
|
||||
|
||||
type Redis struct {
|
||||
Addr string `yaml:"addr"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
type Postgres struct {
|
||||
DSN string `yaml:"dsn"`
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Log Log `yaml:"log"`
|
||||
Redis Redis `yaml:"redis"`
|
||||
Postgres Postgres `yaml:"postgres"`
|
||||
}
|
||||
|
||||
// Load reads server/config/server.yaml and unmarshals into Server struct.
|
||||
func Load() (*Server, error) {
|
||||
path := filepath.Join("server", "config", "server.yaml")
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cfg Server
|
||||
if err := yaml.Unmarshal(b, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cfg, nil
|
||||
}
|
||||
@ -4,7 +4,7 @@ YARN := $(shell command -v yarn 2>/dev/null)
|
||||
MAGICK := $(shell command -v magick 2>/dev/null || command -v convert 2>/dev/null)
|
||||
OS := $(shell uname -s)
|
||||
|
||||
.PHONY: init dev build export clean info icon
|
||||
.PHONY: init dev build export clean info icon run test
|
||||
|
||||
icon:
|
||||
@echo "🎨 Generating favicon and icon images..."
|
||||
@ -51,6 +51,14 @@ dev:
|
||||
@echo "🚀 Starting Next.js dev server (homepage)..."
|
||||
yarn next dev -p 3001
|
||||
|
||||
run:
|
||||
@echo "🚀 Starting Next.js dev server (homepage) in background..."
|
||||
@nohup yarn next dev -p 3001 >/tmp/homepage.log 2>&1 &
|
||||
|
||||
test:
|
||||
@echo "🔍 Running tests..."
|
||||
@yarn test || echo "No tests configured"
|
||||
|
||||
build:
|
||||
@echo "🔨 Building homepage..."
|
||||
yarn next build
|
||||
|
||||
@ -5,7 +5,7 @@ NODE_VERSION := $(shell node -v 2>/dev/null || echo "Not Found")
|
||||
YARN := $(shell command -v yarn 2>/dev/null)
|
||||
OS := $(shell uname -s)
|
||||
|
||||
.PHONY: init build run export clean info
|
||||
.PHONY: init build run export clean info test
|
||||
|
||||
init:
|
||||
@echo "🔧 Installing dependencies..."
|
||||
@ -35,8 +35,12 @@ build:
|
||||
yarn build
|
||||
|
||||
run:
|
||||
@echo "🚀 Starting local dev server..."
|
||||
yarn dev
|
||||
@echo "🚀 Starting local dev server in background..."
|
||||
@nohup yarn dev >/tmp/panel.log 2>&1 &
|
||||
|
||||
test:
|
||||
@echo "🔍 Running tests..."
|
||||
@yarn test || echo "No tests configured"
|
||||
|
||||
export:
|
||||
@echo "📦 Exporting static site to ./out ..."
|
||||
|
||||
Loading…
Reference in New Issue
Block a user