Skip to content

Commit 2fc2b7d

Browse files
authored
Merge pull request #550 from cybertec-postgresql/522-enable-log-rotation
[!] add file log rotation machinery, closes #522
2 parents 2d077d7 + cc322e6 commit 2fc2b7d

File tree

6 files changed

+66
-23
lines changed

6 files changed

+66
-23
lines changed

docs/README.rst

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,39 +59,42 @@ Command line options
5959
-c, --clientname= Unique name for application instance [$PGTT_CLIENTNAME]
6060
--config= YAML configuration file
6161
--no-program-tasks Disable executing of PROGRAM tasks [$PGTT_NOPROGRAMTASKS]
62-
62+
-v, --version Output detailed version information [$PGTT_VERSION]
63+
6364
Connection:
6465
-h, --host= PostgreSQL host (default: localhost) [$PGTT_PGHOST]
6566
-p, --port= PostgreSQL port (default: 5432) [$PGTT_PGPORT]
6667
-d, --dbname= PostgreSQL database name (default: timetable) [$PGTT_PGDATABASE]
6768
-u, --user= PostgreSQL user (default: scheduler) [$PGTT_PGUSER]
6869
--password= PostgreSQL user password [$PGTT_PGPASSWORD]
69-
--sslmode=[disable|require] What SSL mode to use for connection (default: disable) [$PGTT_PGSSLMODE]
70+
--sslmode=[disable|require] Connection SSL mode (default: disable) [$PGTT_PGSSLMODE]
7071
--pgurl= PostgreSQL connection URL [$PGTT_URL]
71-
--timeout= PostgreSQL connection timeout in seconds (default: 90) [$PGTT_TIMEOUT]
72-
72+
--timeout= PostgreSQL connection timeout (default: 90) [$PGTT_TIMEOUT]
73+
7374
Logging:
7475
--log-level=[debug|info|error] Verbosity level for stdout and log file (default: info)
7576
--log-database-level=[debug|info|error|none] Verbosity level for database storing (default: info)
7677
--log-file= File name to store logs
7778
--log-file-format=[json|text] Format of file logs (default: json)
78-
79+
--log-file-rotate Rotate log files
80+
7981
Start:
8082
-f, --file= SQL script file to execute during startup
81-
--init Initialize database schema to the latest version and exit. Can be used
82-
with --upgrade
83+
--init Initialize database schema to the latest version and exit.
84+
Can be used with --upgrade
8385
--upgrade Upgrade database to the latest version
84-
--debug Run in debug mode. Only asynchronous chains will be executed
85-
86+
--debug Run in debug mode. Only asynchronous chains will be executed
87+
8688
Resource:
87-
--cron-workers= Number of parallel workers for scheduled chains (default: 16)
88-
--interval-workers= Number of parallel workers for interval chains (default: 16)
89-
--chain-timeout= Abort any chain that takes more than the specified number of milliseconds
90-
--task-timeout= Abort any task within a chain that takes more than the specified number
91-
of milliseconds
92-
89+
--cron-workers= Number of parallel workers for scheduled chains (default: 16)
90+
--interval-workers= Number of parallel workers for interval chains (default: 16)
91+
--chain-timeout= Abort any chain that takes more than the specified number of
92+
milliseconds
93+
--task-timeout= Abort any task within a chain that takes more than the specified
94+
number of milliseconds
95+
9396
REST:
94-
--rest-port= REST API port (default: 0) [%PGTT_RESTPORT%]
97+
--rest-port= REST API port (default: 0) [$PGTT_RESTPORT]
9598
9699
97100
Contributing

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/sirupsen/logrus v1.9.0
1414
github.com/spf13/viper v1.15.0
1515
github.com/stretchr/testify v1.8.2
16+
gopkg.in/natefinch/lumberjack.v2 v2.2.1
1617
)
1718

