2
0

refactor internally a little to clean up the code. Make the main example a real example so we make sure it compiles

This commit is contained in:
Nate Finch
2014-06-16 12:55:21 -04:00
parent 03e9c77b42
commit fc6790d66f
3 changed files with 75 additions and 71 deletions
+16 -12
View File
@@ -11,22 +11,26 @@ to which logs are written.
Lumberjack plays well with any logger that can write to an io.Writer, Lumberjack plays well with any logger that can write to an io.Writer,
including the standard library's log package. including the standard library's log package.
For example, to use lumberjack with the std lib's log package, just pass it
into the SetOutput function when your application starts:
log.SetOutput(&lumberjack.Logger{
Dir: "/var/log/myapp/"
NameFormat: time.RFC822+".log",
MaxSize: lumberjack.Gigabyte,
MaxBackups: 3,
MaxAge: lumberjack.Week * 4,
))
Lumberjack assumes that only one process is writing to the output files. Lumberjack assumes that only one process is writing to the output files.
Using the same lumberjack configuration from multiple processes on the same Using the same lumberjack configuration from multiple processes on the same
machine will result in improper behavior. machine will result in improper behavior.
#### Example
To use lumberjack with the standard library's log package, just pass it into the
SetOutput function when your application starts.
Code:
```go
log.SetOutput(&lumberjack.Logger{
Dir: "/var/log/myapp/",
NameFormat: time.RFC822 + ".log",
MaxSize: lumberjack.Gigabyte,
MaxBackups: 3,
MaxAge: lumberjack.Week * 4,
})
```
+13
View File
@@ -7,6 +7,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"time"
"github.com/natefinch/lumberjack" "github.com/natefinch/lumberjack"
) )
@@ -25,3 +26,15 @@ func ExampleLogger_Rotate() {
} }
}() }()
} }
// To use lumberjack with the standard library's log package, just pass it into
// the SetOutput function when your application starts.
func Example() {
log.SetOutput(&lumberjack.Logger{
Dir: "/var/log/myapp/",
NameFormat: time.RFC822 + ".log",
MaxSize: lumberjack.Gigabyte,
MaxBackups: 3,
MaxAge: lumberjack.Week * 4,
})
}
+46 -59
View File
@@ -8,17 +8,6 @@
// Lumberjack plays well with any logger that can write to an io.Writer, // Lumberjack plays well with any logger that can write to an io.Writer,
// including the standard library's log package. // including the standard library's log package.
// //
// For example, to use lumberjack with the std lib's log package, just pass it
// into the SetOutput function when your application starts:
//
// log.SetOutput(&lumberjack.Logger{
// Dir: "/var/log/myapp/"
// NameFormat: time.RFC822+".log",
// MaxSize: lumberjack.Gigabyte,
// MaxBackups: 3,
// MaxAge: lumberjack.Week * 4,
// ))
//
// Lumberjack assumes that only one process is writing to the output files. // Lumberjack assumes that only one process is writing to the output files.
// Using the same lumberjack configuration from multiple processes on the same // Using the same lumberjack configuration from multiple processes on the same
// machine will result in improper behavior. // machine will result in improper behavior.
@@ -123,51 +112,46 @@ var currentTime = time.Now
func (l *Logger) Write(p []byte) (n int, err error) { func (l *Logger) Write(p []byte) (n int, err error) {
l.mu.Lock() l.mu.Lock()
defer l.mu.Unlock() defer l.mu.Unlock()
writeLen := int64(len(p)) writeLen := int64(len(p))
if writeLen > l.max() { if writeLen > l.max() {
return 0, fmt.Errorf( return 0, fmt.Errorf(
"write length %d exceeds maximum file size %d", writeLen, l.max(), "write length %d exceeds maximum file size %d", writeLen, l.max(),
) )
} }
f := l.file if l.size+writeLen > l.max() {
rotate := l.size+writeLen > l.max() if err := l.rotate(); err != nil {
if f == nil {
if f, err = l.openExistingOrNew(len(p)); err != nil {
return 0, err return 0, err
} }
} else if rotate { }
if f, err = l.openNew(); err != nil { if l.file == nil {
if err = l.openExistingOrNew(len(p)); err != nil {
return 0, err return 0, err
} }
} }
n, err = f.Write(p) n, err = l.file.Write(p)
l.size += int64(n) l.size += int64(n)
if l.file != nil && rotate {
l.file.Close()
}
l.file = f
if rotate {
if err := l.cleanup(); err != nil {
return 0, err
}
}
return n, err return n, err
} }
// Close implements io.Closer, and closes the current logfile. // Close implements io.Closer, and closes the current logfile.
func (l *Logger) Close() error { func (l *Logger) Close() error {
l.mu.Lock() l.mu.Lock()
defer l.mu.Unlock() err := l.close()
if l.file != nil { l.mu.Unlock()
err := l.file.Close() return err
l.file = nil }
return err
// close closes the file if it is open.
func (l *Logger) close() error {
if l.file == nil {
return nil
} }
return nil err := l.file.Close()
l.file = nil
return err
} }
// Rotate causes Logger to close the existing log file and immediately create a // Rotate causes Logger to close the existing log file and immediately create a
@@ -177,47 +161,49 @@ func (l *Logger) Close() error {
// to the normal rules. // to the normal rules.
func (l *Logger) Rotate() error { func (l *Logger) Rotate() error {
l.mu.Lock() l.mu.Lock()
defer l.mu.Unlock() err := l.rotate()
if l.file != nil { l.mu.Unlock()
if err := l.file.Close(); err != nil { return err
return err }
}
l.file = nil // rotate closes the current file, if any, opens a new file, and then calls
// cleanup.
func (l *Logger) rotate() error {
if err := l.close(); err != nil {
return nil
} }
var err error if err := l.openNew(); err != nil {
l.file, err = l.openNew()
if err != nil {
return err return err
} }
return l.cleanup() return l.cleanup()
} }
// openNew opens a new log file for writing. // openNew opens a new log file for writing.
func (l *Logger) openNew() (*os.File, error) { func (l *Logger) openNew() error {
err := os.MkdirAll(l.dir(), 0744) err := os.MkdirAll(l.dir(), 0744)
if err != nil { if err != nil {
return nil, fmt.Errorf("can't make directories for new logfile: %s", err) return fmt.Errorf("can't make directories for new logfile: %s", err)
} }
filename := l.genFilename() f, err := os.OpenFile(l.genFilename(), os.O_CREATE|os.O_WRONLY, 0644)
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil { if err != nil {
return nil, fmt.Errorf("can't open new logfile: %s", err) return fmt.Errorf("can't open new logfile: %s", err)
} }
info, err := f.Stat() info, err := f.Stat()
if err != nil { if err != nil {
// can't really do anything if close fails here // can't really do anything if close fails here
_ = f.Close() _ = f.Close()
return nil, fmt.Errorf("can't get size of new logfile: %s", err) return fmt.Errorf("can't get size of new logfile: %s", err)
} }
l.size = info.Size() l.size = info.Size()
return f, nil l.file = f
return nil
} }
// openExistingOrNew opens the most recently modified logfile in the log // openExistingOrNew opens the most recently modified logfile in the log
// directory, if the current write would not put it over MaxSize. If there is // directory, if the current write would not put it over MaxSize. If there is
// no such file or the write would put it over the MaxSize, a new file is // no such file or the write would put it over the MaxSize, a new file is
// created. // created.
func (l *Logger) openExistingOrNew(writeLen int) (*os.File, error) { func (l *Logger) openExistingOrNew(writeLen int) error {
if l.Dir == "" && l.NameFormat == "" { if l.Dir == "" && l.NameFormat == "" {
return l.openNew() return l.openNew()
} }
@@ -226,25 +212,26 @@ func (l *Logger) openExistingOrNew(writeLen int) (*os.File, error) {
return l.openNew() return l.openNew()
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("can't read files in log file directory: %s", err) return fmt.Errorf("can't read files in log file directory: %s", err)
} }
sort.Sort(byFormatTime{files, l.format()}) sort.Sort(byFormatTime{files, l.format()})
for _, f := range files { for _, info := range files {
if f.IsDir() { if info.IsDir() {
continue continue
} }
if !l.isLogFile(f) { if !l.isLogFile(info) {
continue continue
} }
// the first file we find that matches our pattern will be the most // the first file we find that matches our pattern will be the most
// recently modified log file. // recently modified log file.
if f.Size()+int64(writeLen) < l.max() { if info.Size()+int64(writeLen) < l.max() {
filename := filepath.Join(l.dir(), f.Name()) filename := filepath.Join(l.dir(), info.Name())
file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644) file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644)
if err == nil { if err == nil {
return file, nil l.file = file
return nil
} }
// if we fail to open the old log file for some reason, just ignore // if we fail to open the old log file for some reason, just ignore
// it and open a new log file. // it and open a new log file.