cassandra-bigtable-migration-tools/cassandra-bigtable-proxy/testing/compliance/utility/logger.go (80 lines of code) (raw):
/*
* Copyright (C) 2025 Google LLC
*
* 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.
*/
package utility
import (
"fmt"
"io"
"log"
"os"
"strings"
"testing"
"time"
)
var Logger = log.New(os.Stdout, "", log.LstdFlags)
// SetupLogger initializes logging to both a file and console if file logging is enabled.
func SetupLogger(logFileName string, enableFileLogging bool) (*os.File, error) {
var logFile *os.File
var err error
if enableFileLogging {
if logFileName == "" {
logFileName = fmt.Sprintf("test_result_%d.log", time.Now().Unix())
}
logFile, err = setupLogging(logFileName)
if err != nil {
return nil, fmt.Errorf("failed to set up logging: %v", err)
}
Logger = log.New(io.MultiWriter(logFile, os.Stdout), "", log.LstdFlags)
}
return logFile, nil
}
func setupLogging(logPath string) (*os.File, error) {
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return nil, fmt.Errorf("failed to open log file: %v", err)
}
// Log to both console and file
multi := io.MultiWriter(logFile, os.Stdout)
log.SetOutput(multi)
return logFile, nil
}
// LogSuccess logs a successful query execution with optional test integration.
func LogSuccess(t *testing.T, opDesc, queryType string) {
msg := fmt.Sprintf("✅ Passed (%s): %s\n", strings.ToUpper(queryType), opDesc)
Logger.Print(msg)
if t != nil {
t.Log(msg) // Also log in the testing framework if `t` is provided
}
}
// LogFailure logs a query execution failure with expected vs actual differences.
func LogFailure(t *testing.T, filename, opDesc, query, diff string) {
msg := fmt.Sprintf("❌ Failed(%s) \nDescription:%s \nQuery: %s\nDifference: %s\n", filename, opDesc, query, diff)
Logger.Print(msg)
if t != nil {
t.Errorf("%s", msg)
}
}
// LogError logs an error when query execution fails.
func LogError(t *testing.T, filename, opDesc, query string, err error) {
msg := fmt.Sprintf("\n❌ Error(%s)\nDescription:%s\nQuery: %s\nError: %v\n", filename, opDesc, query, err)
Logger.Print(msg)
if t != nil {
t.Errorf("%s", msg)
}
}
// LogWarning logs warnings or unexpected but non-fatal conditions.
func LogWarning(t *testing.T, msg string) {
Logger.Printf("\n❌ %s\n", msg)
if t != nil {
t.Errorf("%s", msg)
}
}
// LogWarning logs warnings or unexpected but non-fatal conditions.
func LogTestFatal(t *testing.T, msg string) {
Logger.Printf("\n❌ %s\n", msg)
if t != nil {
t.Fatalf("%s", msg)
}
}
// LogWarning logs warnings or unexpected but non-fatal conditions.
func LogTestError(msg string) {
Logger.Printf("\n❌ %s\n", msg)
}
// LogInfo logs general info messages.
func LogInfo(msg string) {
Logger.Printf("\nℹ️ %s\n", msg)
}
// LogFatal logs a critical error message and exits the application.
func LogFatal(msg string) {
Logger.Printf("\n❌ %s\n", msg)
}
// LogSectionDivider logs a section divider for test case separation.
func LogSectionDivider() {
Logger.Println("\n-------------------------------------------------------")
}