klog

package
v1.2.3 Latest Latest
Warning

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

Go to latest
Published: Dec 23, 2025 License: Apache-2.0 Imports: 4 Imported by: 11

README

KLog

Kubernetes-style logging wrapper with optional caller information tracking.

Overview

The klog package provides wrapper functions for k8s.io/klog/v2, the logging library used throughout Kubernetes. It adds optional caller information tracking to help identify log sources in large applications.

Features

  • Kubernetes Standard - Uses k8s.io/klog/v2 underneath
  • Multiple Formats - Print, Printf, Println, and Structured logging
  • Log Levels - Info, Error, and Fatal levels
  • Caller Tracking - Optional file/line/function information
  • Structured Logging - InfoS and ErrorS for key-value pairs
  • Thread-Safe - Concurrent logging from multiple goroutines
  • Fatal Handling - Fatal logs terminate application with os.Exit(255)

Installation

go get -u github.com/common-library/go/log/klog
go get -u k8s.io/klog/v2

Quick Start

import "github.com/common-library/go/log/klog"

func main() {
    defer klog.Flush()
    
    klog.Info("Application started")
    klog.InfoS("Request processed", "method", "GET", "path", "/api/users")
    klog.Infof("Server listening on port %d", 8080)
}

API Reference

Info Logging
Info
func Info(arguments ...any)

Logs informational messages (like fmt.Print).

InfoS
func InfoS(message string, keysAndValues ...any)

Logs structured messages with key-value pairs.

Infof
func Infof(format string, arguments ...any)

Logs formatted messages (like fmt.Printf).

Infoln
func Infoln(arguments ...any)

Logs messages with newline (like fmt.Println).

Error Logging
Error
func Error(arguments ...any)

Logs error messages.

ErrorS
func ErrorS(err error, message string, keysAndValues ...any)

Logs structured error messages with explicit error parameter.

Errorf
func Errorf(format string, arguments ...any)

Logs formatted error messages.

Errorln
func Errorln(arguments ...any)

Logs error messages with newline.

Fatal Logging
Fatal
func Fatal(arguments ...any)

Logs message and calls os.Exit(255).

Fatalf
func Fatalf(format string, arguments ...any)

Logs formatted message and calls os.Exit(255).

Fatalln
func Fatalln(arguments ...any)

Logs message with newline and calls os.Exit(255).

Utility Functions
Flush
func Flush()

Flushes all pending log I/O.

SetWithCallerInfo
func SetWithCallerInfo(with bool)

Enables/disables caller information in logs.

Complete Examples

Basic Logging
package main

import "github.com/common-library/go/log/klog"

func main() {
    defer klog.Flush()
    
    klog.Info("Application starting")
    klog.Info("Configuration loaded")
    klog.Info("Server ready")
}
Structured Logging
package main

import "github.com/common-library/go/log/klog"

func main() {
    defer klog.Flush()
    
    klog.InfoS("Server started",
        "port", 8080,
        "environment", "production",
        "version", "1.0.0",
    )
    
    klog.InfoS("Request processed",
        "method", "GET",
        "path", "/api/users",
        "duration", 45,
        "status", 200,
    )
}
Formatted Logging
package main

import "github.com/common-library/go/log/klog"

func main() {
    defer klog.Flush()
    
    port := 8080
    klog.Infof("Server listening on port %d", port)
    
    requestCount := 1000
    avgDuration := 45.5
    klog.Infof("Processed %d requests, avg duration: %.2fms", requestCount, avgDuration)
}
Error Logging
package main

import (
    "errors"
    "github.com/common-library/go/log/klog"
)

func main() {
    defer klog.Flush()
    
    err := connectDatabase()
    if err != nil {
        klog.Error("Database connection failed:", err)
        klog.ErrorS(err, "Failed to connect",
            "host", "localhost",
            "port", 5432,
            "database", "myapp",
        )
    }
}

func connectDatabase() error {
    return errors.New("connection timeout")
}
With Caller Information
package main

import "github.com/common-library/go/log/klog"

func processRequest(id int) {
    klog.Info("Processing request", id)
    // Output: [callerInfo:{File:"main.go" Line:8 Function:"main.processRequest"}] Processing request 123
}

func main() {
    defer klog.Flush()
    
    klog.SetWithCallerInfo(true) // Enable caller tracking
    
    processRequest(123)
}
HTTP Server Logging
package main

