Skip to content

Commit 2042b7f

Browse files
lvan100lianghuan
authored andcommitted
refactor(gs): supports multiple log file formats
1 parent 8e820e3 commit 2042b7f

File tree

8 files changed

+131
-112
lines changed

8 files changed

+131
-112
lines changed

conf/bind.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import (
2727
)
2828

2929
var (
30-
ErrNotExist = errors.New("not exist")
31-
ErrInvalidSyntax = errors.New("invalid syntax")
30+
ErrNotExist = util.FormatError(nil, "not exist")
31+
ErrInvalidSyntax = util.FormatError(nil, "invalid syntax")
3232
)
3333

3434
// ParsedTag represents a parsed configuration tag that encodes

gs/app.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func (s *AppStarter) stopApp() {
6565

6666
// Run starts the application, optionally runs a user-defined callback,
6767
// and waits for termination signals (e.g., SIGTERM, Ctrl+C) to trigger graceful shutdown.
68-
func (s *AppStarter) Run(fn ...func(ctx context.Context) error) {
68+
func (s *AppStarter) Run(fn ...func() error) {
6969

7070
// Start application
7171
if err := s.startApp(); err != nil {
@@ -76,7 +76,7 @@ func (s *AppStarter) Run(fn ...func(ctx context.Context) error) {
7676

7777
// Execute user-provided callback after app starts
7878
if len(fn) > 0 && fn[0] != nil {
79-
if err := fn[0](app.Ctx); err != nil {
79+
if err := fn[0](); err != nil {
8080
err = util.WrapError(err, "start app failed")
8181
log.Errorf(context.Background(), log.TagAppDef, "%s", err)
8282
return

gs/gs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ func Web(enable bool) *AppStarter {
280280
}
281281

282282
// Run starts the application with a custom run function.
283-
func Run(fn ...func(ctx context.Context) error) {
283+
func Run(fn ...func() error) {
284284
new(AppStarter).Run(fn...)
285285
}
286286

gs/internal/gs_app/app.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type App struct {
3939
P *gs_conf.AppConfig // Application configuration
4040

4141
exiting atomic.Bool // Indicates whether the application is shutting down
42-
Ctx context.Context // Root context for managing cancellation
42+
ctx context.Context // Root context for managing cancellation
4343
cancel context.CancelFunc // Function to cancel the root context
4444
wg sync.WaitGroup // WaitGroup to track running jobs and servers
4545

@@ -57,7 +57,7 @@ func NewApp() *App {
5757
return &App{
5858
C: gs_core.New(),
5959
P: gs_conf.NewAppConfig(),
60-
Ctx: ctx,
60+
ctx: ctx,
6161
cancel: cancel,
6262
}
6363
}
@@ -98,7 +98,7 @@ func (app *App) Start() error {
9898
if app.EnableJobs {
9999
for _, job := range app.Jobs {
100100
app.wg.Add(1)
101-
goutil.GoFunc(func() {
101+
goutil.Go(app.ctx, func(ctx context.Context) {
102102
defer app.wg.Done()
103103
defer func() {
104104
// Handle unexpected panics by shutting down the app
@@ -107,8 +107,8 @@ func (app *App) Start() error {
107107
panic(r)
108108
}
109109
}()
110-
if err := job.Run(app.Ctx); err != nil {
111-
log.Errorf(context.Background(), log.TagAppDef, "job run error: %v", err)
110+
if err := job.Run(ctx); err != nil {
111+
log.Errorf(ctx, log.TagAppDef, "job run error: %v", err)
112112
app.ShutDown()
113113
}
114114
})
@@ -121,7 +121,7 @@ func (app *App) Start() error {
121121
for _, svr := range app.Servers {
122122
sig.Add()
123123
app.wg.Add(1)
124-
goutil.GoFunc(func() {
124+
goutil.Go(app.ctx, func(ctx context.Context) {
125125
defer app.wg.Done()
126126
defer func() {
127127
// Handle server panics by intercepting readiness and shutting down
@@ -133,22 +133,22 @@ func (app *App) Start() error {
133133
}()
134134
err := svr.ListenAndServe(sig)
135135
if err != nil && !errors.Is(err, http.ErrServerClosed) {
136-
log.Errorf(context.Background(), log.TagAppDef, "server serve error: %v", err)
136+
log.Errorf(ctx, log.TagAppDef, "server serve error: %v", err)
137137
sig.Intercept()
138138
app.ShutDown()
139139
} else {
140-
log.Infof(context.Background(), log.TagAppDef, "server closed")
140+
log.Infof(ctx, log.TagAppDef, "server closed")
141141
}
142142
})
143143
}
144144

145145
// Wait for all servers to be ready
146146
sig.Wait()
147147
if sig.Intercepted() {
148-
log.Infof(context.Background(), log.TagAppDef, "server intercepted")
148+
log.Infof(app.ctx, log.TagAppDef, "server intercepted")
149149
return util.FormatError(nil, "server intercepted")
150150
}
151-
log.Infof(context.Background(), log.TagAppDef, "ready to serve requests")
151+
log.Infof(app.ctx, log.TagAppDef, "ready to serve requests")
152152
sig.Close()
153153
}
154154
return nil
@@ -158,19 +158,19 @@ func (app *App) Start() error {
158158
// and then gracefully stops all servers and jobs.
159159
func (app *App) WaitForShutdown() {
160160
// Wait until the application context is cancelled (triggered by ShutDown)
161-
<-app.Ctx.Done()
161+
<-app.ctx.Done()
162162

163163
// Gracefully shut down all running servers
164164
for _, svr := range app.Servers {
165-
goutil.GoFunc(func() {
166-
if err := svr.Shutdown(app.Ctx); err != nil {
167-
log.Errorf(context.Background(), log.TagAppDef, "shutdown server failed: %v", err)
165+
goutil.Go(app.ctx, func(ctx context.Context) {
166+
if err := svr.Shutdown(context.Background()); err != nil {
167+
log.Errorf(ctx, log.TagAppDef, "shutdown server failed: %v", err)
168168
}
169169
})
170170
}
171171
app.wg.Wait()
172172
app.C.Close()
173-
log.Infof(context.Background(), log.TagAppDef, "shutdown complete")
173+
log.Infof(app.ctx, log.TagAppDef, "shutdown complete")
174174
}
175175

176176
// Exiting returns whether the application is currently in the process of shutting down.
@@ -182,7 +182,7 @@ func (app *App) Exiting() bool {
182182
// setting the exiting flag and cancelling the root context.
183183
func (app *App) ShutDown() {
184184
if app.exiting.CompareAndSwap(false, true) {
185-
log.Infof(context.Background(), log.TagAppDef, "shutting down")
185+
log.Infof(app.ctx, log.TagAppDef, "shutting down")
186186
app.cancel()
187187
}
188188
}

gs/internal/gs_app/app_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"errors"
2323
"net/http"
2424
"os"
25-
"runtime/debug"
2625
"testing"
2726
"time"
2827

@@ -38,8 +37,8 @@ import (
3837
var logBuf = &bytes.Buffer{}
3938

4039
func init() {
41-
goutil.OnPanic = func(ctx context.Context, r any) {
42-
log.Panicf(ctx, log.TagAppDef, "panic: %v\n%s\n", r, debug.Stack())
40+
goutil.OnPanic = func(ctx context.Context, r any, stack []byte) {
41+
log.Panicf(ctx, log.TagAppDef, "panic: %v\n%s\n", r, stack)
4342
}
4443
}
4544

gs/log.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,54 +28,62 @@ import (
2828
// initLog initializes the application's logging system.
2929
func initLog() error {
3030

31-
// Refresh the global system configuration.
31+
// Step 1: Refresh the global system configuration.
3232
p, err := new(gs_conf.SysConfig).Refresh()
3333
if err != nil {
3434
return util.FormatError(err, "refresh error in source sys")
3535
}
3636

37+
// Step 2: Load logging-related configuration parameters.
3738
var c struct {
3839
// LocalDir is the directory that contains configuration files.
3940
// Defaults to "./conf" if not provided.
4041
LocalDir string `value:"${spring.app.config-local.dir:=./conf}"`
4142

4243
// Profiles specifies the active application profile(s),
43-
// such as "dev" or "prod".
44+
// such as "dev", "prod", etc.
45+
// Multiple profiles can be provided as a comma-separated list.
4446
Profiles string `value:"${spring.profiles.active:=}"`
4547
}
4648
if err = p.Bind(&c); err != nil {
4749
return util.FormatError(err, "bind error in source sys")
4850
}
4951

50-
var (
51-
logFileDefault = filepath.Join(c.LocalDir, "log.xml")
52-
logFileProfile string
53-
)
52+
extensions := []string{".properties", ".yaml", ".yml", ".xml", ".json"}
5453

55-
// If one or more profiles are set, use the first profile to look
56-
// for a profile-specific log configuration file.
57-
if c.Profiles != "" {
58-
profile := strings.Split(c.Profiles, ",")[0]
59-
logFileProfile = filepath.Join(c.LocalDir, "log-"+profile+".xml")
54+
// Step 3: Build a list of candidate configuration files.
55+
var files []string
56+
if profiles := strings.TrimSpace(c.Profiles); profiles != "" {
57+
for s := range strings.SplitSeq(profiles, ",") { // NOTE: range returns index
58+
if s = strings.TrimSpace(s); s != "" {
59+
for _, ext := range extensions {
60+
files = append(files, filepath.Join(c.LocalDir, "log-"+s+ext))
61+
}
62+
}
63+
}
64+
}
65+
for _, ext := range extensions {
66+
files = append(files, filepath.Join(c.LocalDir, "log"+ext))
6067
}
6168

62-
// Determine which log configuration file to use.
63-
var logFile string
64-
for _, s := range []string{logFileProfile, logFileDefault} {
69+
// Step 4: Detect existing configuration files.
70+
var logFiles []string
71+
for _, s := range files {
6572
if ok, err := util.PathExists(s); err != nil {
6673
return err
67-
} else if !ok {
68-
continue
74+
} else if ok {
75+
logFiles = append(logFiles, s)
6976
}
70-
logFile = s
71-
break
7277
}
7378

74-
// If no configuration file exists, leave the logger as default.
75-
if logFile == "" {
79+
// Step 5: Apply logging configuration or fall back to defaults.
80+
switch n := len(logFiles); {
81+
case n == 0:
82+
log.Infof(nil, log.TagAppDef, "no log configuration file found, using default logger")
7683
return nil
84+
case n > 1:
85+
return util.FormatError(nil, "multiple log files found: %s", logFiles)
86+
default:
87+
return log.RefreshFile(logFiles[0])
7788
}
78-
79-
// Refresh the logger configuration from the selected file.
80-
return log.RefreshFile(logFile)
8189
}

0 commit comments

Comments
 (0)