Skip to content

Commit 0eb4ab4

Browse files
authored
Fix sub-command log level (go-gitea#25537) (go-gitea#25553)
Backport go-gitea#25537 More fix for go-gitea#24981 * go-gitea#24981 Close go-gitea#22361, go-gitea#25552 * go-gitea#22361 * go-gitea#25552 There were many patches for Gitea's sub-commands to satisfy the facts: * Some sub-commands shouldn't output any log, otherwise the git protocol would be broken * Sometimes the users want to see "verbose" or "quiet" outputs That's a longstanding problem, and very fragile. This PR is only a quick patch for the problem. In the future, the sub-command system should be refactored to a clear solution. ---- Other changes: * Use `ReplaceAllWriters` to replace `RemoveAllWriters().AddWriters(writer)`, then it's an atomic operation. * Remove unnecessary `syncLevelInternal` calls, because `AddWriters/addWritersInternal` already calls it.
1 parent 102dcfa commit 0eb4ab4

11 files changed

+39
-18
lines changed

cmd/cmd.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,21 @@ func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {
106106
WriterOption: log.WriterConsoleOption{Stderr: out == os.Stderr},
107107
}
108108
writer := log.NewEventWriterConsole("console-default", writeMode)
109-
log.GetManager().GetLogger(log.DEFAULT).RemoveAllWriters().AddWriters(writer)
109+
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
110+
}
111+
112+
// PrepareConsoleLoggerLevel by default, use INFO level for console logger, but some sub-commands (for git/ssh protocol) shouldn't output any log to stdout.
113+
// Any log appears in git stdout pipe will break the git protocol, eg: client can't push and hangs forever.
114+
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error {
115+
return func(c *cli.Context) error {
116+
level := defaultLevel
117+
if c.Bool("quiet") || c.GlobalBoolT("quiet") {
118+
level = log.FATAL
119+
}
120+
if c.Bool("debug") || c.GlobalBool("debug") || c.Bool("verbose") || c.GlobalBool("verbose") {
121+
level = log.TRACE
122+
}
123+
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
124+
return nil
125+
}
110126
}

cmd/doctor.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
151151
log.FallbackErrorf("unable to create file log writer: %v", err)
152152
return
153153
}
154-
log.GetManager().GetLogger(log.DEFAULT).RemoveAllWriters().AddWriters(writer)
154+
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
155155
}
156156
}
157157

cmd/hook.go

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"time"
1616

