logie

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 6, 2025 License: MIT Imports: 0 Imported by: 0

README

codecov Go Report Card PkgGoDev

Logie

A flexible structured logging package built on top of zerolog with module-level log control.

Installation

go get github.com/Michi01/logie

Features

  • Module-based logging with independent log levels
  • Global and per-module log level control
  • Structured logging with fields
  • Console output formatting
  • Built-in support for common fields (hostname, PID, Go version)

Quick Start

package main

import "github.com/Michi01/logie"

func main() {
    // Get default logger with console output
    logger := logie.DefaultLogger()
    
    // Basic logging
    logger.Info("Hello, World!")
    
    // Logging with fields
    logger.WithField("user", "john").Info("User logged in")
}

Creating Loggers

Default Logger
logger := logie.DefaultLogger()

The default logger includes:

  • Console output with timestamps
  • Hostname
  • Process ID
  • Go version
  • Application version (if BuildVersion is set)
Custom Logger
output := zerolog.ConsoleWriter{
    Out:        os.Stdout,
    TimeFormat: time.RFC3339,
}

logger := logie.New(output)
Module-Based Logging
logger := logie.New(
    output,
    logie.WithModule("auth"),
)

Log Levels

Available levels: Panic, Fatal, Error, Warn, Info, Debug, Trace

Environment Configuration
package main

import (
    "os"
    "strings"
    
    "github.com/rs/zerolog"
    "github.com/Michi01/logie"
)

func init() {
    // Set global log level from environment
    if levelStr := os.Getenv("LOG_LEVEL"); levelStr != "" {
        level := parseLogLevel(levelStr, zerolog.InfoLevel)
        logie.SetGlobalLevel(level)
    }
    
    // Configure module levels from environment
    // Format: MODULE_LOG_LEVEL_<MODULE>=<LEVEL>
    // Example: MODULE_LOG_LEVEL_AUTH=debug
    for _, env := range os.Environ() {
        if !strings.HasPrefix(env, "MODULE_LOG_LEVEL_") {
            continue
        }
        
        parts := strings.SplitN(env, "=", 2)
        if len(parts) != 2 {
            continue
        }
        
        module := strings.TrimPrefix(parts[0], "MODULE_LOG_LEVEL_")
        module = strings.ToLower(module)
        level := parseLogLevel(parts[1], zerolog.InfoLevel)
        
        logie.SetModuleLevel(module, level)
    }
}

// parseLogLevel converts a string level to zerolog.Level with a default fallback
func parseLogLevel(level string, defaultLevel zerolog.Level) zerolog.Level {
    switch strings.ToLower(level) {
    case "panic":
        return zerolog.PanicLevel
    case "fatal":
        return zerolog.FatalLevel
    case "error":
        return zerolog.ErrorLevel
    case "warn":
        return zerolog.WarnLevel
    case "info":
        return zerolog.InfoLevel
    case "debug":
        return zerolog.DebugLevel
    default:
        return defaultLevel
    }
}

### Setting Global Level

```go
logie.SetGlobalLevel(zerolog.DebugLevel)
Setting Module Level
logie.SetModuleLevel("auth", zerolog.DebugLevel)

Adding Context

Single Field
logger.WithField("user_id", 123).Info("User action")
Multiple Fields
logger.WithFields(map[string]interface{}{
    "user_id": 123,
    "action": "login",
}).Info("User action")

Formatted Logging

All log levels support formatted messages:

logger.Infof("Processing item %d of %d", current, total)
logger.Errorf("Failed to process: %v", err)
Environment Variables
  • LOG_LEVEL: Sets the global logging level (default: "info")
  • MODULE_LOG_LEVEL_<MODULE>: Sets the log level for a specific module
    • Example: MODULE_LOG_LEVEL_AUTH=debug
    • Example: MODULE_LOG_LEVEL_DATABASE=error

Usage Patterns

Global Logger
package main

import "github.com/Michi01/logie"

var log *logie.Logger

func init() {
    log = logie.DefaultLogger()
}

func main() {
    log.Info("Application started")
}
Dependency Injection Pattern
// auth/auth.go
package auth

type Service struct {
    log *logie.Logger
}

func NewService(logger *logie.Logger) *Service {
    return &Service{
        log: logger.WithModule("auth"),
    }
}

func (s *Service) Login(username string) {
    s.log.WithField("user", username).Info("Login attempt")
}

// database/db.go
package database

type Repository struct {
    log *logie.Logger
}

func NewRepository(logger *logie.Logger) *Repository {
    return &Repository{
        log: logger.WithModule("database"),
    }
}

// main.go
package main

func main() {
    logger := logie.DefaultLogger()
    
    authService := auth.NewService(logger)
    dbRepo := database.NewRepository(logger)
    
    // Both services now have their own logger instance with module context
}
Package-Level Logger
// payments/logger.go
package payments

import "github.com/Michi01/logie"

var log *logie.Logger

func init() {
    log = logie.DefaultLogger().WithModule("payments")
}

// payments/service.go
package payments

func ProcessPayment(amount float64) {
    log.WithField("amount", amount).Info("Processing payment")
}

Best Practices

  1. Use modules to organize logs by component
  2. Add contextual fields using WithField/WithFields
  3. Set appropriate log levels for different environments
  4. Use structured fields instead of embedding data in messages
  5. Prefer dependency injection for better testability
  6. Use package-level loggers only when dependency injection isn't practical

Thread Safety

All operations in Logie are thread-safe and can be used concurrently.

Documentation

Overview

Package logie provides a flexible structured logging package built on top of zerolog with module-level log control.

Basic usage:

logger := logie.DefaultLogger()
logger.Info("Hello, World!")

With fields:

logger.WithField("user", "john").Info("User logged in")

Module-based logging:

logger := logie.New(output, logie.WithModule("auth"))

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

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