summaryrefslogtreecommitdiff
path: root/internal/log
diff options
context:
space:
mode:
authorJeroen Wijenbergh <jeroen.wijenbergh@geant.org>2026-02-12 12:34:08 +0100
committerJeroen Wijenbergh <jeroen.wijenbergh@geant.org>2026-02-12 12:59:03 +0100
commita30ef6b27e578a4cf0a674b24f5b52b4c1516c63 (patch)
tree27c7321cbceac2a487c1ba17151711de3d438a53 /internal/log
parentb00ce8214479c50e137db73c77b0cc1393c5e7d4 (diff)
All: Rename packages that sound useless or clash with std
Diffstat (limited to 'internal/log')
-rw-r--r--internal/log/log.go37
-rw-r--r--internal/log/rotate.go109
-rw-r--r--internal/log/rotate_test.go144
3 files changed, 0 insertions, 290 deletions
diff --git a/internal/log/log.go b/internal/log/log.go
deleted file mode 100644
index 91eaed8..0000000
--- a/internal/log/log.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Package log implements a basic level based logger
-package log
-
-import (
- "fmt"
- "io"
- "log/slog"
- "os"
- "path"
-)
-
-type Logger struct {
- fr *FileRotater
-}
-
-func (l *Logger) Init(dir string) (*slog.Logger, error) {
- err := os.MkdirAll(dir, 0o700)
- if err != nil {
- return nil, err
- }
- name := path.Join(dir, "log")
-
- fr, err := NewFileRotater(name)
- if err != nil {
- return nil, fmt.Errorf("failed creating log rotater: %w", err)
- }
- l.fr = fr
- multi := io.MultiWriter(os.Stdout, fr)
- handler := slog.NewTextHandler(multi, &slog.HandlerOptions{
- Level: slog.LevelDebug,
- })
- return slog.New(handler), nil
-}
-
-func (l *Logger) Close() error {
- return l.fr.Close()
-}
diff --git a/internal/log/rotate.go b/internal/log/rotate.go
deleted file mode 100644
index 2971f70..0000000
--- a/internal/log/rotate.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package log
-
-import (
- "io"
- "os"
- "sync"
-
- "codeberg.org/eduVPN/eduvpn-common/internal/atomicfile"
-)
-
-var (
- // MaxSize is the maximum size in bytes from when to start trimming
- MaxSize int64 = 10 * 1024 * 1024
-
- // TrimSize denotes how much to trim from the beginning
- TrimSize = MaxSize / 2
-
- // TrimMsg is the message to display when it was trimmed
- TrimMsg = "--- previous part was trimmed by eduvpn-common as the file was too big (10MB) ---\n"
-)
-
-// FileRotater is a file that is trimmed when a maximum size is reached
-// This is for logging useful
-type FileRotater struct {
- filename string
- file *os.File
- mu sync.Mutex
-}
-
-// NewFileRotater creates a new log file rotater
-func NewFileRotater(filename string) (*FileRotater, error) {
- fr := &FileRotater{
- filename: filename,
- }
-
- err := fr.open()
- if err != nil {
- return nil, err
- }
- return fr, nil
-}
-
-func (fr *FileRotater) open() error {
- f, err := os.OpenFile(fr.filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
- if err != nil {
- return err
- }
- fr.file = f
- return nil
-}
-
-func (fr *FileRotater) trim() error {
- // We need to seek to the trim size to skip over that part as we discard it
- _, err := fr.file.Seek(TrimSize, io.SeekStart)
- if err != nil {
- return err
- }
-
- // get the part of the file that we want to keep
- keep, err := io.ReadAll(fr.file)
- if err != nil {
- return err
- }
-
- all := []byte(TrimMsg)
- all = append(all, keep...)
- err = atomicfile.WriteFile(fr.file.Name(), all, 0o666)
- if err != nil {
- return err
- }
-
- // re-open the handle as the file was renamed
- err = fr.file.Close()
- if err != nil {
- return err
- }
- err = fr.open()
- if err != nil {
- return err
- }
- return nil
-}
-
-// Write implements io.Writer for the log rotater
-func (fr *FileRotater) Write(p []byte) (n int, err error) {
- fr.mu.Lock()
- defer fr.mu.Unlock()
- fi, err := fr.file.Stat()
- if err != nil {
- return 0, err
- }
-
- if fi.Size() >= MaxSize {
- err = fr.trim()
- if err != nil {
- return 0, err
- }
- }
- // we don't write atomically here as we want it to be as fast as possible
- // and if we lose a part of one log statement it's not a big deal
- return fr.file.Write(p)
-}
-
-// Close closes the file in a safe way by locking and unlocking the mutex
-func (fr *FileRotater) Close() error {
- fr.mu.Lock()
- defer fr.mu.Unlock()
- return fr.file.Close()
-}
diff --git a/internal/log/rotate_test.go b/internal/log/rotate_test.go
deleted file mode 100644
index 4fa77fd..0000000
--- a/internal/log/rotate_test.go
+++ /dev/null
@@ -1,144 +0,0 @@
-package log
-
-import (
- "io"
- "os"
- "path/filepath"
- "strings"
- "sync"
- "testing"
-)
-
-func createFileRotater(t *testing.T) (*FileRotater, func()) {
- d, err := os.MkdirTemp("", "logtest")
- if err != nil {
- t.Fatalf("failed creating tmp dir: %v", err)
- }
- fn := filepath.Join(d, "test.log")
- fr, err := NewFileRotater(fn)
- if err != nil {
- t.Fatalf("NewFileRotater error: %v", err)
- }
- if fr == nil {
- t.Fatal("NewFileRotater returned nil")
- }
- return fr, func() {
- err := os.RemoveAll(d)
- if err != nil {
- t.Errorf("failed removing file: %v", err)
- }
- }
-}
-
-func TestNewFileRotater(t *testing.T) {
- _, cleanup := createFileRotater(t)
- cleanup()
-
- d, err := os.MkdirTemp("", "anotherlogtest")
- if err != nil {
- t.Fatalf("failed creating another tmp dir: %v", err)
- }
- nef := filepath.Join(d, "notexist", "test.log")
- _, err = NewFileRotater(nef)
- if err == nil {
- t.Error("NewFileRotater returned no error with nonexistent dir")
- }
-}
-
-func TestWriteConcurrent(t *testing.T) {
- fr, cleanup := createFileRotater(t)
- defer cleanup()
- MaxSize = 5
- var wg sync.WaitGroup
- for range 5 {
- wg.Add(1)
- go func() {
- _, err := fr.Write([]byte("test"))
- defer wg.Done()
- if err != nil {
- t.Errorf("concurrent write returned an error: %v", err)
- }
- }()
- }
- wg.Wait()
-}
-
-func TestWriteTrim(t *testing.T) {
- fr, cleanup := createFileRotater(t)
- defer cleanup()
- writeNCheckSize := func(n int, size int64) {
- buf := make([]byte, n)
-
- for i := range n {
- buf[i] = 'x'
- }
- _, err := fr.Write(buf)
- if err != nil {
- t.Fatalf("failed writing: %v", err)
- }
-
- fs, err := fr.file.Stat()
- if err != nil {
- t.Fatalf("failed getting size: %v", err)
- }
-
- gsize := fs.Size()
-
- if gsize != size {
- t.Fatalf("got: %v, want: %v, max size: %v", gsize, size, MaxSize)
- }
- }
-
- // we test by writing a start message and checking if it disappears after trimmign
- // the max size we set to the length of the start message + 20 bytes
- begS := "this is the start"
- begB := []byte(begS)
- startN := int64(len(begB))
- MaxSize = startN + 20
- TrimSize = MaxSize / 2
-
- // no trim yet
- _, err := fr.Write(begB)
- if err != nil {
- t.Fatalf("failed writing start message: %v", err)
- }
-
- // write until the trimming size
- writeNCheckSize(5, startN+5)
- writeNCheckSize(15, MaxSize)
-
- // set the length we want to write
- var n int64 = 11
-
- // now the size should be the length of the trimmed message plus the remaining (non-trimmed part of the file) plus the length we want to write
-
- size := int64(len(TrimMsg)) + (MaxSize - TrimSize) + n
- writeNCheckSize(11, size)
-
- // disable trimming by setting it to a high value
- MaxSize = 9000
- TrimSize = 9000
-
- // now the size should be the old size plus the write size
- newN := 12
- writeNCheckSize(newN, size+int64(newN))
-
- _, err = fr.file.Seek(0, io.SeekStart)
- if err != nil {
- t.Fatalf("failed going to beginning of file: %v", err)
- }
-
- b, err := io.ReadAll(fr.file)
- if err != nil {
- t.Fatalf("failed reading file: %v", err)
- }
-
- corpus := string(b)
- if strings.Contains(corpus, begS) {
- t.Fatalf("file still contains beginning message: %v", corpus)
- }
-
- if !strings.Contains(corpus, TrimMsg) {
- t.Fatalf("file does not contain trim message: %v", corpus)
- }
-}