import (
    "net/http"
    "time"
    "github.com/common-library/go/log/klog"
)

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        
        klog.InfoS("Request started",
            "method", r.Method,
            "path", r.URL.Path,
            "remote", r.RemoteAddr,
        )
        
        next.ServeHTTP(w, r)
        
        klog.InfoS("Request completed",
            "method", r.Method,
            "path", r.URL.Path,
            "duration", time.Since(start).Milliseconds(),
        )
    })
}

func handler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello"))
}

func main() {
    defer klog.Flush()
    
    klog.Info("Starting HTTP server on :8080")
    
    http.Handle("/", loggingMiddleware(http.HandlerFunc(handler)))
    
    if err := http.ListenAndServe(":8080", nil); err != nil {
        klog.Fatal("Server failed:", err)
    }
}
Kubernetes Controller Logging
package main

import (
    "time"
    "github.com/common-library/go/log/klog"
)

type Controller struct {
    name string
}

func (c *Controller) Run() {
    klog.InfoS("Controller starting", "controller", c.name)
    
    ticker := time.NewTicker(30 * time.Second)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            c.reconcile()
        }
    }
}

func (c *Controller) reconcile() {
    klog.InfoS("Reconciliation started", "controller", c.name)
    
    // Reconciliation logic...
    
    klog.InfoS("Reconciliation completed",
        "controller", c.name,
        "resourcesProcessed", 10,
    )
}

func main() {
    defer klog.Flush()
    
    controller := &Controller{name: "pod-controller"}
    controller.Run()
}
Fatal Error Handling
package main

import (
    "os"
    "github.com/common-library/go/log/klog"
)

func loadConfig() error {
    configFile := "config.yaml"
    if _, err := os.Stat(configFile); os.IsNotExist(err) {
        return err
    }
    return nil
}

func main() {
    defer klog.Flush()
    
    if err := loadConfig(); err != nil {
        klog.Fatalf("Configuration file required: %v", err)
        // Application terminates here with os.Exit(255)
    }
    
    klog.Info("Application started successfully")
}
Environment-Based Configuration
package main

import (
    "os"
    "github.com/common-library/go/log/klog"
)

func main() {
    defer klog.Flush()
    
    // Enable caller info in development
    if os.Getenv("ENV") == "development" {
        klog.SetWithCallerInfo(true)
        klog.Info("Development mode: caller info enabled")
    } else {
        klog.SetWithCallerInfo(false)
        klog.Info("Production mode: caller info disabled")
    }
    
    klog.InfoS("Application started",
        "environment", os.Getenv("ENV"),
        "version", "1.0.0",
    )
}
Multi-Level Logging
package main

import (
    "errors"
    "github.com/common-library/go/log/klog"
)

func main() {
    defer klog.Flush()
    
    // Informational
    klog.Info("Application initializing")
    klog.InfoS("Configuration loaded", "source", "config.yaml")
    
    // Warnings (use Error level, klog doesn't have Warn)
    klog.Error("Cache miss, using default value")
    
    // Errors
    err := processData()
    if err != nil {
        klog.Error("Processing failed:", err)
        klog.ErrorS(err, "Data processing error",
            "component", "processor",
            "operation", "transform",
        )
    }
    
    // Fatal (terminates application)
    if criticalError() {
        klog.Fatal("Critical system error, cannot continue")
    }
}

func processData() error {
    return errors.New("invalid data format")
}

func criticalError() bool {
    return false
}

Best Practices

1. Always Flush Before Exit
// Good: Ensures logs are written
func main() {
    defer klog.Flush()
    // ... code ...
}

// Avoid: May lose logs
func main() {
    // ... code ...
    // No flush
}
2. Use Structured Logging
// Good: Structured data
klog.InfoS("Request processed",
    "method", "GET",
    "path", "/api/users",
    "duration", 45,
)

// Avoid: Concatenated strings
klog.Info("Request processed: GET /api/users duration=45ms")
3. Use ErrorS for Errors
// Good: Explicit error parameter
klog.ErrorS(err, "Database query failed",
    "query", sql,
    "table", "users",
)

// Acceptable but less structured
klog.Error("Database query failed:", err)
4. Enable Caller Info Selectively
// Good: Only in development
if os.Getenv("DEBUG") == "true" {
    klog.SetWithCallerInfo(true)
}

