diff --git a/cmd/versitygw/main.go b/cmd/versitygw/main.go index 458da43c..0798b91e 100644 --- a/cmd/versitygw/main.go +++ b/cmd/versitygw/main.go @@ -442,13 +442,13 @@ func initFlags() []cli.Flag { }, &cli.StringFlag{ Name: "access-log", - Usage: "enable server access logging to specified file", + Usage: "enable server access logging to specified file, stdout, stderr, or - for stdout", EnvVars: []string{"LOGFILE", "VGW_ACCESS_LOG"}, Destination: &accessLog, }, &cli.StringFlag{ Name: "admin-access-log", - Usage: "enable admin server access logging to specified file", + Usage: "enable admin server access logging to specified file, stdout, stderr, or - for stdout", EnvVars: []string{"LOGFILE", "VGW_ADMIN_ACCESS_LOG"}, Destination: &adminLogFile, }, diff --git a/cmd/vgwrdma/main.go b/cmd/vgwrdma/main.go index 2185934f..88795087 100644 --- a/cmd/vgwrdma/main.go +++ b/cmd/vgwrdma/main.go @@ -483,13 +483,13 @@ func initFlags() []cli.Flag { }, &cli.StringFlag{ Name: "access-log", - Usage: "enable server access logging to specified file", + Usage: "enable server access logging to specified file, stdout, stderr, or - for stdout", EnvVars: []string{"LOGFILE", "VGW_ACCESS_LOG"}, Destination: &accessLog, }, &cli.StringFlag{ Name: "admin-access-log", - Usage: "enable admin server access logging to specified file", + Usage: "enable admin server access logging to specified file, stdout, stderr, or - for stdout", EnvVars: []string{"LOGFILE", "VGW_ADMIN_ACCESS_LOG"}, Destination: &adminLogFile, }, diff --git a/embedgw/embedgw.go b/embedgw/embedgw.go index 6065581b..cd227560 100644 --- a/embedgw/embedgw.go +++ b/embedgw/embedgw.go @@ -347,14 +347,16 @@ type Config struct { // are independent and can be enabled simultaneously in any combination. // All are optional; omit or leave empty to disable that output. - // AccessLog is the file path for S3 request access logs in the AWS S3 + // AccessLog is the file path or stream name (stdout, stderr, or - for + // stdout) for S3 request access logs in the AWS S3 // access log format. Use absolute paths; relative paths may break if the // server changes its working directory. Empty disables file logging. AccessLog string // LogWebhookURL is an HTTP(S) URL that receives S3 access log entries as // JSON-encoded POST requests. Can be set alongside AccessLog. LogWebhookURL string - // AdminLogFile is the file path for admin API request logs. + // AdminLogFile is the file path or stream name (stdout, stderr, or - for + // stdout) for admin API request logs. AdminLogFile string // Metrics diff --git a/extra/example.conf b/extra/example.conf index 3204301a..02298798 100644 --- a/extra/example.conf +++ b/extra/example.conf @@ -196,18 +196,18 @@ ROOT_SECRET_ACCESS_KEY= # Access Logs # ############### -# The VGW_ACCESS_LOG option when set will specify the file to log all S3 -# server requests to. This option is optional, and defaults to not logging. -# It is suggested to use absolute paths for the server log file because the -# server may chdir into the backend root directory and change locations for -# relative paths. +# The VGW_ACCESS_LOG option when set will specify where to log all S3 +# server requests. Set it to a file path, stdout, stderr, or - for stdout. +# This option is optional, and defaults to not logging. When using a file, +# it is suggested to use an absolute path because the server may chdir into +# the backend root directory and change locations for relative paths. # The log file format follows the AWS S3 access log format documented in # https://docs.aws.amazon.com/AmazonS3/latest/userguide/LogFormat.html. #VGW_ACCESS_LOG= -# The VGW_ADMIN_ACCESS_LOG option when set will specify the file to log all -# admin server requests to. When not set, admin requests are logged to the -# same file as the S3 server (VGW_ACCESS_LOG) if that is configured. +# The VGW_ADMIN_ACCESS_LOG option when set will specify where to log all +# admin server requests. Set it to a file path, stdout, stderr, or - for +# stdout. This option is optional, and defaults to not logging admin requests. #VGW_ADMIN_ACCESS_LOG= # The VGW_LOG_WEBHOOK_URL option when set will specify the URL to send the diff --git a/s3log/file.go b/s3log/file.go index 55b76ac5..1a2bda92 100644 --- a/s3log/file.go +++ b/s3log/file.go @@ -35,24 +35,37 @@ const ( // FileLogger is a local file audit log type FileLogger struct { - logfile string - f *os.File - gotErr bool - mu sync.Mutex + logfile string + f *os.File + standardStream bool + gotErr bool + mu sync.Mutex } var _ AuditLogger = &FileLogger{} // InitFileLogger initializes audit logs to local file func InitFileLogger(logname string) (AuditLogger, error) { - f, err := os.OpenFile(logname, os.O_APPEND|os.O_CREATE|os.O_WRONLY, logFileMode) + f, standardStream, err := openLogDestination(logname) if err != nil { return nil, fmt.Errorf("open log: %w", err) } fmt.Fprintf(f, "log starts %v\n", time.Now()) - return &FileLogger{logfile: logname, f: f}, nil + return &FileLogger{logfile: logname, f: f, standardStream: standardStream}, nil +} + +func openLogDestination(logname string) (*os.File, bool, error) { + switch strings.ToLower(logname) { + case "stdout", "-": + return os.Stdout, true, nil + case "stderr": + return os.Stderr, true, nil + default: + f, err := os.OpenFile(logname, os.O_APPEND|os.O_CREATE|os.O_WRONLY, logFileMode) + return f, false, err + } } // Log sends log message to file logger @@ -222,6 +235,11 @@ func (f *FileLogger) writeLog(lf LogFields) { // HangUp closes current logfile handle and opens a new one // typically needed for log rotations func (f *FileLogger) HangUp() error { + if f.standardStream { + f.f.WriteString(fmt.Sprintf("log starts %v\n", time.Now())) + return nil + } + err := f.f.Close() if err != nil { return fmt.Errorf("close log: %w", err) @@ -239,5 +257,9 @@ func (f *FileLogger) HangUp() error { // Shutdown closes logfile handle func (f *FileLogger) Shutdown() error { + if f.standardStream { + return nil + } + return f.f.Close() } diff --git a/s3log/file_admin.go b/s3log/file_admin.go index b13ea085..a3789b8c 100644 --- a/s3log/file_admin.go +++ b/s3log/file_admin.go @@ -34,14 +34,14 @@ var _ AuditLogger = &AdminFileLogger{} // InitFileLogger initializes audit logs to local file func InitAdminFileLogger(logname string) (AuditLogger, error) { - f, err := os.OpenFile(logname, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + f, standardStream, err := openLogDestination(logname) if err != nil { return nil, fmt.Errorf("open log: %w", err) } f.WriteString(fmt.Sprintf("log starts %v\n", time.Now())) - return &AdminFileLogger{FileLogger: FileLogger{logfile: logname, f: f}}, nil + return &AdminFileLogger{FileLogger: FileLogger{logfile: logname, f: f, standardStream: standardStream}}, nil } // Log sends log message to file logger