mirror of
https://github.com/kemko/nomad.git
synced 2026-01-09 20:05:42 +03:00
Implemented a method to purge files
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -15,6 +16,8 @@ const (
|
||||
bufSize = 32 * 1024
|
||||
)
|
||||
|
||||
// LogRotator rotates files for a buffer and retains only the last N rotated
|
||||
// files
|
||||
type LogRotator struct {
|
||||
maxFiles int
|
||||
fileSize int64
|
||||
@@ -25,6 +28,7 @@ type LogRotator struct {
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// NewLogRotator configures and returns a new LogRotator
|
||||
func NewLogRotator(path string, fileName string, maxFiles int, fileSize int64, logger *log.Logger) (*LogRotator, error) {
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
@@ -55,6 +59,8 @@ func NewLogRotator(path string, fileName string, maxFiles int, fileSize int64, l
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start reads from a Reader and writes them to files and rotates them when the
|
||||
// size of the file becomes equal to the max size configured
|
||||
func (l *LogRotator) Start(r io.Reader) error {
|
||||
buf := make([]byte, bufSize)
|
||||
for {
|
||||
@@ -111,3 +117,32 @@ func (l *LogRotator) Start(r io.Reader) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PurgeOldFiles removes older files and keeps only the last N files rotated for
|
||||
// a file
|
||||
func (l *LogRotator) PurgeOldFiles() {
|
||||
fIndexes := make([]int, l.maxFiles)
|
||||
files, err := ioutil.ReadDir(l.path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count := 0
|
||||
for _, f := range files {
|
||||
if strings.HasPrefix(f.Name(), l.fileName) {
|
||||
fileIdx := strings.TrimPrefix(f.Name(), fmt.Sprintf("%s.", l.fileName))
|
||||
n, err := strconv.Atoi(fileIdx)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if count == l.maxFiles {
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(fIndexes)))
|
||||
fname := filepath.Join(l.path, fmt.Sprintf("%s.%d", l.fileName, fIndexes[count-1]))
|
||||
l.logger.Printf("[INFO] removing file: %v", fname)
|
||||
os.RemoveAll(fname)
|
||||
count -= 1
|
||||
}
|
||||
fIndexes[count] = n
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
var (
|
||||
logger = log.New(os.Stdout, "", log.LstdFlags)
|
||||
path = "/tmp/logrotator"
|
||||
)
|
||||
|
||||
func TestLogRotator_IncorrectPath(t *testing.T) {
|
||||
@@ -23,7 +24,6 @@ func TestLogRotator_IncorrectPath(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogRotator_FindCorrectIndex(t *testing.T) {
|
||||
path := "/tmp/tmplogrator"
|
||||
if err := os.Mkdir(path, os.ModeDir|os.ModePerm); err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
}
|
||||
@@ -49,7 +49,6 @@ func TestLogRotator_FindCorrectIndex(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogRotator_AppendToCurrentFile(t *testing.T) {
|
||||
path := "/tmp/tmplogrator"
|
||||
defer os.RemoveAll(path)
|
||||
if err := os.Mkdir(path, os.ModeDir|os.ModePerm); err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
@@ -84,7 +83,6 @@ func TestLogRotator_AppendToCurrentFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogRotator_RotateFiles(t *testing.T) {
|
||||
path := "/tmp/tmplogrator"
|
||||
defer os.RemoveAll(path)
|
||||
if err := os.Mkdir(path, os.ModeDir|os.ModePerm); err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
@@ -127,7 +125,6 @@ func TestLogRotator_RotateFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogRotator_StartFromEmptyDir(t *testing.T) {
|
||||
path := "/tmp/tmplogrator"
|
||||
defer os.RemoveAll(path)
|
||||
if err := os.Mkdir(path, os.ModeDir|os.ModePerm); err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
@@ -159,7 +156,6 @@ func TestLogRotator_StartFromEmptyDir(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogRotator_SetPathAsFile(t *testing.T) {
|
||||
path := "/tmp/tmplogrator"
|
||||
defer os.RemoveAll(path)
|
||||
if _, err := os.Create(path); err != nil {
|
||||
t.Fatalf("test setup problem: %v", err)
|
||||
@@ -172,7 +168,6 @@ func TestLogRotator_SetPathAsFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogRotator_ExcludeDirs(t *testing.T) {
|
||||
path := "/tmp/tmplogrator"
|
||||
defer os.RemoveAll(path)
|
||||
if err := os.Mkdir(path, os.ModeDir|os.ModePerm); err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
@@ -196,7 +191,7 @@ func TestLogRotator_ExcludeDirs(t *testing.T) {
|
||||
t.Fatalf("Failure in logrotator start %v", err)
|
||||
}
|
||||
|
||||
finfo, err := os.Stat("/tmp/tmplogrator/redis.stdout.1")
|
||||
finfo, err := os.Stat(filepath.Join(path, "redis.stdout.1"))
|
||||
if err != nil {
|
||||
t.Fatal("expected rotator to create redis.stdout.1")
|
||||
}
|
||||
@@ -204,3 +199,35 @@ func TestLogRotator_ExcludeDirs(t *testing.T) {
|
||||
t.Fatalf("expected size: %v, actual: %v", 2, finfo.Size())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogRotator_PurgeDirs(t *testing.T) {
|
||||
defer os.RemoveAll(path)
|
||||
if err := os.Mkdir(path, os.ModeDir|os.ModePerm); err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
}
|
||||
|
||||
l, err := NewLogRotator(path, "redis.stdout", 2, 4, logger)
|
||||
if err != nil {
|
||||
t.Fatalf("test setup err: %v", err)
|
||||
}
|
||||
|
||||
r, w := io.Pipe()
|
||||
go func() {
|
||||
w.Write([]byte("abcdefghijklmno"))
|
||||
w.Close()
|
||||
}()
|
||||
|
||||
err = l.Start(r)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Fatalf("failure in logrotator start: %v", err)
|
||||
}
|
||||
l.PurgeOldFiles()
|
||||
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if len(files) != 2 {
|
||||
t.Fatalf("expected number of files: %v, actual: %v", 2, len(files))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user