// Avoid: Always enabled (performance impact)
klog.SetWithCallerInfo(true)
5. Use Fatal Appropriately
// Good: Truly unrecoverable errors
if configFile == nil {
    klog.Fatal("Configuration file required")
}

// Avoid: Recoverable errors
if err := connect(); err != nil {
    klog.Fatal(err) // Should use Error instead
}

Comparison with slog

Feature klog slog
Backend k8s.io/klog/v2 log/slog
Async No Yes
Output Dest Flags-based Configurable
Rotation External Built-in (daily)
Fatal Exits app No exit
Use Case Kubernetes apps General apps

Performance Tips

  1. Minimize Caller Info - Only enable in development
  2. Use Structured Logging - InfoS/ErrorS more efficient than formatted strings
  3. Flush Strategically - Only at shutdown or critical points
  4. Avoid Fatal in Libraries - Use Error instead

Testing

func TestLogging(t *testing.T) {
    // Redirect klog output for testing
    flag.Set("logtostderr", "false")
    flag.Set("log_file", "test.log")
    
    klog.Info("Test message")
    klog.Flush()
    
    // Verify log file
    data, err := os.ReadFile("test.log")
    if err != nil {
        t.Fatal(err)
    }
    
    if !strings.Contains(string(data), "Test message") {
        t.Error("Log not found")
    }
    
    // Cleanup
    os.Remove("test.log")
}

Dependencies

  • k8s.io/klog/v2 - Kubernetes logging library
  • github.com/common-library/go/utility - Caller info utilities

Further Reading

Documentation

Overview

Package klog provides wrapper functions for Kubernetes klog logging.

This package wraps k8s.io/klog/v2 with optional caller information tracking, providing structured logging capabilities commonly used in Kubernetes applications.

Features:

  • Info, Error, and Fatal log levels
  • Formatted logging (Infof, Errorf, Fatalf)
  • Line-based logging (Infoln, Errorln, Fatalln)
  • Structured logging (InfoS, ErrorS)
  • Optional caller information (file, line, function)
  • Thread-safe operations

Example:

klog.SetWithCallerInfo(true)
klog.Info("Server started")
klog.InfoS("Request processed", "method", "GET", "path", "/api/users")
klog.Flush()

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Error

func Error(arguments ...any)

Error logs error messages.

This function logs at error level using klog. If caller information is enabled, it includes file name, line number, and function name.

Parameters:

  • arguments: Values to log (similar to fmt.Print)

Example:

klog.Error("Failed to connect to database")

Example with context:

klog.Error("Request failed:", err)

Example with caller info enabled:

klog.SetWithCallerInfo(true)
klog.Error("Authentication failed for user", userID)

func ErrorS

func ErrorS(err error, message string, keysAndValues ...any)

ErrorS logs structured error messages with key-value pairs.

This function provides structured logging at error level with an explicit error parameter and additional context.

Parameters:

  • err: The error to log (can be nil)
  • message: The log message
  • keysAndValues: Alternating keys (strings) and values (any type)

Example:

klog.ErrorS(err, "Database query failed", "query", sql, "duration", elapsed)

Example with nil error:

klog.ErrorS(nil, "Validation failed", "field", "email", "value", userEmail)

Example with caller info:

klog.SetWithCallerInfo(true)
klog.ErrorS(err, "Failed to save user",
    "userID", 123,
    "operation", "UPDATE",
    "table", "users",
)

func Errorf

func Errorf(format string, arguments ...any)

Errorf logs formatted error messages.

This function logs at error level using printf-style formatting.

Parameters:

  • format: Printf-style format string
  • arguments: Values for format string placeholders

Example:

klog.Errorf("Failed to open file: %v", err)

Example with multiple values:

klog.Errorf("User %d attempted invalid action: %s", userID, action)

Example with caller info:

klog.SetWithCallerInfo(true)
klog.Errorf("Timeout after %d attempts", retries)

func Errorln

func Errorln(arguments ...any)

Errorln logs error messages with a newline.

Similar to Error but always appends a newline, like fmt.Println.

Parameters:

  • arguments: Values to log

Example:

klog.Errorln("Connection lost")

Example with error:

klog.Errorln("Operation failed:", err)

func Fatal

func Fatal(arguments ...any)

Fatal logs a message and then calls os.Exit(255).

This function logs at fatal level and terminates the program. Deferred functions will NOT run.

