Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions tail.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/ActiveState/tail/util"
"github.com/ActiveState/tail/watch"
"io"
"io/ioutil"
"launchpad.net/tomb"
"log"
"os"
Expand Down Expand Up @@ -47,6 +48,10 @@ type Config struct {
// Generic IO
Follow bool // Continue looking for new lines (tail -f)
MaxLineSize int // If non-zero, split longer lines into multiple lines

// Logger, when nil, is set to tail.DefaultLogger
// To disable logging: set field to tail.DiscardingLogger
Logger *log.Logger
}

type Tail struct {
Expand All @@ -63,6 +68,13 @@ type Tail struct {
tomb.Tomb // provides: Done, Kill, Dying
}

var (
// DefaultLogger is used when Config.Logger == nil
DefaultLogger = log.New(os.Stderr, "", log.LstdFlags)
// DiscardingLogger can be used to disable logging output
DiscardingLogger = log.New(ioutil.Discard, "", 0)
)

// TailFile begins tailing the file. Output stream is made available
// via the `Tail.Lines` channel. To handle errors during tailing,
// invoke the `Wait` or `Err` method after finishing reading from the
Expand All @@ -75,7 +87,13 @@ func TailFile(filename string, config Config) (*Tail, error) {
t := &Tail{
Filename: filename,
Lines: make(chan *Line),
Config: config}
Config: config,
}

// when Logger was not specified in config, use default logger
if t.Logger == nil {
t.Logger = log.New(os.Stderr, "", log.LstdFlags)
}

t.rateMon = new(RateMonitor)

Expand Down Expand Up @@ -135,7 +153,7 @@ func (tail *Tail) reopen() error {
tail.file, err = os.Open(tail.Filename)
if err != nil {
if os.IsNotExist(err) {
log.Printf("Waiting for %s to appear...", tail.Filename)
tail.Logger.Printf("Waiting for %s to appear...", tail.Filename)
if err := tail.watcher.BlockUntilExists(&tail.Tomb); err != nil {
if err == tomb.ErrDying {
return err
Expand Down Expand Up @@ -174,7 +192,7 @@ func (tail *Tail) tailFileSync() {
// Seek to requested location on first open of the file.
if tail.Location != nil {
_, err := tail.file.Seek(tail.Location.Offset, tail.Location.Whence)
// log.Printf("Seeked %s - %+v\n", tail.Filename, tail.Location)
tail.Logger.Printf("Seeked %s - %+v\n", tail.Filename, tail.Location)
if err != nil {
tail.Killf("Seek error on %s: %s", tail.Filename, err)
return
Expand Down Expand Up @@ -257,24 +275,24 @@ func (tail *Tail) waitForChanges() error {
tail.changes = nil
if tail.ReOpen {
// XXX: we must not log from a library.
log.Printf("Re-opening moved/deleted file %s ...", tail.Filename)
tail.Logger.Printf("Re-opening moved/deleted file %s ...", tail.Filename)
if err := tail.reopen(); err != nil {
return err
}
log.Printf("Successfully reopened %s", tail.Filename)
tail.Logger.Printf("Successfully reopened %s", tail.Filename)
tail.reader = bufio.NewReader(tail.file)
return nil
} else {
log.Printf("Stopping tail as file no longer exists: %s", tail.Filename)
tail.Logger.Printf("Stopping tail as file no longer exists: %s", tail.Filename)
return ErrStop
}
case <-tail.changes.Truncated:
// Always reopen truncated files (Follow is true)
log.Printf("Re-opening truncated file %s ...", tail.Filename)
tail.Logger.Printf("Re-opening truncated file %s ...", tail.Filename)
if err := tail.reopen(); err != nil {
return err
}
log.Printf("Successfully reopened truncated %s", tail.Filename)
tail.Logger.Printf("Successfully reopened truncated %s", tail.Filename)
tail.reader = bufio.NewReader(tail.file)
return nil
case <-tail.Dying():
Expand All @@ -300,7 +318,7 @@ func (tail *Tail) sendLine(line []byte) bool {
tail.Lines <- &Line{line, now, nil}
rate := tail.rateMon.Tick(nowUnix)
if tail.LimitRate > 0 && rate > tail.LimitRate {
log.Printf("Rate limit (%v < %v) reached on file (%v); entering 1s cooloff period.\n",
tail.Logger.Printf("Rate limit (%v < %v) reached on file (%v); entering 1s cooloff period.\n",
tail.LimitRate,
rate,
tail.Filename)
Expand Down