Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch from gotail library to a notify or polling reader increases read performance while following by 10-25x
- Loading branch information
Showing
10 changed files
with
638 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package followreader | ||
|
||
import ( | ||
"io" | ||
) | ||
|
||
type FollowReader interface { | ||
io.ReadCloser | ||
Drain() error | ||
} | ||
|
||
func New(filename string, reopen, poll bool) (FollowReader, error) { | ||
if poll { | ||
return NewPolling(filename, reopen) | ||
} | ||
return NewNotify(filename, reopen) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package followreader | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"sync" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
// reads data and asserts all reads successful | ||
func assertSequentialReads(t *testing.T, tail FollowReader, reads int) { | ||
buf := make([]byte, 100) | ||
for i := 0; i < reads; i++ { | ||
n, err := tail.Read(buf) | ||
assert.NoError(t, err) | ||
assert.NotZero(t, n) | ||
} | ||
} | ||
|
||
// Helper to create a file and write random data at random intervals | ||
type testAppendingFile struct { | ||
f *os.File | ||
Line []byte | ||
|
||
stop chan<- bool | ||
wg sync.WaitGroup | ||
} | ||
|
||
func CreateAppendingFromFile(filename string) *testAppendingFile { | ||
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return createAppendingFileEx(f) | ||
} | ||
|
||
func CreateAppendingTempFile() *testAppendingFile { | ||
f, err := ioutil.TempFile("", "go-test-") | ||
if err != nil { | ||
panic(err) | ||
} | ||
return createAppendingFileEx(f) | ||
} | ||
|
||
func createAppendingFileEx(f *os.File) *testAppendingFile { | ||
ret := &testAppendingFile{ | ||
f: f, | ||
Line: []byte("test file 123\n"), | ||
wg: sync.WaitGroup{}, | ||
} | ||
|
||
ret.startWriteRandomData(1 * time.Millisecond) | ||
|
||
return ret | ||
} | ||
|
||
func (s *testAppendingFile) Name() string { | ||
return s.f.Name() | ||
} | ||
|
||
func (s *testAppendingFile) startWriteRandomData(interval time.Duration) { | ||
stop := make(chan bool) | ||
s.stop = stop | ||
s.wg.Add(1) | ||
|
||
go func() { | ||
defer s.wg.Done() | ||
for { | ||
select { | ||
case <-stop: | ||
return | ||
case <-time.After(interval): | ||
s.f.Write(s.Line) | ||
} | ||
} | ||
}() | ||
} | ||
|
||
// Stop writing to the file | ||
func (s *testAppendingFile) Stop() { | ||
if s.stop != nil { | ||
s.stop <- true | ||
s.wg.Wait() | ||
s.stop = nil | ||
} | ||
} | ||
|
||
// Close and stop writing to the file | ||
func (s *testAppendingFile) Close() { | ||
s.Stop() | ||
err := s.f.Close() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
err = os.Remove(s.f.Name()) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
Oops, something went wrong.