Parameters:

  • arguments: Values to log before exiting

Warning: This terminates the application. Use Error for recoverable errors.

Example:

if configFile == nil {
    klog.Fatal("Configuration file required")
}

Example with context:

klog.Fatal("Critical dependency missing:", dependency)

func Fatalf

func Fatalf(format string, arguments ...any)

Fatalf logs a formatted message and then calls os.Exit(255).

This function logs at fatal level using printf-style formatting and terminates the program. Deferred functions will NOT run.

Parameters:

  • format: Printf-style format string
  • arguments: Values for format string placeholders

Warning: This terminates the application. Use Errorf for recoverable errors.

Example:

if port < 1024 {
    klog.Fatalf("Invalid port: %d", port)
}

Example with error:

klog.Fatalf("Failed to initialize: %v", err)

func Fatalln

func Fatalln(arguments ...any)

Fatalln logs a message with a newline and then calls os.Exit(255).

Similar to Fatal but always appends a newline. This function terminates the program. Deferred functions will NOT run.

Parameters:

  • arguments: Values to log before exiting

Warning: This terminates the application.

Example:

klog.Fatalln("Database connection failed")

Example with error:

klog.Fatalln("Startup failed:", err)

func Flush

func Flush()

Flush flushes all pending log I/O.

This function blocks until all buffered log data has been written. It's essential to call this before application shutdown to ensure no logs are lost.

Example at shutdown:

defer klog.Flush()

klog.Info("Application starting")
// ... application logic ...
klog.Info("Application shutting down")

Example in signal handler:

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
<-sigChan
klog.Info("Interrupt received")
klog.Flush()

func Info

func Info(arguments ...any)

Info logs informational messages.

This function logs at info level using klog. If caller information is enabled, it includes file name, line number, and function name.

Parameters:

  • arguments: Values to log (similar to fmt.Print)

Example:

klog.Info("Server started on port 8080")

Example with multiple arguments:

klog.Info("Processing request", requestID, "from user", userID)

Example with caller info enabled:

klog.SetWithCallerInfo(true)
klog.Info("Database connected")
// Output: [callerInfo:{File:"main.go" Line:42 Function:"main.init"}] Database connected

func InfoS

func InfoS(message string, keysAndValues ...any)

InfoS logs structured informational messages with key-value pairs.

This function provides structured logging at info level. Arguments are interpreted as alternating keys and values.

Parameters:

  • message: The log message
  • keysAndValues: Alternating keys (strings) and values (any type)

Example:

klog.InfoS("Request completed", "method", "GET", "path", "/api/users", "duration", 45)

Example with caller info:

klog.SetWithCallerInfo(true)
klog.InfoS("User logged in",
    "userID", 123,
    "username", "alice",
    "timestamp", time.Now(),
)

func Infof

func Infof(format string, arguments ...any)

Infof logs formatted informational messages.

This function logs at info level using printf-style formatting.

Parameters:

  • format: Printf-style format string
  • arguments: Values for format string placeholders

Example:

klog.Infof("Server listening on port %d", 8080)

Example with multiple values:

klog.Infof("Processing %d requests for user %s", count, username)

Example with caller info:

klog.SetWithCallerInfo(true)
klog.Infof("Cache hit rate: %.2f%%", hitRate*100)

func Infoln

func Infoln(arguments ...any)

Infoln logs informational messages with a newline.

Similar to Info but always appends a newline, like fmt.Println.

Parameters:

  • arguments: Values to log

Example:

klog.Infoln("Application initialized")

Example with multiple arguments:

klog.Infoln("User", userID, "logged in at", time.Now())

func SetWithCallerInfo

func SetWithCallerInfo(with bool)

SetWithCallerInfo enables or disables caller information in log entries.

Parameters:

  • with: If true, includes file name, line number, and function name in logs

When enabled, each log entry will include caller information showing where the log call originated. This is useful for debugging but adds overhead.

Example:

klog.SetWithCallerInfo(true)
klog.Info("Server started")
// Output includes: [callerInfo:{File:"main.go" Line:42 Function:"main"}] Server started

Example for environment-based configuration:

if os.Getenv("DEBUG") == "true" {
    klog.SetWithCallerInfo(true)
} else {
    klog.SetWithCallerInfo(false)
}

Types

This section is empty.

Jump to

Keyboard shortcuts

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