1717
"code.gitea.io/gitea/modules/git"
18+
"code.gitea.io/gitea/modules/log"
1819
"code.gitea.io/gitea/modules/private"
1920
repo_module "code.gitea.io/gitea/modules/repository"
2021
"code.gitea.io/gitea/modules/setting"
@@ -32,6 +33,7 @@ var (
3233
Name: "hook",
3334
Usage: "Delegate commands to corresponding Git hooks",
3435
Description: "This should only be called by Git",
36+
Before: PrepareConsoleLoggerLevel(log.FATAL),
3537
Subcommands: []cli.Command{
3638
subcmdHookPreReceive,
3739
subcmdHookUpdate,

cmd/keys.go

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"strings"
1010

11+
"code.gitea.io/gitea/modules/log"
1112
"code.gitea.io/gitea/modules/private"
1213

1314
"github.com/urfave/cli"
@@ -17,6 +18,7 @@ import (
1718
var CmdKeys = cli.Command{
1819
Name: "keys",
1920
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
21+
Before: PrepareConsoleLoggerLevel(log.FATAL),
2022
Action: runKeys,
2123
Flags: []cli.Flag{
2224
cli.StringFlag{

cmd/serv.go

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ var CmdServ = cli.Command{
4444
Name: "serv",
4545
Usage: "This command should only be called by SSH shell",
4646
Description: "Serv provides access auth for repositories",
47+
Before: PrepareConsoleLoggerLevel(log.FATAL),
4748
Action: runServ,
4849
Flags: []cli.Flag{
4950
cli.BoolFlag{

cmd/web.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var CmdWeb = cli.Command{
3535
Usage: "Start Gitea web server",
3636
Description: `Gitea web server is the only thing you need to run,
3737
and it takes care of all the other things for you`,
38+
Before: PrepareConsoleLoggerLevel(log.INFO),
3839
Action: runWeb,
3940
Flags: []cli.Flag{
4041
cli.StringFlag{
@@ -206,11 +207,6 @@ func servePprof() {
206207
}
207208

208209
func runWeb(ctx *cli.Context) error {
209-
if ctx.Bool("verbose") {
210-
setupConsoleLogger(log.TRACE, log.CanColorStdout, os.Stdout)
211-
} else if ctx.Bool("quiet") {
212-
setupConsoleLogger(log.FATAL, log.CanColorStdout, os.Stdout)
213-
}
214210
defer func() {
215211
if panicked := recover(); panicked != nil {
216212
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))

main.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ func main() {
108108
cmd.CmdActions,
109109
}
110110

111-
// default configuration flags
111+
// shared configuration flags, they are for global and for each sub-command at the same time
112+
// eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed
113+
// keep in mind that the short flags like "-C", "-c" and "-w" are globally polluted, they can't be used for sub-commands anymore.
112114
globalFlags := []cli.Flag{
113115
cli.HelpFlag,
114116
cli.StringFlag{
@@ -128,9 +130,10 @@ func main() {
128130

129131
// Set the default to be equivalent to cmdWeb and add the default flags
130132
app.Flags = append(app.Flags, globalFlags...)
131-
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...)
133+
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...) // TODO: the web flags polluted the global flags, they are not really global flags
132134
app.Action = prepareWorkPathAndCustomConf(cmd.CmdWeb.Action)
133135
app.HideHelp = true // use our own help action to show helps (with more information like default config)
136+
app.Before = cmd.PrepareConsoleLoggerLevel(log.INFO)
134137
app.Commands = append(app.Commands, cmdHelp)
135138
for i := range app.Commands {
136139
prepareSubcommands(&app.Commands[i], globalFlags)

modules/log/logger_global.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ func SetConsoleLogger(loggerName, writerName string, level Level) {
7979
Colorize: CanColorStdout,
8080
WriterOption: WriterConsoleOption{},
8181
})
82-
GetManager().GetLogger(loggerName).RemoveAllWriters().AddWriters(writer)
82+
GetManager().GetLogger(loggerName).ReplaceAllWriters(writer)
8383
}

modules/log/logger_impl.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ func (l *LoggerImpl) removeWriterInternal(w EventWriter) {
9696
func (l *LoggerImpl) AddWriters(writer ...EventWriter) {
9797
l.eventWriterMu.Lock()
9898
defer l.eventWriterMu.Unlock()
99+
l.addWritersInternal(writer...)
100+
}
99101

102+
func (l *LoggerImpl) addWritersInternal(writer ...EventWriter) {
100103
for _, w := range writer {
101104
if old, ok := l.eventWriters[w.GetWriterName()]; ok {
102105
l.removeWriterInternal(old)
@@ -126,17 +129,16 @@ func (l *LoggerImpl) RemoveWriter(modeName string) error {
126129
return nil
127130
}
128131

129-
// RemoveAllWriters removes all writers from the logger, non-shared writers are closed and flushed
130-
func (l *LoggerImpl) RemoveAllWriters() *LoggerImpl {
132+
// ReplaceAllWriters replaces all writers from the logger, non-shared writers are closed and flushed
133+
func (l *LoggerImpl) ReplaceAllWriters(writer ...EventWriter) {
131134
l.eventWriterMu.Lock()
132135
defer l.eventWriterMu.Unlock()
133136

134137
for _, w := range l.eventWriters {
135138
l.removeWriterInternal(w)
136139
}
137140
l.eventWriters = map[string]EventWriter{}
138-
l.syncLevelInternal()
139-
return l
141+
l.addWritersInternal(writer...)
140142
}
141143

142144
// DumpWriters dumps the writers as a JSON map, it's used for debugging and display purposes.
@@ -161,7 +163,7 @@ func (l *LoggerImpl) DumpWriters() map[string]any {
161163

162164
// Close closes the logger, non-shared writers are closed and flushed
163165
func (l *LoggerImpl) Close() {
164-
l.RemoveAllWriters()
166+
l.ReplaceAllWriters()
165167
l.ctxCancel()
166168
}
167169

@@ -233,7 +235,6 @@ func NewLoggerWithWriters(ctx context.Context, name string, writer ...EventWrite
233235
l.ctx, l.ctxCancel = newProcessTypedContext(ctx, "Logger: "+name)
234236
l.LevelLogger = BaseLoggerToGeneralLogger(l)
235237
l.eventWriters = map[string]EventWriter{}
236-
l.syncLevelInternal()
237238
l.AddWriters(writer...)
238239
return l
239240
}

modules/log/manager_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestSharedWorker(t *testing.T) {
2323
loggerTest := m.GetLogger("test")
2424
loggerTest.AddWriters(w)
2525
loggerTest.Info("msg-1")
26-
loggerTest.RemoveAllWriters() // the shared writer is not closed here
26+
loggerTest.ReplaceAllWriters() // the shared writer is not closed here
2727
loggerTest.Info("never seen")
2828

2929
// the shared writer can still be used later

modules/setting/log.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ func initLoggerByName(manager *log.LoggerManager, rootCfg ConfigProvider, logger
244244
eventWriters = append(eventWriters, eventWriter)
245245
}
246246

247-
manager.GetLogger(loggerName).RemoveAllWriters().AddWriters(eventWriters...)
247+
manager.GetLogger(loggerName).ReplaceAllWriters(eventWriters...)
248248
}
249249

250250
func InitSQLLoggersForCli(level log.Level) {

0 commit comments

Comments
 (0)