logger

package
v0.0.7-1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 8 Imported by: 0

README

GoKit Logger

Go Version License

Logger modular, concurrente y personalizable para aplicaciones Go, desarrollado como parte del ecosistema GoKit.

Está construido únicamente con la biblioteca estándar de Go y ofrece diferentes niveles de logging, campos estructurados, colores ANSI, múltiples destinos de salida y un logger global listo para utilizar.


🌟 Características

  • 8 niveles de log: Trace, Debug, Info, Success, Warn, Error, Fatal y Panic.
  • Thread-safe: las escrituras de cada instancia están protegidas mediante sync.Mutex.
  • Logger global: funciones package-level listas para usar sin crear una instancia manualmente.
  • Campos estructurados: agrega información adicional mediante WithFields().
  • Functional Options: configuración sencilla y flexible mediante opciones.
  • Colores ANSI: temas personalizables por nivel.
  • Temas thread-safe: el tema global utiliza sync.RWMutex.
  • Múltiples destinos: consola, archivo o varios destinos simultáneamente.
  • Salida a archivos: crea automáticamente los directorios necesarios y utiliza modo append.
  • Formateo configurable: fecha, hora y nivel pueden mostrarse u ocultarse.
  • Zero dependencies: utiliza exclusivamente la biblioteca estándar de Go.

📦 Instalación

go get github.com/AndresGT/GoKit/logger

Importa el paquete:

import "github.com/AndresGT/GoKit/logger"

🚀 Inicio rápido

Logger global

Puedes utilizar el logger global directamente:

package main

import "github.com/AndresGT/GoKit/logger"

func main() {
    logger.Trace("Mensaje de trazabilidad")
    logger.Debug("Conectando a la base de datos...")
    logger.Info("Servidor iniciado en el puerto 8080")
    logger.Success("Proceso completado correctamente")
    logger.Warn("Conexión lenta detectada")
    logger.Error("No se pudo conectar con la API externa")
}

Una salida típica puede verse así:

2026-09-24 18:00:00 [INFO] Servidor iniciado en el puerto 8080
2026-09-24 18:00:00 [SUCCESS] Proceso completado correctamente
2026-09-24 18:00:00 [WARN] Conexión lenta detectada
2026-09-24 18:00:00 [ERROR] No se pudo conectar con la API externa

Los colores ANSI están habilitados por defecto.


🧩 Crear un Logger personalizado

La configuración se realiza mediante Functional Options:

package main

import "github.com/AndresGT/GoKit/logger"

func main() {
    log := logger.New(
        logger.WithLevel(logger.DebugLevel),
        logger.WithColor(true),
        logger.WithShowDate(true),
        logger.WithShowTime(true),
    )

    log.Info("Logger personalizado inicializado")

    log.Debug("Ejecutando consulta a la base de datos...")
}

También puedes controlar fecha y hora mediante una sola opción:

log := logger.New(
    logger.WithLevel(logger.DebugLevel),
    logger.WithDateTime(true, true),
)

📖 Niveles de Log

Nivel Instancia Global Descripción
Trace log.Trace() logger.Trace() Diagnóstico muy detallado
Debug log.Debug() logger.Debug() Información para depuración
Info log.Info() logger.Info() Información general
Success log.Success() logger.Success() Operación completada correctamente
Warn log.Warn() logger.Warn() Advertencia
Error log.Error() logger.Error() Error de ejecución
Fatal log.Fatal() logger.Fatal() Registra el mensaje y termina el proceso
Panic log.Panic() logger.Panic() Registra el mensaje y ejecuta panic()
Filtrado por nivel

El logger registra únicamente los mensajes cuyo nivel sea igual o superior al nivel configurado.

Por ejemplo:

log := logger.New(
    logger.WithLevel(logger.InfoLevel),
)

Con esta configuración:

  • Trace → ignorado
  • Debug → ignorado
  • Info → registrado
  • Success → registrado
  • Warn → registrado
  • Error → registrado
  • Fatal → registrado
  • Panic → registrado

