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,
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.
Using the same lumberjack configuration from multiple processes on the same
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/signal"
"syscall"
"time"
"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,
// 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.
// Using the same lumberjack configuration from multiple processes on the same
// machine will result in improper behavior.
@@ -123,51 +112,46 @@ var currentTime = time.Now
func (l *Logger) Write(p []byte) (n int, err error) {
l.mu.Lock()
defer l.mu.Unlock()
writeLen := int64(len(p))
if writeLen > l.max() {
return 0, fmt.Errorf(
"write length %d exceeds maximum file size %d", writeLen, l.max(),
)
}
f := l.file
rotate := l.size+writeLen > l.max()
if f == nil {
if f, err = l.openExistingOrNew(len(p)); err != nil {
if l.size+writeLen > l.max() {
if err := l.rotate(); err != nil {
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
}
}
n, err = f.Write(p)
n, err = l.file.Write(p)
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
}
// Close implements io.Closer, and closes the current logfile.
func (l *Logger) Close() error {
l.mu.Lock()
defer l.mu.Unlock()
if l.file != nil {
err := l.file.Close()
l.file = nil
return err
err := l.close()
l.mu.Unlock()
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
@@ -177,47 +161,49 @@ func (l *Logger) Close() error {
// to the normal rules.
func (l *Logger) Rotate() error {
l.mu.Lock()
defer l.mu.Unlock()
if l.file != nil {
if err := l.file.Close(); err != nil {
return err
}
l.file = nil
err := l.rotate()
l.mu.Unlock()
return err
}
// 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
l.file, err = l.openNew()
if err != nil {
if err := l.openNew(); err != nil {
return err
}
return l.cleanup()
}
// 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)
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(filename, os.O_CREATE|os.O_WRONLY, 0644)
f, err := os.OpenFile(l.genFilename(), os.O_CREATE|os.O_WRONLY, 0644)
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()
if err != nil {
// can't really do anything if close fails here
_ = 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()
return f, nil
l.file = f
return nil
}
// openExistingOrNew opens the most recently modified logfile in the log
// 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
// created.
func (l *Logger) openExistingOrNew(writeLen int) (*os.File, error) {
func (l *Logger) openExistingOrNew(writeLen int) error {
if l.Dir == "" && l.NameFormat == "" {
return l.openNew()
}
@@ -226,25 +212,26 @@ func (l *Logger) openExistingOrNew(writeLen int) (*os.File, error) {
return l.openNew()
}
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()})
for _, f := range files {
if f.IsDir() {
for _, info := range files {
if info.IsDir() {
continue
}
if !l.isLogFile(f) {
if !l.isLogFile(info) {
continue
}
// the first file we find that matches our pattern will be the most
// recently modified log file.
if f.Size()+int64(writeLen) < l.max() {
filename := filepath.Join(l.dir(), f.Name())
if info.Size()+int64(writeLen) < l.max() {
filename := filepath.Join(l.dir(), info.Name())
file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644)
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
// it and open a new log file.