Ctrl K
ComunidadGuías…

common/sys_log.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package common

import (
	"fmt"
	"io"
	"net"
	"os"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
)

// LogWriterMu protects concurrent access to gin.DefaultWriter/gin.DefaultErrorWriter
// during log file rotation. Acquire RLock when reading/writing through the writers,
// acquire Lock when swapping writers and closing old files.
var LogWriterMu sync.RWMutex

// LogWriter and ErrorLogWriter write to gin.DefaultWriter and
// gin.DefaultErrorWriter as they are at write time. Middleware that keeps its
// writer from startup, such as the gin access logger and panic recovery, must
// use them: log rotation swaps the gin writers and closes the old log file.
var (
	LogWriter      io.Writer = currentLogWriter{}
	ErrorLogWriter io.Writer = currentLogWriter{errorStream: true}
)

type currentLogWriter struct {
	errorStream bool
}

func (w currentLogWriter) Write(p []byte) (int, error) {
	LogWriterMu.RLock()
	defer LogWriterMu.RUnlock()
	if w.errorStream {
		return gin.DefaultErrorWriter.Write(p)
	}
	return gin.DefaultWriter.Write(p)
}

func SysLog(s string) {
	t := time.Now()
	LogWriterMu.RLock()
	_, _ = fmt.Fprintf(gin.DefaultWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s)
	LogWriterMu.RUnlock()
}

func SysError(s string) {
	t := time.Now()
	LogWriterMu.RLock()
	_, _ = fmt.Fprintf(gin.DefaultErrorWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s)
	LogWriterMu.RUnlock()
}

func FatalLog(v ...any) {
	t := time.Now()
	LogWriterMu.RLock()
	_, _ = fmt.Fprintf(gin.DefaultErrorWriter, "[FATAL] %v | %v \n", t.Format("2006/01/02 - 15:04:05"), v)
	LogWriterMu.RUnlock()
	os.Exit(1)
}

func LogStartupSuccess(startTime time.Time, host, port string) {
	duration := time.Since(startTime)
	durationMs := duration.Milliseconds()

	// Get network IPs
	networkIps := GetNetworkIps()

	LogWriterMu.RLock()
	defer LogWriterMu.RUnlock()

	if SessionCookieSecure == false {
		// Warn when the local HTTP compatibility mode disables cookie transport
		// security and refresh/logout Origin validation.
		fmt.Fprintf(gin.DefaultWriter, "\n")
		fmt.Fprintf(gin.DefaultWriter, "  \033[33m%s\033[0m\n", LogText("Warning: Refresh cookie is not secure and refresh/logout Origin validation is disabled. Please set SESSION_COOKIE_SECURE=true in production."))
		fmt.Fprintf(gin.DefaultWriter, "\n")
	}

	fmt.Fprintf(gin.DefaultWriter, "\n")
	fmt.Fprintf(gin.DefaultWriter, "  \033[32m%s %s\033[0m  %s\n", SystemName, Version, LogText("ready in %d ms", durationMs))
	fmt.Fprintf(gin.DefaultWriter, "\n")

	if ip := net.ParseIP(host); host != "" && !ip.IsUnspecified() {
		label := LogText("Network:")
		if ip.IsLoopback() {
			label = LogText("Local:")
		}
		fmt.Fprintf(gin.DefaultWriter, "  ➜  \033[1m%-8s\033[0m http://%s/\n", label, net.JoinHostPort(host, port))
		fmt.Fprintf(gin.DefaultWriter, "\n")
		return
	}

	if !IsRunningInContainer() {
		fmt.Fprintf(gin.DefaultWriter, "  ➜  \033[1m%-8s\033[0m http://localhost:%s/\n", LogText("Local:"), port)
	}

	for _, ip := range networkIps {
		fmt.Fprintf(gin.DefaultWriter, "  ➜  \033[1m%-8s\033[0m http://%s:%s/\n", LogText("Network:"), ip, port)
	}

	fmt.Fprintf(gin.DefaultWriter, "\n")
}