⚠️ Fatal y Panic

Estos dos niveles tienen un comportamiento especial.

Fatal

Fatal escribe el mensaje y posteriormente ejecuta:

os.Exit(1)

Ejemplo:

logger.Fatal("No se pudo iniciar el servidor")

El proceso termina inmediatamente.

Panic

Panic escribe el mensaje y posteriormente ejecuta:

panic(message)

Ejemplo:

logger.Panic("Estado interno inválido")

🏷️ Campos estructurados

Los métodos WithFields() permiten adjuntar información contextual utilizando:

map[string]any

Ejemplo:

log.InfoWithFields("Usuario autenticado", map[string]any{
    "user_id": 42,
    "role":    "admin",
    "ip":      "127.0.0.1",
})

Salida:

2026-09-24 18:00:00 [INFO] Usuario autenticado | user_id=42, role=admin, ip=127.0.0.1
Métodos disponibles

Actualmente existen métodos con campos para:

DebugWithFields()
InfoWithFields()
SuccessWithFields()
WarnWithFields()
ErrorWithFields()

También están disponibles en el logger global:

logger.DebugWithFields(...)
logger.InfoWithFields(...)
logger.SuccessWithFields(...)
logger.WarnWithFields(...)
logger.ErrorWithFields(...)
Ejemplo práctico
log.ErrorWithFields("Error en la base de datos", map[string]any{
    "query":       "SELECT * FROM users",
    "error":       err.Error(),
    "duration_ms": 1500,
})

Salida:

2026-09-24 18:00:00 [ERROR] Error en la base de datos | query=SELECT * FROM users, error=connection timeout, duration_ms=1500

El orden de los campos provenientes de un map no está garantizado por Go.


⚙️ Configuración

La configuración interna utiliza la siguiente estructura:

type Config struct {
    Writer      io.Writer
    Level       Level
    EnableColor bool
    ShowDate    bool
    ShowTime    bool
    ShowLevel   bool
}
Valores predeterminados

El logger utiliza:

Level       = InfoLevel
Writer      = os.Stdout
EnableColor = true
ShowDate    = true
ShowTime    = true
ShowLevel   = true

Puedes obtener una copia de la configuración predeterminada con:

cfg := logger.NewConfig()

🛠️ Functional Options

WithLevel

Establece el nivel mínimo de logging:

log := logger.New(
    logger.WithLevel(logger.DebugLevel),
)

Si se proporciona un nivel inválido, la opción no modifica la configuración.


WithWriter

Permite definir un destino personalizado:

log := logger.New(
    logger.WithWriter(os.Stdout),
)

También puedes utilizar cualquier implementación de:

io.Writer

Por ejemplo:

var buffer bytes.Buffer

log := logger.New(
    logger.WithWriter(&buffer),
)

WithColor

Activa o desactiva los colores ANSI:

log := logger.New(
    logger.WithColor(false),
)

WithShowDate

Controla la fecha:

log := logger.New(
    logger.WithShowDate(false),
)

WithShowTime

Controla la hora:

log := logger.New(
    logger.WithShowTime(false),
)

WithDateTime

Permite controlar fecha y hora simultáneamente:

log := logger.New(
    logger.WithDateTime(true, false),
)

En este ejemplo se muestra únicamente la fecha.


WithFileOutput

Configura directamente la salida hacia un archivo:

log := logger.New(
    logger.WithFileOutput("logs/app.log"),
)

El archivo se abre en modo append.

Además, cuando se utiliza WithFileOutput, los colores ANSI se desactivan automáticamente.

Si no es posible abrir o crear el archivo, la opción conserva el writer anterior y escribe el error en stderr.


📤 Destinos de salida

El paquete proporciona varias funciones para trabajar con diferentes destinos.

Consola
writer := logger.NewConsoleWriter()

log := logger.New(
    logger.WithWriter(writer),
)

