Skip to content

Commit

Permalink
fix logs in docker
Browse files Browse the repository at this point in the history
  • Loading branch information
iloveicedgreentea committed Dec 14, 2024
1 parent 3e78360 commit 3e87333
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 72 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ EXPOSE 3000

ENV TZ=America/New_York
ENV GIN_MODE=release
ENV LOG_TO_FILE=true
ENV LOG_FILE=true

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
29 changes: 27 additions & 2 deletions cmd/gowatchit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,19 @@ func noCache() gin.HandlerFunc {
func main() {
// init context
ctx := context.Background()
log := logger.GetLoggerFromContext(ctx)

// reuse logger object in calls
err := logger.InitLoggerFile()
if err != nil {
logger.Fatal("Failed to initialize the logger: ", err)
}
defer func() {
if err := logger.CleanupLogger(); err != nil {
logger.Fatal("Failed to close the logger: ", err)
}
}()

log := logger.GetLogger()
logger.AddLoggerToContext(ctx, log)

log.Info("Starting up please wait until the server is ready...")
Expand Down Expand Up @@ -62,8 +72,12 @@ func main() {
if db == nil {
logger.Fatal("db is nil")
}

// close db when done
defer func() {
if err := logger.CleanupLogger(); err != nil {
logger.Fatal("Failed to close the logger: ", err)
}
log.Debug("Closing the database connection")
if err := db.Close(); err != nil {
logger.Fatal("Failed to close the database: ", err)
Expand Down Expand Up @@ -92,7 +106,18 @@ func main() {

// cors
router.Use(func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
origin := c.Request.Header.Get("Origin")

// Define allowed origins
allowedOrigins := map[string]bool{
"http://localhost:5173": true, // bun
"http://localhost:3000": true, // nginx
}

// Check if origin is allowed and set the header
if allowedOrigins[origin] {
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
}
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
Expand Down
8 changes: 2 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ services:
- '3000:3000'
environment:
LOG_LEVEL: 'debug'
LOG_TO_FILE: 'true'
LOG_FILE: 'true'
BASE_DIR: '/data'
volumes:
- data_volume:/data

volumes:
data_volume:
driver: local
- ./docker/data/:/data
11 changes: 1 addition & 10 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
#!/bin/sh

# Kill any existing nginx processes
pkill nginx || true

# Wait a moment for the port to be released
sleep 1

# Start nginx
nginx -g "daemon off;" &

# Start the main app
ls
pwd
stat "/gowatchit"
exec /gowatchit
/gowatchit
17 changes: 9 additions & 8 deletions internal/database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,33 @@ import (
func GetDB(path string) (*sql.DB, error) {
log := logger.GetLogger()
if path != ":memory:" {

log.Debug("not using in-memory database", slog.String("path", path))
// Check if the file exists
dirInfo, err := os.Stat(path)
_, err := os.Stat(path)
if err != nil {
return nil, fmt.Errorf("failed to stat database file: %w", err)
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to stat database file: %w", err)
}
log.Debug("Database file does not exist", slog.String("path", path))
}
log.Debug("Directory info", slog.Any("dirInfo", dirInfo))
log.Debug("Checking if database file exists", slog.String("path", path))
if os.IsNotExist(err) {
// Create the directory if it doesn't exist
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o750); err != nil {
return nil, err
return nil, fmt.Errorf("failed to create database directory: %w", err)
}
log.Debug("Creating database directory", slog.String("dir", dir))

// Create an empty file
// TODO: is path ever user supplied? potential directory traversal
file, err := os.Create(path) // #nosec
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create database file: %w", err)
}
log.Debug("File created", slog.String("path", path))
err = file.Close()
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to close created database file: %w", err)
}
}
}
Expand Down
113 changes: 69 additions & 44 deletions internal/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,87 +11,112 @@ import (
// loggerKey is used as the key for storing the logger in the context
type loggerKey struct{}

var defaultLogger *slog.Logger
var (
defaultLogger *slog.Logger
logFile *os.File // Keep track of the log file
)

func Fatal(msg string, args ...any) {
slog.Error(msg, args...)
os.Exit(1)
}

func InitLoggerFile() error {
if os.Getenv("LOG_FILE") == "true" {
logFilePath := getLogFilePath()

// Remove old log file if it exists
err := os.Remove(logFilePath)
if err != nil && !os.IsNotExist(err) {
return err
}

// Create new log file
// #nosec G304 - We are not using user input to create the file
file, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
if err != nil {
return err
}

// Store the file handle globally
logFile = file

// Create a new logger with the file
handler := slog.NewJSONHandler(io.MultiWriter(file, os.Stdout), &slog.HandlerOptions{
Level: getLogLevel(),
AddSource: true,
})

// Set up the default logger
defaultLogger = slog.New(handler)
slog.SetDefault(defaultLogger)
}
return nil
}

func getLogLevel() slog.Level {
if strings.ToLower(os.Getenv("LOG_LEVEL")) == "debug" {
return slog.LevelDebug
}
return slog.LevelInfo
}

func getLogFilePath() string {
env := os.Getenv("LOG_ENV")
if env == "" {
// if this is unset assume running in docker
env, ok := os.LookupEnv("LOG_ENV")
if env == "" || !ok {
return "/data/app.log"
}

return "./applog.log"
}

// CleanupLogger ensures the log file is properly closed
func CleanupLogger() error {
if logFile != nil {
return logFile.Close()
}
return nil
}

// AddLoggerToContext adds a slog.Logger to the context
func AddLoggerToContext(ctx context.Context, logger *slog.Logger) context.Context {
return context.WithValue(ctx, loggerKey{}, logger)
}

// GetLoggerFromContext retrieves the slog.Logger from the context
func GetLoggerFromContext(ctx context.Context) *slog.Logger {
logger, ok := ctx.Value(loggerKey{}).(*slog.Logger)
if !ok {
// Return the default logger if not found in context
return GetLogger()
if logger, ok := ctx.Value(loggerKey{}).(*slog.Logger); ok {
return logger
}
return logger
return GetLogger()
}

// GetLogger returns the default slog.Logger instance

func GetLogger() *slog.Logger {
if defaultLogger == nil {
var handler slog.Handler
level := getLogLevel()

// Determine the log level
level := slog.LevelInfo
if strings.ToLower(os.Getenv("LOG_LEVEL")) == "debug" {
level = slog.LevelDebug
}

// Set up logging to file if LOG_FILE is "true"
if os.Getenv("LOG_FILE") == "true" {
logFilePath := getLogFilePath()
// Remove old log file
err := os.Remove(logFilePath)
if err != nil && !os.IsNotExist(err) {
slog.Error("Failed to remove log file", "error", err)
}

// Open a new log file
// #nosec G304 - We are not using user input to create the file
file, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
if err != nil {
slog.Error("Failed to open log file", "error", err)
} else {
// Create a multi-writer for both file and stdout
multiWriter := io.MultiWriter(file, os.Stdout)
handler = slog.NewJSONHandler(multiWriter, &slog.HandlerOptions{
Level: level,
AddSource: true,
})
}
}

// If no file handler was created, use a default stdout handler
if handler == nil {
if os.Getenv("LOG_FILE") == "true" && logFile != nil {
// Use existing log file if available
multiWriter := io.MultiWriter(logFile, os.Stdout)
handler = slog.NewJSONHandler(multiWriter, &slog.HandlerOptions{
Level: level,
AddSource: true,
})
} else {
// Fallback to stdout only
handler = slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: level,
AddSource: true,
})
}

// Create the logger
defaultLogger = slog.New(handler)

// Set as default logger
slog.SetDefault(defaultLogger)
}

return defaultLogger
}

Expand Down
2 changes: 1 addition & 1 deletion web/src/components/providers/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function ToastContextProvider({
}) {
const [toasts, setToasts] = useState<Toast[]>([]);
const [isConnected, setIsConnected] = useState(true);
const [retryDelay, setRetryDelay] = useState(INITIAL_RETRY_DELAY);
const [_, setRetryDelay] = useState<number>(INITIAL_RETRY_DELAY);

// Remove old toasts when we exceed the limit
useEffect(() => {
Expand Down

0 comments on commit 3e87333

Please sign in to comment.