Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[!] add file log rotation machinery, closes #522 #550

Merged
merged 2 commits into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions docs/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,39 +59,42 @@ Command line options
-c, --clientname= Unique name for application instance [$PGTT_CLIENTNAME]
--config= YAML configuration file
--no-program-tasks Disable executing of PROGRAM tasks [$PGTT_NOPROGRAMTASKS]

-v, --version Output detailed version information [$PGTT_VERSION]

Connection:
-h, --host= PostgreSQL host (default: localhost) [$PGTT_PGHOST]
-p, --port= PostgreSQL port (default: 5432) [$PGTT_PGPORT]
-d, --dbname= PostgreSQL database name (default: timetable) [$PGTT_PGDATABASE]
-u, --user= PostgreSQL user (default: scheduler) [$PGTT_PGUSER]
--password= PostgreSQL user password [$PGTT_PGPASSWORD]
--sslmode=[disable|require] What SSL mode to use for connection (default: disable) [$PGTT_PGSSLMODE]
--sslmode=[disable|require] Connection SSL mode (default: disable) [$PGTT_PGSSLMODE]
--pgurl= PostgreSQL connection URL [$PGTT_URL]
--timeout= PostgreSQL connection timeout in seconds (default: 90) [$PGTT_TIMEOUT]

--timeout= PostgreSQL connection timeout (default: 90) [$PGTT_TIMEOUT]
Logging:
--log-level=[debug|info|error] Verbosity level for stdout and log file (default: info)
--log-database-level=[debug|info|error|none] Verbosity level for database storing (default: info)
--log-file= File name to store logs
--log-file-format=[json|text] Format of file logs (default: json)

--log-file-rotate Rotate log files

Start:
-f, --file= SQL script file to execute during startup
--init Initialize database schema to the latest version and exit. Can be used
with --upgrade
--init Initialize database schema to the latest version and exit.
Can be used with --upgrade
--upgrade Upgrade database to the latest version
--debug Run in debug mode. Only asynchronous chains will be executed

--debug Run in debug mode. Only asynchronous chains will be executed
Resource:
--cron-workers= Number of parallel workers for scheduled chains (default: 16)
--interval-workers= Number of parallel workers for interval chains (default: 16)
--chain-timeout= Abort any chain that takes more than the specified number of milliseconds
--task-timeout= Abort any task within a chain that takes more than the specified number
of milliseconds

--cron-workers= Number of parallel workers for scheduled chains (default: 16)
--interval-workers= Number of parallel workers for interval chains (default: 16)
--chain-timeout= Abort any chain that takes more than the specified number of
milliseconds
--task-timeout= Abort any task within a chain that takes more than the specified
number of milliseconds

REST:
--rest-port= REST API port (default: 0) [%PGTT_RESTPORT%]
--rest-port= REST API port (default: 0) [$PGTT_RESTPORT]


Contributing
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/sirupsen/logrus v1.9.0
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.2
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
3 changes: 2 additions & 1 deletion internal/config/cmdparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type ConnectionOpts struct {
DBName string `short:"d" long:"dbname" description:"PostgreSQL database name" default:"timetable" env:"PGTT_PGDATABASE"`
User string `short:"u" long:"user" description:"PostgreSQL user" default:"scheduler" env:"PGTT_PGUSER"`
Password string `long:"password" description:"PostgreSQL user password" env:"PGTT_PGPASSWORD"`
SSLMode string `long:"sslmode" default:"disable" description:"What SSL mode to use for connection" env:"PGTT_PGSSLMODE" choice:"disable" choice:"require"`
SSLMode string `long:"sslmode" default:"disable" description:"Connection SSL mode" env:"PGTT_PGSSLMODE" choice:"disable" choice:"require"`
PgURL string `long:"pgurl" description:"PostgreSQL connection URL" env:"PGTT_URL"`
Timeout int `long:"timeout" description:"PostgreSQL connection timeout" env:"PGTT_TIMEOUT" default:"90"`
}
Expand All @@ -25,6 +25,7 @@ type LoggingOpts struct {
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"`
LogFile string `long:"log-file" mapstructure:"log-file" description:"File name to store logs"`
LogFileFormat string `long:"log-file-format" mapstructure:"log-file-format" description:"Format of file logs" choice:"json" choice:"text" default:"json"`
LogFileRotate bool `long:"log-file-rotate" mapstructure:"log-file-rotate" description:"Rotate log files"`
}

// StartOpts specifies the application startup options
Expand Down
27 changes: 21 additions & 6 deletions internal/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/jackc/pgx/v5/tracelog"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
)

type (
Expand All @@ -22,18 +23,32 @@ type (
loggerKey struct{}
)

func getLogFileWriter(opts config.LoggingOpts) any {
if opts.LogFileRotate {
return &lumberjack.Logger{
Filename: opts.LogFile,
MaxSize: 10, // megabytes after which new file is created
MaxBackups: 10, // number of backups
MaxAge: 7, //days
}
}
return opts.LogFile
}

func getLogFileFormatter(opts config.LoggingOpts) logrus.Formatter {
if opts.LogFileFormat == "text" {
return &logrus.TextFormatter{}
}
return &logrus.JSONFormatter{}
}

// Init creates logging facilities for the application
func Init(opts config.LoggingOpts) LoggerHookerIface {
var err error
l := logrus.New()
l.Out = os.Stdout
if opts.LogFile > "" {
var f logrus.Formatter
f = &logrus.JSONFormatter{}
if opts.LogFileFormat == "text" {
f = &logrus.TextFormatter{}
}
l.AddHook(lfshook.NewHook(opts.LogFile, f))
l.AddHook(lfshook.NewHook(getLogFileWriter(opts), getLogFileFormatter(opts)))
}
l.Level, err = logrus.ParseLevel(opts.LogLevel)
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions internal/log/log_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package log

import (
"testing"

"github.com/cybertec-postgresql/pg_timetable/internal/config"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"gopkg.in/natefinch/lumberjack.v2"
)

func TestGetLogFileWriter(t *testing.T) {
assert.IsType(t, getLogFileWriter(config.LoggingOpts{LogFileRotate: true}), &lumberjack.Logger{})
assert.IsType(t, getLogFileWriter(config.LoggingOpts{LogFileRotate: false}), "string")
}

func TestGetLogFileFormatter(t *testing.T) {
assert.IsType(t, getLogFileFormatter(config.LoggingOpts{LogFileFormat: "json"}), &logrus.JSONFormatter{})
assert.IsType(t, getLogFileFormatter(config.LoggingOpts{LogFileFormat: "blah"}), &logrus.JSONFormatter{})
assert.IsType(t, getLogFileFormatter(config.LoggingOpts{LogFileFormat: "text"}), &logrus.TextFormatter{})
}