NewConsoleWriter() devuelve os.Stdout.


Archivo
fileWriter, err := logger.NewFileWriter("logs/app.log")
if err != nil {
    panic(err)
}

log := logger.New(
    logger.WithWriter(fileWriter),
)

NewFileWriter():

  • Crea los directorios intermedios si no existen.
  • Crea el archivo si no existe.
  • Abre el archivo en modo append.
  • Devuelve un io.Writer.
  • Devuelve un error si no puede crear o abrir el archivo.

Consola + archivo

Puedes escribir simultáneamente en varios destinos:

consoleWriter := logger.NewConsoleWriter()

fileWriter, err := logger.NewFileWriter("logs/app.log")
if err != nil {
    panic(err)
}

combinedWriter := logger.NewMultiWriter(
    consoleWriter,
    fileWriter,
)

log := logger.New(
    logger.WithWriter(combinedWriter),
)

NewMultiWriter() utiliza internamente:

io.MultiWriter

y acepta cualquier cantidad de io.Writer.


🎨 Temas y colores

Los colores de los niveles se administran mediante Theme.

La estructura es:

type Theme struct {
    Trace   string
    Debug   string
    Info    string
    Success string
    Warn    string
    Error   string
    Fatal   string
    Panic   string
    Reset   string
}
Tema predeterminado
Nivel Color
Trace Gris
Debug Azul
Info Cyan
Success Verde
Warn Amarillo
Error Rojo
Fatal Magenta
Panic Fondo rojo + texto blanco
Crear un tema personalizado
customTheme := logger.Theme{
    Trace:   "\033[90m",
    Debug:   "\033[34m",
    Info:    "\033[36m",
    Success: "\033[32m",
    Warn:    "\033[33m",
    Error:   "\033[31m",
    Fatal:   "\033[35m",
    Panic:   "\033[41m\033[97m",
    Reset:   "\033[0m",
}

logger.SetTheme(customTheme)
Restaurar el tema
logger.ResetTheme()
Obtener el tema actual
theme := logger.GetTheme()

La lectura y modificación del tema global están protegidas mediante sync.RWMutex.


🌐 Logger global

GoKit Logger incluye una instancia global creada automáticamente.

Esto permite escribir:

logger.Info("Aplicación iniciada")

sin necesidad de crear manualmente:

log := logger.New(...)
Cambiar el logger global

Puedes establecer una instancia personalizada como logger predeterminado:

customLogger := logger.New(
    logger.WithLevel(logger.DebugLevel),
    logger.WithColor(false),
)

logger.SetDefault(customLogger)

A partir de ese momento:

logger.Debug("Mensaje de debug")
logger.Info("Mensaje informativo")
logger.Error("Ocurrió un error")

utilizarán la instancia configurada.

Obtener el logger global
log := logger.GetDefault()

log.Info("Usando el logger global")

SetDefault() y GetDefault() utilizan sync.RWMutex para proteger el acceso concurrente al logger global.


🧵 Concurrencia y Thread-Safety

El logger está diseñado para utilizarse desde múltiples goroutines.

Cada instancia de Logger contiene un mutex interno:

type Logger struct {
    mu        sync.Mutex
    config    Config
    formatter *Formatter
}

Las escrituras se sincronizan para evitar que varios mensajes se mezclen cuando diferentes goroutines escriben simultáneamente.

Ejemplo:

package main

import (
    "sync"

    "github.com/AndresGT/GoKit/logger"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 100; i++ {
        wg.Add(1)

        go func(id int) {
            defer wg.Done()

            logger.InfoWithFields(
                "Procesando worker",
                map[string]any{
                    "worker": id,
                },
            )
        }(i)
    }

    wg.Wait()
}

El acceso al logger global también está protegido:

defaultLoggerMu sync.RWMutex

y el tema global utiliza:

themeMu sync.RWMutex

📝 Formateo

El formateador utiliza strings.Builder para construir cada línea.