1819
require (

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
498498
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
499499
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
500500
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
501+
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
502+
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
501503
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
502504
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
503505
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

internal/config/cmdparser.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type ConnectionOpts struct {
1414
DBName string `short:"d" long:"dbname" description:"PostgreSQL database name" default:"timetable" env:"PGTT_PGDATABASE"`
1515
User string `short:"u" long:"user" description:"PostgreSQL user" default:"scheduler" env:"PGTT_PGUSER"`
1616
Password string `long:"password" description:"PostgreSQL user password" env:"PGTT_PGPASSWORD"`
17-
SSLMode string `long:"sslmode" default:"disable" description:"What SSL mode to use for connection" env:"PGTT_PGSSLMODE" choice:"disable" choice:"require"`
17+
SSLMode string `long:"sslmode" default:"disable" description:"Connection SSL mode" env:"PGTT_PGSSLMODE" choice:"disable" choice:"require"`
1818
PgURL string `long:"pgurl" description:"PostgreSQL connection URL" env:"PGTT_URL"`
1919
Timeout int `long:"timeout" description:"PostgreSQL connection timeout" env:"PGTT_TIMEOUT" default:"90"`
2020
}
@@ -25,6 +25,7 @@ type LoggingOpts struct {
2525
LogDBLevel string `long:"log-database-level" mapstructure:"log-database-level" description:"Verbosity level for database storing" choice:"debug" choice:"info" choice:"error" choice:"none" default:"info"`
2626
LogFile string `long:"log-file" mapstructure:"log-file" description:"File name to store logs"`
2727
LogFileFormat string `long:"log-file-format" mapstructure:"log-file-format" description:"Format of file logs" choice:"json" choice:"text" default:"json"`
28+
LogFileRotate bool `long:"log-file-rotate" mapstructure:"log-file-rotate" description:"Rotate log files"`
2829
}
2930

3031
// StartOpts specifies the application startup options

internal/log/log.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/jackc/pgx/v5/tracelog"
99
"github.com/rifflock/lfshook"
1010
"github.com/sirupsen/logrus"
11+
"gopkg.in/natefinch/lumberjack.v2"
1112
)
1213

1314
type (
@@ -22,18 +23,32 @@ type (
2223
loggerKey struct{}
2324
)
2425

26+
func getLogFileWriter(opts config.LoggingOpts) any {
27+
if opts.LogFileRotate {
28+
return &lumberjack.Logger{
29+
Filename: opts.LogFile,
30+
MaxSize: 10, // megabytes after which new file is created
31+
MaxBackups: 10, // number of backups
32+
MaxAge: 7, //days
33+
}
34+
}
35+
return opts.LogFile
36+
}
37+
38+
func getLogFileFormatter(opts config.LoggingOpts) logrus.Formatter {
39+
if opts.LogFileFormat == "text" {
40+
return &logrus.TextFormatter{}
41+
}
42+
return &logrus.JSONFormatter{}
43+
}
44+
2545
// Init creates logging facilities for the application
2646
func Init(opts config.LoggingOpts) LoggerHookerIface {
2747
var err error
2848
l := logrus.New()
2949
l.Out = os.Stdout
3050
if opts.LogFile > "" {
31-
var f logrus.Formatter
32-
f = &logrus.JSONFormatter{}
33-
if opts.LogFileFormat == "text" {
34-
f = &logrus.TextFormatter{}
35-
}
36-
l.AddHook(lfshook.NewHook(opts.LogFile, f))
51+
l.AddHook(lfshook.NewHook(getLogFileWriter(opts), getLogFileFormatter(opts)))
3752
}
3853
l.Level, err = logrus.ParseLevel(opts.LogLevel)
3954
if err != nil {

internal/log/log_file_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package log
2+
3+
import (
4+
"testing"
5+
6+
"github.com/cybertec-postgresql/pg_timetable/internal/config"
7+
"github.com/sirupsen/logrus"
8+
"github.com/stretchr/testify/assert"
9+
"gopkg.in/natefinch/lumberjack.v2"
10+
)
11+
12+
func TestGetLogFileWriter(t *testing.T) {
13+
assert.IsType(t, getLogFileWriter(config.LoggingOpts{LogFileRotate: true}), &lumberjack.Logger{})
14+
assert.IsType(t, getLogFileWriter(config.LoggingOpts{LogFileRotate: false}), "string")
15+
}
16+
17+
func TestGetLogFileFormatter(t *testing.T) {
18+
assert.IsType(t, getLogFileFormatter(config.LoggingOpts{LogFileFormat: "json"}), &logrus.JSONFormatter{})
19+
assert.IsType(t, getLogFileFormatter(config.LoggingOpts{LogFileFormat: "blah"}), &logrus.JSONFormatter{})
20+
assert.IsType(t, getLogFileFormatter(config.LoggingOpts{LogFileFormat: "text"}), &logrus.TextFormatter{})
21+
}

0 commit comments

Comments
 (0)