Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 14:45 UTC
logging: Support `zstd` roll compression (#7515)
Francis Lavoie committed
Feb 23, 2026 at 18:04 UTC
987375297862d9cd0a3fa33cfb199c25e504ad1b
2 files changed
+46
-2
caddytest/integration/caddyfile_adapt/log_roll_days.caddyfiletest
+4
@@ -6,6 +6,7 @@ log one {
6
dir_mode 0755
7
roll_size 1gb
8
roll_uncompressed
9
+ roll_compression none
10
roll_local_time
11
roll_keep 5
12
roll_keep_for 90d
@@ -16,6 +17,7 @@ log two {
17
mode 0777
18
dir_mode from_file
19
roll_size 1gib
20
+ roll_compression zstd
21
roll_interval 12h
22
roll_at 00:00 06:00 12:00,18:00
23
roll_minutes 10 40 45,46
@@ -39,6 +41,7 @@ log two {
41
"filename": "/var/log/access.log",
42
"mode": "0644",
43
"output": "file",
44
+ "roll_compression": "none",
45
"roll_gzip": false,
46
"roll_keep": 5,
47
"roll_keep_days": 90,
@@ -61,6 +64,7 @@ log two {
64
"12:00",
65
"18:00"
66
],
67
+ "roll_compression": "zstd",
68
"roll_interval": 43200000000000,
69
"roll_keep": 10,
70
"roll_keep_days": 90,
modules/logging/filewriter.go
+42
-2
@@ -122,9 +122,16 @@ type FileWriter struct {
122
// See https://github.com/DeRuina/timberjack#%EF%B8%8F-rotation-notes--warnings for caveats
123
RollAt []string `json:"roll_at,omitempty"`
124
125
- // Whether to compress rolled files. Default: true
125
+ // Whether to compress rolled files.
126
+ // Default: true.
127
+ // Deprecated: Use RollCompression instead, setting it to "none".
128
RollCompress *bool `json:"roll_gzip,omitempty"`
129
130
+ // RollCompression selects the compression algorithm for rolled files.
131
+ // Accepted values: "none", "gzip", "zstd".
132
+ // Default: gzip
133
+ RollCompression string `json:"roll_compression,omitempty"`
134
+
135
// Whether to use local timestamps in rolled filenames.
136
// Default: false
137
RollLocalTime bool `json:"roll_local_time,omitempty"`
@@ -254,13 +261,32 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
261
if fw.RollKeepDays == 0 {
262
fw.RollKeepDays = 90
263
}
264
+
265
+ // Determine compression algorithm to use. Priority:
266
+ // 1) explicit RollCompression (none|gzip|zstd)
267
+ // 2) if RollCompress is unset or true -> gzip
268
+ // 3) if RollCompress is false -> none
269
+ var compression string
270
+ if fw.RollCompression != "" {
271
+ compression = strings.ToLower(strings.TrimSpace(fw.RollCompression))
272
+ if compression != "none" && compression != "gzip" && compression != "zstd" {
273
+ return nil, fmt.Errorf("invalid roll_compression: %s", fw.RollCompression)
274
+ }
275
+ } else {
276
+ if fw.RollCompress == nil || *fw.RollCompress {
277
+ compression = "gzip"
278
+ } else {
279
+ compression = "none"
280
+ }
281
+ }
282
+
283
return &timberjack.Logger{
284
Filename: fw.Filename,
285
MaxSize: fw.RollSizeMB,
286
MaxAge: fw.RollKeepDays,
287
MaxBackups: fw.RollKeep,
288
LocalTime: fw.RollLocalTime,
263
- Compress: *fw.RollCompress,
289
+ Compression: compression,
290
RotationInterval: fw.RollInterval,
291
RotateAtMinutes: fw.RollAtMinutes,
292
RotateAt: fw.RollAt,
@@ -332,6 +358,7 @@ func mkdirAllFromFile(dir string, fileMode os.FileMode) error {
358
// roll_disabled
359
// roll_size <size>
360
// roll_uncompressed
361
+// roll_compression <none|gzip|zstd>
362
// roll_local_time
363
// roll_keep <num>
364
// roll_keep_for <days>
@@ -413,6 +440,19 @@ func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
440
return d.ArgErr()
441
}
442
443
+ case "roll_compression":
444
+ var comp string
445
+ if !d.AllArgs(&comp) {
446
+ return d.ArgErr()
447
+ }
448
+ comp = strings.ToLower(strings.TrimSpace(comp))
449
+ switch comp {
450
+ case "none", "gzip", "zstd":
451
+ fw.RollCompression = comp
452
+ default:
453
+ return d.Errf("parsing roll_compression: must be 'none', 'gzip' or 'zstd'")
454
+ }
455
+
456
case "roll_local_time":
457
fw.RollLocalTime = true
458
if d.NextArg() {