El formato depende de las opciones configuradas.

Fecha + hora + nivel

Configuración:

logger.New(
    logger.WithDateTime(true, true),
)

Salida:

2026-09-24 18:00:00 [INFO] Servidor iniciado
Solo fecha
logger.New(
    logger.WithDateTime(true, false),
)

Salida:

2026-09-24 [INFO] Servidor iniciado
Solo hora
logger.New(
    logger.WithDateTime(false, true),
)

Salida:

18:00:00 [INFO] Servidor iniciado
Sin fecha ni hora
logger.New(
    logger.WithDateTime(false, false),
)

Salida:

[INFO] Servidor iniciado
Ocultar el nivel

La configuración también permite controlar ShowLevel directamente:

cfg := logger.NewConfig()
cfg.ShowLevel = false

🔌 Uso con io.Writer

Una de las ventajas del logger es que no está limitado a os.Stdout.

Puedes utilizar cualquier tipo que implemente:

io.Writer

Por ejemplo:

var buffer bytes.Buffer

log := logger.New(
    logger.WithWriter(&buffer),
)

log.Info("Mensaje de prueba")

fmt.Println(buffer.String())

Esto también facilita la integración con otros sistemas de logging, buffers, archivos o componentes de una aplicación.


🧪 Pruebas

Para ejecutar las pruebas:

go test ./...

Para ejecutarlas con el detector de condiciones de carrera:

go test -race ./...

También puedes utilizar:

go test -v -race ./...

El uso de -race es especialmente recomendable cuando se realizan cambios relacionados con concurrencia, logger global, temas o escritura simultánea.


📁 Estructura del paquete

La implementación está organizada por responsabilidades:

logger/
├── config.go
├── doc.go
├── errors.go
├── formatter.go
├── levels.go
├── logger.go
├── options.go
├── output.go
├── theme.go
└── README.md
config.go

Define:

  • Config
  • configuración predeterminada
  • NewConfig()
levels.go

Define:

  • Level
  • niveles disponibles
  • validación
  • nombres
  • prefijos
  • colores
logger.go

Contiene:

  • Logger
  • creación de instancias
  • métodos de logging
  • campos estructurados
  • logger global
  • control de concurrencia
options.go

Contiene las opciones de configuración:

  • WithLevel
  • WithWriter
  • WithColor
  • WithDateTime
  • WithShowDate
  • WithShowTime
  • WithFileOutput
formatter.go

Se encarga de construir el texto final del log.

output.go

Proporciona:

  • NewConsoleWriter
  • NewFileWriter
  • NewMultiWriter
theme.go

Gestiona:

  • Theme
  • SetTheme
  • GetTheme
  • ResetTheme
  • colores ANSI
  • sincronización del tema global
errors.go

Define errores relacionados con el paquete:

var (
    ErrInvalidLevel    = errors.New("nivel de log inválido")
    ErrWriteFailed     = errors.New("fallo al escribir el mensaje de log")
    ErrInvalidFilePath = errors.New("ruta de archivo de log inválida o inaccesible")
)

📚 API principal

Creación
logger.New(...)
logger.NewConfig()
Logger global
logger.SetDefault(...)
logger.GetDefault()
Logging
logger.Trace(...)
logger.Debug(...)
logger.Info(...)
logger.Success(...)
logger.Warn(...)
logger.Error(...)
logger.Fatal(...)
logger.Panic(...)
Campos
logger.DebugWithFields(...)
logger.InfoWithFields(...)
logger.SuccessWithFields(...)
logger.WarnWithFields(...)
logger.ErrorWithFields(...)
Configuración
logger.WithLevel(...)
logger.WithWriter(...)
logger.WithColor(...)
logger.WithDateTime(...)
logger.WithShowDate(...)
logger.WithShowTime(...)
logger.WithFileOutput(...)
Outputs
logger.NewConsoleWriter()
logger.NewFileWriter(...)
logger.NewMultiWriter(...)
Temas
logger.SetTheme(...)
logger.GetTheme()
logger.ResetTheme()

