Skip to content

Commit

Permalink
Merge pull request #1 from qazwsxedckll/dev
Browse files Browse the repository at this point in the history
v0.1.0
  • Loading branch information
qazwsxedckll authored Mar 6, 2024
2 parents be2c2b1 + c3519e1 commit 82089ef
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 0 deletions.
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/qazwsxedckll/logh

go 1.22.0

require github.com/stretchr/testify v1.9.0

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
14 changes: 14 additions & 0 deletions rotate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package logh

import (
"log/slog"
)

func NewRotateJSONHandler(directory string, basename string, rollSize int, opts *slog.HandlerOptions, options ...Option) (slog.Handler, error) {
file, err := NewRotateFile(directory, basename, rollSize, options...)
if err != nil {
return nil, err
}

return slog.NewJSONHandler(file, opts), nil
}
104 changes: 104 additions & 0 deletions rotate_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package logh

import (
"fmt"
"os"
"time"
)

type RotateFile struct {
filepath string
file *os.File

rotateSize int
rotateInterval time.Duration
checkEveryN int

written int
lastRotate time.Time
count int
}

func NewRotateFile(directory string, basename string, rotateSize int, opts ...Option) (*RotateFile, error) {
err := os.MkdirAll(directory, 0o755)
if err != nil {
return nil, err
}

rf := &RotateFile{
filepath: directory + "/" + basename,
rotateSize: rotateSize,
rotateInterval: time.Hour * 24,
checkEveryN: 1024,
}

for _, opt := range opts {
if opt != nil {
opt(rf)
}
}

rf.rotate()

return rf, nil
}

func (r *RotateFile) Write(p []byte) (int, error) {
n, err := r.file.Write(p)
r.written += n

if r.written > r.rotateSize {
r.rotate()
} else {
r.count++
if r.count >= r.checkEveryN {
r.count = 0
if time.Now().After(r.lastRotate.Add(r.rotateInterval)) {
r.rotate()
}
}
}

return n, err
}

func (r *RotateFile) logFileName() (string, time.Time) {
hostname, err := os.Hostname()
if err != nil {
hostname = "unknownhost"
}
now := time.Now()
return r.filepath + "." + now.Format("20060102-150405.000000000") + "." + hostname + "." + fmt.Sprint(os.Getpid()) + ".log", now
}

func (r *RotateFile) rotate() {
filename, now := r.logFileName()

if now.After(r.lastRotate) {
file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
if err != nil {
panic(fmt.Sprintf("Failed to open log file %s: %s", filename, err))
}

if r.file != nil {
// TODO: error handling?
r.file.Close()
}
r.file = file
r.lastRotate = now
}
}

type Option func(*RotateFile)

func WithCheckEveryN(n int) Option {
return func(r *RotateFile) {
r.checkEveryN = n
}
}

func WithRotateInterval(d time.Duration) Option {
return func(r *RotateFile) {
r.rotateInterval = d
}
}
70 changes: 70 additions & 0 deletions rotate_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package logh

import (
"os"
"testing"
"time"

"github.com/stretchr/testify/require"
)

func TestNewRotateFile(t *testing.T) {
path, err := os.MkdirTemp("", "loghtest")
require.NoError(t, err)
defer os.RemoveAll(path)

path += "/TestNewRotateFile"
file, err := NewRotateFile(path, "test", 10, nil)
require.NoError(t, err)
require.NotNil(t, file)

dir, err := os.ReadDir(path)
require.NoError(t, err)
require.Len(t, dir, 1)
}

func TestRotateSize(t *testing.T) {
path, err := os.MkdirTemp("", "loghtest-TestRotateSize")
require.NoError(t, err)
defer os.RemoveAll(path)

file, err := NewRotateFile(path, "test", 10)
require.NoError(t, err)

_, err = file.Write([]byte("12345678901234567890"))
require.NoError(t, err)
_, err = file.Write([]byte("12345678901234567890"))
require.NoError(t, err)

dir, err := os.ReadDir(path)
require.NoError(t, err)
require.Len(t, dir, 3)
}

func TestRotateInterval(t *testing.T) {
path, err := os.MkdirTemp("", "loghtest-TestRotateInterval")
require.NoError(t, err)
defer os.RemoveAll(path)

file, err := NewRotateFile(path, "test", 1024, WithCheckEveryN(2), WithRotateInterval(1*time.Second))
require.NoError(t, err)

_, err = file.Write([]byte("1"))
require.NoError(t, err)
_, err = file.Write([]byte("2"))
require.NoError(t, err)

dir, err := os.ReadDir(path)
require.NoError(t, err)
require.Len(t, dir, 1)

time.Sleep(1 * time.Second)
_, err = file.Write([]byte("1"))
require.NoError(t, err)
_, err = file.Write([]byte("2"))
require.NoError(t, err)

dir, err = os.ReadDir(path)
require.NoError(t, err)
require.Len(t, dir, 2)
}

0 comments on commit 82089ef

Please sign in to comment.