Skip to content

Commit cb9292a

Browse files
authored
Merge pull request #349 from pohly/init-flags-concurrency
InitFlags concurrency fix
2 parents 02fe323 + 28f7906 commit cb9292a

File tree

2 files changed

+74
-32
lines changed

2 files changed

+74
-32
lines changed

klog.go

+29-32
Original file line numberDiff line numberDiff line change
@@ -396,45 +396,48 @@ type flushSyncWriter interface {
396396
io.Writer
397397
}
398398

399-
// init sets up the defaults.
399+
var logging loggingT
400+
var commandLine flag.FlagSet
401+
402+
// init sets up the defaults and creates command line flags.
400403
func init() {
404+
commandLine.StringVar(&logging.logDir, "log_dir", "", "If non-empty, write log files in this directory (no effect when -logtostderr=true)")
405+
commandLine.StringVar(&logging.logFile, "log_file", "", "If non-empty, use this log file (no effect when -logtostderr=true)")
406+
commandLine.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", 1800,
407+
"Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. "+
408+
"If the value is 0, the maximum file size is unlimited.")
409+
commandLine.BoolVar(&logging.toStderr, "logtostderr", true, "log to standard error instead of files")
410+
commandLine.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files (no effect when -logtostderr=true)")
411+
logging.setVState(0, nil, false)
412+
commandLine.Var(&logging.verbosity, "v", "number for the log level verbosity")
413+
commandLine.BoolVar(&logging.addDirHeader, "add_dir_header", false, "If true, adds the file directory to the header of the log messages")
414+
commandLine.BoolVar(&logging.skipHeaders, "skip_headers", false, "If true, avoid header prefixes in the log messages")
415+
commandLine.BoolVar(&logging.oneOutput, "one_output", false, "If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)")
416+
commandLine.BoolVar(&logging.skipLogHeaders, "skip_log_headers", false, "If true, avoid headers when opening log files (no effect when -logtostderr=true)")
401417
logging.stderrThreshold = severityValue{
402418
Severity: severity.ErrorLog, // Default stderrThreshold is ERROR.
403419
}
404-
logging.setVState(0, nil, false)
405-
logging.logDir = ""
406-
logging.logFile = ""
407-
logging.logFileMaxSizeMB = 1800
408-
logging.toStderr = true
409-
logging.alsoToStderr = false
410-
logging.skipHeaders = false
411-
logging.addDirHeader = false
412-
logging.skipLogHeaders = false
413-
logging.oneOutput = false
420+
commandLine.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false)")
421+
commandLine.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
422+
commandLine.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
423+
424+
logging.settings.contextualLoggingEnabled = true
414425
logging.flushD = newFlushDaemon(logging.lockAndFlushAll, nil)
415426
}
416427

417428
// InitFlags is for explicitly initializing the flags.
429+
// It may get called repeatedly for different flagsets, but not
430+
// twice for the same one. May get called concurrently
431+
// to other goroutines using klog. However, only some flags
432+
// may get set concurrently (see implementation).
418433
func InitFlags(flagset *flag.FlagSet) {
419434
if flagset == nil {
420435
flagset = flag.CommandLine
421436
}
422437

423-
flagset.StringVar(&logging.logDir, "log_dir", logging.logDir, "If non-empty, write log files in this directory (no effect when -logtostderr=true)")
424-
flagset.StringVar(&logging.logFile, "log_file", logging.logFile, "If non-empty, use this log file (no effect when -logtostderr=true)")
425-
flagset.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", logging.logFileMaxSizeMB,
426-
"Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. "+
427-
"If the value is 0, the maximum file size is unlimited.")
428-
flagset.BoolVar(&logging.toStderr, "logtostderr", logging.toStderr, "log to standard error instead of files")
429-
flagset.BoolVar(&logging.alsoToStderr, "alsologtostderr", logging.alsoToStderr, "log to standard error as well as files (no effect when -logtostderr=true)")
430-
flagset.Var(&logging.verbosity, "v", "number for the log level verbosity")
431-
flagset.BoolVar(&logging.addDirHeader, "add_dir_header", logging.addDirHeader, "If true, adds the file directory to the header of the log messages")
432-
flagset.BoolVar(&logging.skipHeaders, "skip_headers", logging.skipHeaders, "If true, avoid header prefixes in the log messages")
433-
flagset.BoolVar(&logging.oneOutput, "one_output", logging.oneOutput, "If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)")
434-
flagset.BoolVar(&logging.skipLogHeaders, "skip_log_headers", logging.skipLogHeaders, "If true, avoid headers when opening log files (no effect when -logtostderr=true)")
435-
flagset.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false)")
436-
flagset.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
437-
flagset.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
438+
commandLine.VisitAll(func(f *flag.Flag) {
439+
flagset.Var(f.Value, f.Name, f.Usage)
440+
})
438441
}
439442

440443
// Flush flushes all pending log I/O.
@@ -549,12 +552,6 @@ type loggingT struct {
549552
vmap map[uintptr]Level
550553
}
551554

552-
var logging = loggingT{
553-
settings: settings{
554-
contextualLoggingEnabled: true,
555-
},
556-
}
557-
558555
// setVState sets a consistent state for V logging.
559556
// l.mu is held.
560557
func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) {

klog_test.go

+45
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,9 @@ func TestFileSizeCheck(t *testing.T) {
764764
}
765765

766766
func TestInitFlags(t *testing.T) {
767+
defer CaptureState().Restore()
768+
setFlags()
769+
767770
fs1 := flag.NewFlagSet("test1", flag.PanicOnError)
768771
InitFlags(fs1)
769772
fs1.Set("log_dir", "/test1")
@@ -779,6 +782,48 @@ func TestInitFlags(t *testing.T) {
779782
}
780783
}
781784

785+
func TestCommandLine(t *testing.T) {
786+
var fs flag.FlagSet
787+
InitFlags(&fs)
788+
789+
expectedFlags := ` -add_dir_header
790+
If true, adds the file directory to the header of the log messages
791+
-alsologtostderr
792+
log to standard error as well as files (no effect when -logtostderr=true)
793+
-log_backtrace_at value
794+
when logging hits line file:N, emit a stack trace
795+
-log_dir string
796+
If non-empty, write log files in this directory (no effect when -logtostderr=true)
797+
-log_file string
798+
If non-empty, use this log file (no effect when -logtostderr=true)
799+
-log_file_max_size uint
800+
Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
801+
-logtostderr
802+
log to standard error instead of files (default true)
803+
-one_output
804+
If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
805+
-skip_headers
806+
If true, avoid header prefixes in the log messages
807+
-skip_log_headers
808+
If true, avoid headers when opening log files (no effect when -logtostderr=true)
809+
-stderrthreshold value
810+
logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
811+
-v value
812+
number for the log level verbosity
813+
-vmodule value
814+
comma-separated list of pattern=N settings for file-filtered logging
815+
`
816+
817+
var output bytes.Buffer
818+
fs.SetOutput(&output)
819+
fs.PrintDefaults()
820+
actualFlags := output.String()
821+
822+
if expectedFlags != actualFlags {
823+
t.Fatalf("Command line changed.\nExpected:\n%q\nActual:\n%q\n", expectedFlags, actualFlags)
824+
}
825+
}
826+
782827
func TestInfoObjectRef(t *testing.T) {
783828
defer CaptureState().Restore()
784829
setFlags()

0 commit comments

Comments
 (0)