💡 Ejemplo completo

package main

import (
    "sync"

    "github.com/AndresGT/GoKit/logger"
)

func main() {
    log := logger.New(
        logger.WithLevel(logger.DebugLevel),
        logger.WithColor(true),
        logger.WithDateTime(true, true),
    )

    log.Info("Aplicación iniciada")

    log.DebugWithFields("Configuración cargada", map[string]any{
        "environment": "development",
        "port":        8080,
    })

    log.SuccessWithFields("Usuario autenticado", map[string]any{
        "user_id": 42,
        "role":    "admin",
    })

    log.Warn("La conexión está tardando más de lo esperado")

    log.ErrorWithFields("Error al consultar la base de datos", map[string]any{
        "query": "SELECT * FROM users",
    })

    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)

        go func(id int) {
            defer wg.Done()

            log.InfoWithFields(
                "Worker ejecutándose",
                map[string]any{
                    "worker": id,
                },
            )
        }(i)
    }

    wg.Wait()

    log.Info("Aplicación finalizada")
}

📄 Licencia

Este proyecto se distribuye bajo la licencia MIT.

Consulta el archivo LICENSE para obtener los términos completos de la licencia.

Documentation

Overview

Package logger provides a modular, concurrent-safe, and colorful logging utility for GoKit applications.

It supports multiple log levels (Trace, Debug, Info, Success, Warn, Error, Fatal, Panic), customizable themes, and flexible output destinations (console, file, or both via io.MultiWriter).

Basic usage:

log := logger.New(logger.NewConfig())
log.Info("Aplicación iniciada correctamente")
log.Error("No se pudo conectar a la base de datos")

Advanced usage with file output and custom level:

cfg := logger.NewConfig()
cfg.Level = logger.DebugLevel
cfg.Writer = logger.NewMultiWriter(logger.NewConsoleWriter(), fileWriter)
log := logger.New(cfg)
log.Debug("Conectando a la base de datos...")

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidLevel    = errors.New("nivel de log inválido")
	ErrWriteFailed     = errors.New("fallo al escribir el mensaje de log")
	ErrInvalidFilePath = errors.New("ruta de archivo de log inválida o inaccesible")
)

Functions

func Debug

func Debug(message string)

func DebugWithFields added in v0.0.7

func DebugWithFields(msg string, fields map[string]any)

func Error

func Error(message string)

func ErrorWithFields added in v0.0.7

func ErrorWithFields(msg string, fields map[string]any)

func Fatal

func Fatal(message string)

func Info

func Info(message string)

func InfoWithFields added in v0.0.7

func InfoWithFields(msg string, fields map[string]any)

func NewConsoleWriter

func NewConsoleWriter() io.Writer

NewConsoleWriter devuelve un io.Writer que escribe en la salida estándar (consola). Es el comportamiento predeterminado, pero se expone explícitamente por claridad.

func NewFileWriter

func NewFileWriter(filePath string) (io.Writer, error)

NewFileWriter crea y devuelve un io.Writer que escribe en el archivo especificado. Si el archivo no existe, intenta crearlo. Si los directorios intermedios no existen, intenta crearlos también. El archivo se abre en modo append (añadir al final).

Ejemplo de uso:

writer, err := logger.NewFileWriter("logs/app.log")
if err != nil {
    log.Fatal(err)
}

func NewMultiWriter added in v0.0.7

func NewMultiWriter(writers ...io.Writer) io.Writer

NewMultiWriter combina múltiples destinos de escritura (por ejemplo, consola y archivo) en un único io.Writer. Cada mensaje de log se escribirá en todos los destinos proporcionados.

Ejemplo de uso (Consola + Archivo):

fileWriter, _ := logger.NewFileWriter("logs/app.log")
combinedWriter := logger.NewMultiWriter(logger.NewConsoleWriter(), fileWriter)

