fix: don't expose the old log file time format string

Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso
2025-11-21 11:31:50 -05:00
parent 7a9590efd8
commit ad680d8a48
4 changed files with 46 additions and 74 deletions

View File

@@ -372,15 +372,14 @@ This isn't currently used by Anubis, but will be in the future for "slightly imp
The `file` sink makes Anubis write its logs to the filesystem and rotate them out when the log file meets certain thresholds. This logging sink takes the following parameters:
| Name | Type | Example | Description |
| :------------------ | :-------------------- | :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `file` | string | `/var/log/anubis.log` | The file where Anubis logs should be written to. Make sure the user Anubis is running as has write and file creation permissions to this directory. |
| `maxBackups` | number | `3` | The number of old log files that should be maintained when log files are rotated out. |
| `maxBytes` | number of bytes | `67108864` (64Mi) | The maximum size of each log file before it is rotated out. |
| `maxAge` | number of days | `7` | If a log file is more than this many days old, rotate it out. |
| `oldFileTimeFormat` | Go time format string | `2006-01-02T15-04-05` | A [Go time format string](https://pkg.go.dev/time#Layout) that describes how the filenames of old log files should be constructed. This default somewhat conforms to [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339). |
| `compress` | boolean | `true` | If true, compress old log files with gzip. This should be set to `true` and is only exposed as an option for dealing with legacy workflows where there is pre-existing magical thinking about log files at play. |
| `useLocalTime` | boolean | `false` | If true, use the system local time zone to create log filenames instead of UTC. This should almost always be set to `false` and is only exposed for legacy workflows where there is pre-existing magical thinking about time zones at play. |
| Name | Type | Example | Description |
| :------------- | :-------------- | :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `file` | string | `/var/log/anubis.log` | The file where Anubis logs should be written to. Make sure the user Anubis is running as has write and file creation permissions to this directory. |
| `maxBackups` | number | `3` | The number of old log files that should be maintained when log files are rotated out. |
| `maxBytes` | number of bytes | `67108864` (64Mi) | The maximum size of each log file before it is rotated out. |
| `maxAge` | number of days | `7` | If a log file is more than this many days old, rotate it out. |
| `compress` | boolean | `true` | If true, compress old log files with gzip. This should be set to `true` and is only exposed as an option for dealing with legacy workflows where there is magical thinking about log files at play. |
| `useLocalTime` | boolean | `false` | If true, use the system local time zone to create log filenames instead of UTC. This should almost always be set to `false` and is only exposed for legacy workflows where there is magical thinking about time zones at play. |
```yaml
logging:
@@ -390,11 +389,12 @@ logging:
maxBackups: 3 # keep at least 3 old copies
maxBytes: 67108864 # each file can have up to 64 Mi of logs
maxAge: 7 # rotate files out every n days
oldFileTimeFormat: 2006-01-02T15-04-05 # RFC 3339-ish
compress: true # gzip-compress old log files
useLocalTime: false # timezone for rotated files is UTC
```
When files are rotated out, the old files will be named after the rotation timestamp in [RFC 3339 format](https://www.rfc-editor.org/rfc/rfc3339).
### `stdio` sink
By default, Anubis logs everything to the standard error stream of its process. This requires no configuration:

View File

@@ -4,15 +4,13 @@ import (
"errors"
"fmt"
"log/slog"
"time"
)
var (
ErrMissingLoggingFileConfig = errors.New("config.Logging: missing value parameters in logging block")
ErrInvalidLoggingSink = errors.New("config.Logging: invalid sink")
ErrInvalidLoggingFileConfig = errors.New("config.LoggingFileConfig: invalid parameters")
ErrInvalidLoggingFileConfigOldTimeFormat = errors.New("config.LoggingFileConfig: invalid old time format")
ErrOutOfRange = errors.New("config: error out of range")
ErrMissingLoggingFileConfig = errors.New("config.Logging: missing value parameters in logging block")
ErrInvalidLoggingSink = errors.New("config.Logging: invalid sink")
ErrInvalidLoggingFileConfig = errors.New("config.LoggingFileConfig: invalid parameters")
ErrOutOfRange = errors.New("config: error out of range")
)
type Logging struct {
@@ -58,13 +56,12 @@ func (Logging) Default() *Logging {
}
type LoggingFileConfig struct {
Filename string `json:"file"`
OldFileTimeFormat string `json:"oldFileTimeFormat"`
MaxBackups int `json:"maxBackups"`
MaxBytes int64 `json:"maxBytes"`
MaxAge int `json:"maxAge"`
Compress bool `json:"compress"`
UseLocalTime bool `json:"useLocalTime"`
Filename string `json:"file"`
MaxBackups int `json:"maxBackups"`
MaxBytes int64 `json:"maxBytes"`
MaxAge int `json:"maxAge"`
Compress bool `json:"compress"`
UseLocalTime bool `json:"useLocalTime"`
}
func (lfc *LoggingFileConfig) Valid() error {
@@ -82,10 +79,6 @@ func (lfc *LoggingFileConfig) Valid() error {
errs = append(errs, fmt.Errorf("%w: filename", ErrMissingValue))
}
if _, err := time.Parse(lfc.OldFileTimeFormat, time.Now().UTC().Format(time.RFC3339)); err != nil {
errs = append(errs, fmt.Errorf("%w: %w", ErrInvalidLoggingFileConfigOldTimeFormat, err))
}
if lfc.MaxBackups < 0 {
errs = append(errs, fmt.Errorf("%w: max backup count %d is not greater than or equal to zero", ErrOutOfRange, lfc.MaxBackups))
}
@@ -105,7 +98,6 @@ func (lfc *LoggingFileConfig) Valid() error {
func (lfc LoggingFileConfig) Zero() bool {
for _, cond := range []bool{
lfc.Filename != "",
lfc.OldFileTimeFormat != "",
lfc.MaxBackups != 0,
lfc.MaxBytes != 0,
lfc.MaxAge != 0,
@@ -122,12 +114,11 @@ func (lfc LoggingFileConfig) Zero() bool {
func (LoggingFileConfig) Default() *LoggingFileConfig {
return &LoggingFileConfig{
Filename: "./var/anubis.log",
OldFileTimeFormat: time.RFC3339,
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
Filename: "./var/anubis.log",
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
}
}

View File

@@ -3,7 +3,6 @@ package config
import (
"errors"
"testing"
"time"
)
func TestLoggingValid(t *testing.T) {
@@ -50,45 +49,27 @@ func TestLoggingValid(t *testing.T) {
input: &Logging{
Sink: LogSinkFile,
Parameters: &LoggingFileConfig{
Filename: "",
OldFileTimeFormat: time.RFC3339,
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
Filename: "",
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
},
},
want: ErrMissingValue,
},
{
name: "file sink with wrong time format",
input: &Logging{
Sink: LogSinkFile,
Parameters: &LoggingFileConfig{
Filename: "./var/anubis.log",
OldFileTimeFormat: "2025-01-01",
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
},
},
want: ErrInvalidLoggingFileConfigOldTimeFormat,
},
{
name: "file sink with negative max backups",
input: &Logging{
Sink: LogSinkFile,
Parameters: &LoggingFileConfig{
Filename: "./var/anubis.log",
OldFileTimeFormat: time.RFC3339,
MaxBackups: -3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
Filename: "./var/anubis.log",
MaxBackups: -3,
MaxBytes: 104857600, // 100 Mi
MaxAge: 7, // 7 days
Compress: true,
UseLocalTime: false,
},
},
want: ErrOutOfRange,
@@ -98,13 +79,12 @@ func TestLoggingValid(t *testing.T) {
input: &Logging{
Sink: LogSinkFile,
Parameters: &LoggingFileConfig{
Filename: "./var/anubis.log",
OldFileTimeFormat: time.RFC3339,
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: -7, // 7 days
Compress: true,
UseLocalTime: false,
Filename: "./var/anubis.log",
MaxBackups: 3,
MaxBytes: 104857600, // 100 Mi
MaxAge: -7, // 7 days
Compress: true,
UseLocalTime: false,
},
},
want: ErrOutOfRange,

View File

@@ -8,6 +8,7 @@ import (
"log/slog"
"os"
"sync/atomic"
"time"
"github.com/TecharoHQ/anubis/internal"
"github.com/TecharoHQ/anubis/lib/config"
@@ -216,7 +217,7 @@ func ParseConfig(ctx context.Context, fin io.Reader, fname string, defaultDiffic
case config.LogSinkFile:
out := &logrotate.Logger{
Filename: c.Logging.Parameters.Filename,
FilenameTimeFormat: c.Logging.Parameters.OldFileTimeFormat,
FilenameTimeFormat: time.RFC3339,
MaxBytes: c.Logging.Parameters.MaxBytes,
MaxAge: c.Logging.Parameters.MaxAge,
MaxBackups: c.Logging.Parameters.MaxBackups,