Skip to content

Commit

Permalink
integrate with lumberjack
Browse files Browse the repository at this point in the history
  • Loading branch information
ashmeenkaur committed Nov 17, 2023
1 parent 7d6a208 commit db0b308
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 25 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ require (
golang.org/x/text v0.9.0
golang.org/x/time v0.3.0
google.golang.org/api v0.126.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
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.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
4 changes: 2 additions & 2 deletions internal/fs/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,11 @@ func (t *fsTest) SetUpTestSuite() {
mountCfg.OpContext = ctx

if mountCfg.ErrorLogger == nil {
mountCfg.ErrorLogger = logger.NewError("fuse_errors: ")
mountCfg.ErrorLogger = logger.NewLegacyLogger(logger.LevelError, "fuse_errors: ")
}

if *fDebug {
mountCfg.DebugLogger = logger.NewDebug("fuse: ")
mountCfg.DebugLogger = logger.NewLegacyLogger(logger.LevelDebug, "fuse: ")
}

mfs, err = fuse.Mount(mntDir, server, &mountCfg)
Expand Down
31 changes: 8 additions & 23 deletions internal/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import (
"context"
"fmt"
"io"
"log"
"log/slog"
"log/syslog"
"os"
"runtime/debug"

"github.com/googlecloudplatform/gcsfuse/internal/config"
"gopkg.in/natefinch/lumberjack.v2"
)

// Syslog file contains logs from all different programmes running on the VM.
Expand Down Expand Up @@ -104,27 +104,6 @@ func Close() {
}
}

// NewDebug returns a new logger for logging debug messages with given prefix
// to the log file or stdout.
func NewDebug(prefix string) *log.Logger {
// TODO: delete this method after all slog changed are merged.
return NewLegacyLogger(LevelDebug, prefix)
}

// NewInfo returns a new logger for logging info with given prefix to the log
// file or stdout.
func NewInfo(prefix string) *log.Logger {
// TODO: delete this method after all slog changed are merged.
return NewLegacyLogger(LevelInfo, prefix)
}

// NewError returns a new logger for logging errors with given prefix to the log
// file or stderr.
func NewError(prefix string) *log.Logger {
// TODO: delete this method after all slog changed are merged.
return NewLegacyLogger(LevelError, prefix)
}

// Tracef prints the message with TRACE severity in the specified format.
func Tracef(format string, v ...interface{}) {
defaultLogger.Log(context.Background(), LevelTrace, fmt.Sprintf(format, v...))
Expand Down Expand Up @@ -189,7 +168,13 @@ func (f *loggerFactory) createJsonOrTextHandler(writer io.Writer, levelVar *slog

func (f *loggerFactory) handler(levelVar *slog.LevelVar, prefix string) slog.Handler {
if f.file != nil {
return f.createJsonOrTextHandler(f.file, levelVar, prefix)
fileWriter := &lumberjack.Logger{
Filename: f.file.Name(),
MaxSize: f.logRotateConfig.MaxFileSizeMB,
MaxBackups: f.logRotateConfig.FileCount - 1,
Compress: f.logRotateConfig.Compress,
}
return f.createJsonOrTextHandler(fileWriter, levelVar, prefix)
}

if f.sysWriter != nil {
Expand Down
175 changes: 175 additions & 0 deletions tools/integration_tests/log_rotation/log_rotation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Copyright 2023 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Provides integration tests for log rotation of gcsfuse logs.

package log_rotation

import (
"math/rand"
"os"
"path"
"strings"
"testing"
"time"

"github.com/googlecloudplatform/gcsfuse/internal/config"
"github.com/googlecloudplatform/gcsfuse/tools/integration_tests/util/mounting/static_mounting"
"github.com/googlecloudplatform/gcsfuse/tools/integration_tests/util/operations"
"github.com/googlecloudplatform/gcsfuse/tools/integration_tests/util/setup"
)

const (
testDirName = "LogRotationTest"
testFileName = "file1.txt"
logFileName = "log.txt"
MiB = 1024 * 1024
filePerms = 0644
logDirName = "gcsfuse_integration_test_logs"
)

var (
logFilePath, logDirPath string
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func getMountConfigForLogRotation(maxFileSizeMB, fileCount int, compress bool,
logFilePath string) config.MountConfig {
mountConfig := config.MountConfig{
LogConfig: config.LogConfig{
Severity: config.TRACE,
FilePath: logFilePath,
LogRotateConfig: config.LogRotateConfig{
MaxFileSizeMB: maxFileSizeMB,
FileCount: fileCount,
Compress: compress,
},
},
}
return mountConfig
}

func generateRandomData(t *testing.T, sizeInBytes int64) []byte {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
data := make([]byte, sizeInBytes)
_, err := r.Read(data)
if err != nil {
t.Errorf("error while generating random data to write to file.")
}
return data
}

func writeRandomDataToFileTillLogRotation(t *testing.T) {
testDirPath := setup.SetupTestDirectory(testDirName)

// Generate random data to write to file.
randomData := generateRandomData(t, MiB)
// Setup file to write to.
filePath := path.Join(testDirPath, testFileName)
fh := operations.CreateFile(filePath, filePerms, t)

// Keep performing operations in mounted directory until log file is rotated.
var lastLogFileSize int64 = 0
for {
operations.WriteAt(string(randomData), 0, fh, t)
operations.ReadDirectory(testDirPath, t)
err := fh.Sync()
if err != nil {
t.Errorf("sync failed: %v", err)
}
fi, err := operations.StatFile(logFilePath)
if err != nil {
t.Errorf("stat operation on file %s: %v", logFilePath, err)
}
if (*fi).Size() < lastLogFileSize {
// Log file got rotated as current log file size < last log file size.
break
}
lastLogFileSize = (*fi).Size()
}
operations.CloseFileShouldNotThrowError(fh, t)
}

////////////////////////////////////////////////////////////////////////
// TestMain
////////////////////////////////////////////////////////////////////////

func TestLogRotation(t *testing.T) {
// Perform log rotation 2 times.
for i := 0; i < 2; i++ {
writeRandomDataToFileTillLogRotation(t)
}

// Validate that in the end we have one compressed rotated log file and one
// active log file.
dirEntries := operations.ReadDirectory(logDirPath, t)
if len(dirEntries) != 2 {
t.Errorf("Expected log files in dirEntries folder: 2, got: %d", len(dirEntries))
}
countOfRotatedCompressedFiles := 0
countOfLogFile := 0
for i := 0; i < 2; i++ {
if dirEntries[i].Name() == logFileName {
countOfLogFile++
}
if strings.Contains(dirEntries[i].Name(), "txt.gz") {
countOfRotatedCompressedFiles++
}
}
if countOfLogFile != 1 {
t.Errorf("expected countOfLogFile: 1, got: %d", countOfLogFile)
}
if countOfRotatedCompressedFiles != 1 {
t.Errorf("expected countOfRotatedCompressedFiles: 1, got: %d",
countOfRotatedCompressedFiles)
}
}

func TestMain(m *testing.M) {
setup.ParseSetUpFlags()

setup.ExitWithFailureIfBothTestBucketAndMountedDirectoryFlagsAreNotSet()

// Run tests for mountedDirectory only if --mountedDirectory flag is set.
logDirPath = path.Join("/tmp", logDirName)
logFilePath = path.Join(logDirPath, logFileName)
setup.RunTestsForMountedDirectoryFlag(m)

// Else run tests for testBucket.
// Set up test directory.
setup.SetUpTestDirForTestBucketFlag()

logDirPath = setup.SetUpLogDir(logDirName)
logFilePath = path.Join(logDirPath, logFileName)

configFile := setup.YAMLConfigFile(
getMountConfigForLogRotation(1, 2, true, logFilePath),
)

// Set up flags to run tests on.
// Not setting config file explicitly with 'create-empty-file: false' as it is default.
flags := [][]string{
{"--config-file=" + configFile},
}

successCode := static_mounting.RunTests(flags, m)

// Clean up test directory created.
setup.CleanupDirectoryOnGCS(path.Join(setup.TestBucket(), testDirName))
setup.RemoveBinFileCopiedForTesting()
os.Exit(successCode)
}
16 changes: 16 additions & 0 deletions tools/integration_tests/run_tests_mounted_directory.sh
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,19 @@ sudo umount $MOUNT_DIR
gcsfuse --implicit-dirs=false --rename-dir-limit=3 $TEST_BUCKET_NAME $MOUNT_DIR
GODEBUG=asyncpreemptoff=1 go test ./tools/integration_tests/local_file/... -p 1 --integrationTest -v --mountedDirectory=$MOUNT_DIR --testbucket=$TEST_BUCKET_NAME
sudo umount $MOUNT_DIR

# Run tests with log rotation config.
mkdir /tmp/gcsfuse_integration_test_logs
rm -r /tmp/gcsfuse_integration_test_logs
echo "logging:
file-path: /tmp/gcsfuse_integration_test_logs/log.txt
format: text
severity: trace
log-rotate:
max-file-size-mb: 1
file-count: 1
compress: true
" > /tmp/gcsfuse_config.yaml
gcsfuse --config-file=/tmp/gcsfuse_config.yaml $TEST_BUCKET_NAME $MOUNT_DIR
GODEBUG=asyncpreemptoff=1 go test ./tools/integration_tests/log_rotation/... -p 1 --integrationTest -v --mountedDirectory=$MOUNT_DIR
sudo umount $MOUNT_DIR
9 changes: 9 additions & 0 deletions tools/integration_tests/util/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@ func SetUpTestDirForTestBucketFlag() {
}
}

func SetUpLogDir(logDirName string) (logDir string) {
logDir, err := os.MkdirTemp("", logDirName)
if err != nil {
log.Printf("SetUpLogDir: %v\n", err)
os.Exit(1)
}
return
}

func LogAndExit(s string) {
log.Print(s)
log.Print(string(debug.Stack()))
Expand Down

0 comments on commit db0b308

Please sign in to comment.