func Panic added in v0.0.7

func Panic(message string)

func ResetTheme added in v0.0.7

func ResetTheme()

func SetDefault

func SetDefault(l *Logger)

func SetTheme added in v0.0.7

func SetTheme(t Theme)

func Success

func Success(message string)

func SuccessWithFields added in v0.0.7

func SuccessWithFields(msg string, fields map[string]any)

func Trace added in v0.0.7

func Trace(message string)

func Warn

func Warn(message string)

func WarnWithFields added in v0.0.7

func WarnWithFields(msg string, fields map[string]any)

Types

type Config

type Config struct {
	Writer      io.Writer
	Level       Level
	EnableColor bool
	ShowDate    bool
	ShowTime    bool
	ShowLevel   bool
}

func NewConfig added in v0.0.7

func NewConfig() Config

type Formatter added in v0.0.7

type Formatter struct {
	// contains filtered or unexported fields
}

func NewFormatter added in v0.0.7

func NewFormatter(cfg Config) *Formatter

func (*Formatter) Format added in v0.0.7

func (f *Formatter) Format(level Level, message string) string

type Level

type Level uint8
const (
	TraceLevel Level = iota
	DebugLevel
	InfoLevel
	SuccessLevel
	WarnLevel
	ErrorLevel
	FatalLevel
	PanicLevel
)

func (Level) Color added in v0.0.7

func (l Level) Color() string

func (Level) Enabled added in v0.0.7

func (l Level) Enabled(min Level) bool

func (Level) IsValid added in v0.0.7

func (l Level) IsValid() bool

func (Level) Prefix added in v0.0.7

func (l Level) Prefix() string

func (Level) String

func (l Level) String() string

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

func GetDefault added in v0.0.7

func GetDefault() *Logger

func New

func New(opts ...Option) *Logger

func (*Logger) Debug

func (l *Logger) Debug(message string)

func (*Logger) DebugWithFields added in v0.0.7

func (l *Logger) DebugWithFields(message string, fields map[string]any)

func (*Logger) Error

func (l *Logger) Error(message string)

func (*Logger) ErrorWithFields added in v0.0.7

func (l *Logger) ErrorWithFields(message string, fields map[string]any)

func (*Logger) Fatal

func (l *Logger) Fatal(message string)

func (*Logger) Info

func (l *Logger) Info(message string)

func (*Logger) InfoWithFields added in v0.0.7

func (l *Logger) InfoWithFields(message string, fields map[string]any)

func (*Logger) Panic added in v0.0.7

func (l *Logger) Panic(message string)

func (*Logger) Success

func (l *Logger) Success(message string)

func (*Logger) SuccessWithFields added in v0.0.7

func (l *Logger) SuccessWithFields(message string, fields map[string]any)

func (*Logger) Trace added in v0.0.7

func (l *Logger) Trace(message string)

func (*Logger) Warn

func (l *Logger) Warn(message string)

func (*Logger) WarnWithFields added in v0.0.7

func (l *Logger) WarnWithFields(message string, fields map[string]any)

type Option added in v0.0.7

type Option func(*Config)

func WithColor added in v0.0.7

func WithColor(enable bool) Option

func WithDateTime added in v0.0.7

func WithDateTime(showDate, showTime bool) Option

func WithFileOutput added in v0.0.7

func WithFileOutput(filePath string) Option

func WithLevel added in v0.0.7

func WithLevel(level Level) Option

func WithShowDate

func WithShowDate(showDate bool) Option

func WithShowTime

func WithShowTime(showTime bool) Option

func WithWriter added in v0.0.7

func WithWriter(w io.Writer) Option

type Theme added in v0.0.7

type Theme struct {
	Trace   string
	Debug   string
	Info    string
	Success string
	Warn    string
	Error   string
	Fatal   string
	Panic   string
	Reset   string
}

func GetTheme

func GetTheme() Theme

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL