Skip to content

Commit

Permalink
Add a log-file-max-size flag to fix large logfile (>1.8GB) truncation.
Browse files Browse the repository at this point in the history
  • Loading branch information
yuwenma committed Apr 9, 2019
1 parent aaeac2f commit e025e58
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
20 changes: 18 additions & 2 deletions klog.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@ func InitFlags(flagset *flag.FlagSet) {
}
flagset.StringVar(&logging.logDir, "log_dir", "", "If non-empty, write log files in this directory")
flagset.StringVar(&logging.logFile, "log_file", "", "If non-empty, use this log file")
flagset.Uint64Var(&logging.logFileMaxSize, "log_file_max_size", 0,
"Defines the maximum size a log file can grow to. Unit is megabytes. " +
"When giving a zero, there's no file size limitations.")
flagset.BoolVar(&logging.toStderr, "logtostderr", true, "log to standard error instead of files")
flagset.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files")
flagset.Var(&logging.verbosity, "v", "number for the log level verbosity")
Expand Down Expand Up @@ -472,6 +475,10 @@ type loggingT struct {
// with the log-dir option.
logFile string

// When logFile is specified, this limiter makes sure the logFile won't exceeds a certain size. When exceeds, the
// logFile will be cleaned up. If this value is negative, no size limitation will be applied to logFile.
logFileMaxSize uint64

// If true, do not add the prefix headers, useful when used with SetOutput
skipHeaders bool

Expand Down Expand Up @@ -874,8 +881,17 @@ func (sb *syncBuffer) Sync() error {
return sb.file.Sync()
}

func IsFileReachedMaxSize(bufferSize uint64) bool {
if logging.logFile != "" {
// If logFileMaxSize is zero, we don't have limitations on the log size.
return logging.logFileMaxSize > 0 && bufferSize >= logging.logFileMaxSize
}
// If "log_file" flag is not specified, the log files will be cleaned up when reaches a fixed size.
return bufferSize >= MaxSize
}

func (sb *syncBuffer) Write(p []byte) (n int, err error) {
if sb.nbytes+uint64(len(p)) >= MaxSize {
if IsFileReachedMaxSize(sb.nbytes+uint64(len(p))) {
if err := sb.rotateFile(time.Now(), false); err != nil {
sb.logger.exit(err)
}
Expand All @@ -890,7 +906,7 @@ func (sb *syncBuffer) Write(p []byte) (n int, err error) {

// rotateFile closes the syncBuffer's file and starts a new one.
// The startup argument indicates whether this is the initial startup of klog.
// If startup is true, existing files are opened for apending instead of truncated.
// If startup is true, existing files are opened for appending instead of truncated.
func (sb *syncBuffer) rotateFile(now time.Time, startup bool) error {
if sb.file != nil {
sb.Flush()
Expand Down
2 changes: 1 addition & 1 deletion klog_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ var onceLogDirs sync.Once
// successfully, create also attempts to update the symlink for that tag, ignoring
// errors.
// The startup argument indicates whether this is the initial startup of klog.
// If startup is true, existing files are opened for apending instead of truncated.
// If startup is true, existing files are opened for appending instead of truncated.
func create(tag string, t time.Time, startup bool) (f *os.File, filename string, err error) {
if logging.logFile != "" {
f, err := openOrCreate(logging.logFile, startup)
Expand Down
47 changes: 47 additions & 0 deletions klog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,50 @@ func BenchmarkHeader(b *testing.B) {
logging.putBuffer(buf)
}
}

// Test the logic on checking log size limitation.
func TestLogFileReachesMaxSize(t *testing.T) {
setFlags()
testData := map[string] struct{
testLogFile string
testLogFileMaxSize uint64
testCurrentSize uint64
expectedResult bool
}{
"logFile not specified, exceeds max size": {
testLogFile: "",
testLogFileMaxSize: 1,
testCurrentSize: 1024 * 1024 * 2000, //exceeds the maxSize
expectedResult: true,
},

"logFile not specified, not exceeds max size": {
testLogFile: "",
testLogFileMaxSize: 1,
testCurrentSize: 1024 * 1024 * 1000, // smaller than the maxSize
expectedResult: false,
},
"logFile specified, exceeds max size": {
testLogFile: "/tmp/test.log",
testLogFileMaxSize: 1024 * 1024 * 500,
testCurrentSize: 1024 * 1024 * 1000, //exceeds the logFileMaxSize
expectedResult: true,
},
"logFile specified, not exceeds max size": {
testLogFile: "/tmp/test.log",
testLogFileMaxSize: 1024 * 1024 * 500,
testCurrentSize: 1024 * 1024 * 300, //exceeds the logFileMaxSize
expectedResult: false,
},
}

for name, test := range testData {
logging.logFile = test.testLogFile
logging.logFileMaxSize = test.testLogFileMaxSize
actualResult := IsFileReachedMaxSize(test.testCurrentSize)
if test.expectedResult != actualResult {
t.Fatalf("Error on test case '%v': Was expecting result equals %v, got %v",
name, test.expectedResult, actualResult)
}
}
}

0 comments on commit e025e58

Please sign in to comment.