logutil

package
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Jan 7, 2026 License: BSD-3-Clause Imports: 5 Imported by: 0

README

logutil - 日志实用工具包

logutil 是一个为 kydenul/log 日志库提供实用工具函数的包。它提供了常见日志记录任务的便捷函数,帮助简化应用程序中的日志记录代码。

功能特性

HTTP 请求日志工具
  • LogHTTPRequest() - 记录 HTTP 请求详情
  • LogHTTPResponse() - 记录 HTTP 响应详情,根据状态码自动选择日志级别
错误处理工具
  • LogError() - 仅在错误不为 nil 时记录错误
  • FatalOnError() - 在错误不为 nil 时记录致命错误并退出程序
  • CheckError() - 检查并记录错误,返回是否有错误发生
  • Must() - FatalOnError() 的简短别名
性能计时工具
  • Timer() - 返回一个函数,调用时记录从创建到调用的耗时
  • TimeFunction() - 执行函数并记录其执行时间
条件日志工具
  • InfoIf() - 仅在条件为真时记录信息日志
  • ErrorIf() - 仅在条件为真时记录错误日志
  • DebugIf() - 仅在条件为真时记录调试日志
  • WarnIf() - 仅在条件为真时记录警告日志
上下文日志工具
  • WithRequestID() - 从上下文中提取请求 ID 并创建自动包含请求 ID 的日志包装器
异常处理工具
  • LogPanic() - 恢复 panic 并记录为错误,然后重新 panic
  • LogPanicAsError() - 恢复 panic 并记录为错误,不重新 panic
应用生命周期工具
  • LogStartup() - 记录应用启动信息
  • LogShutdown() - 记录应用关闭信息

使用示例

HTTP 请求日志
import (
    "github.com/kydenul/log"
    "github.com/kydenul/log/logutil"
)

func httpHandler(w http.ResponseWriter, r *http.Request) {
    logger := log.NewLog(nil)
    start := time.Now()
    
    // 记录请求
    logutil.LogHTTPRequest(logger, r)
    
    // 处理请求...
    statusCode := 200
    
    // 记录响应
    duration := time.Since(start)
    logutil.LogHTTPResponse(logger, r, statusCode, duration)
}
错误处理
func processData() error {
    logger := log.NewLog(nil)
    
    data, err := loadData()
    if logutil.CheckError(logger, err, "Failed to load data") {
        return err
    }
    
    // 继续处理...
    return nil
}

func criticalOperation() {
    logger := log.NewLog(nil)
    
    err := performCriticalTask()
    logutil.FatalOnError(logger, err, "Critical task failed")
    
    // 如果没有错误,继续执行...
}
性能计时
func databaseQuery() {
    logger := log.NewLog(nil)
    
    // 方法1:使用 Timer
    defer logutil.Timer(logger, "database_query")()
    
    // 执行数据库查询...
}

func processData() {
    logger := log.NewLog(nil)
    
    // 方法2:使用 TimeFunction
    logutil.TimeFunction(logger, "data_processing", func() {
        // 数据处理逻辑...
    })
}
条件日志
func validateInput(input string) error {
    logger := log.NewLog(nil)
    debugMode := os.Getenv("DEBUG") == "true"
    
    logutil.InfoIf(logger, debugMode, "Validating input", "input_length", len(input))
    
    if input == "" {
        logutil.ErrorIf(logger, true, "Input validation failed", "reason", "empty_input")
        return errors.New("input cannot be empty")
    }
    
    return nil
}
请求 ID 日志
func handleRequest(w http.ResponseWriter, r *http.Request) {
    logger := log.NewLog(nil)
    
    // 从上下文中获取请求 ID 并创建包装器
    ctx := context.WithValue(r.Context(), "request_id", generateRequestID())
    requestLogger := logutil.WithRequestID(logger, ctx)
    
    // 所有日志调用都会自动包含请求 ID
    requestLogger.Info("Processing request")
    requestLogger.Error("Request failed")
}
异常处理
func riskyOperation() {
    logger := log.NewLog(nil)
    
    // 恢复 panic 并记录,但不重新 panic
    defer logutil.LogPanicAsError(logger, "risky_operation")
    
    // 可能会 panic 的代码...
    panic("something went wrong")
    
    // 这行代码不会执行,但程序不会崩溃
}
应用生命周期
func main() {
    logger := log.NewLog(nil)
    startTime := time.Now()
    
    // 记录启动
    logutil.LogStartup(logger, "my-service", "v1.0.0", 8080)
    
    // 应用逻辑...
    
    // 记录关闭
    uptime := time.Since(startTime)
    logutil.LogShutdown(logger, "my-service", uptime)
}

设计原则

  1. 空安全: 所有函数都能安全处理 nil logger 和 nil 参数
  2. 非侵入性: 不修改原始日志库的行为,只是提供便捷包装
  3. 性能友好: 避免不必要的操作,如条件检查在日志记录前进行
  4. 一致性: 遵循原日志库的命名约定和参数模式
  5. 实用性: 专注于解决实际开发中的常见日志记录需求

兼容性

  • 兼容任何实现 log.Logger 接口的日志器
  • 不依赖特定的日志实现细节
  • 可以与现有代码无缝集成

测试

运行测试:

go test ./logutil -v

查看测试覆盖率:

go test ./logutil -cover

Documentation

Overview

Package logutil provides utility functions for common logging tasks. It works with any logger that implements the log.Logger interface.

Example (HttpHandler)

Example of using logutil in an HTTP handler

package main

import (
	"context"
	"net/http"
	"net/http/httptest"
	"time"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	handler := func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()

		// Log incoming request
		logutil.LogHTTPRequest(logger, r)

		// Add request ID to context and create request-scoped logger
		ctx := context.WithValue(r.Context(), "request_id", "req-789")
		requestLogger := logutil.WithRequestID(ctx, logger)

		// Use timer to measure processing time
		defer logutil.Timer(requestLogger, "request_processing")()

		// Simulate request processing
		err := processRequest(r)
		if logutil.CheckError(requestLogger, err, "Failed to process request") {
			http.Error(w, "Internal Server Error", 500)
			logutil.LogHTTPResponse(logger, r, 500, time.Since(start))
			return
		}

		w.WriteHeader(200)
		w.Write([]byte("OK"))

		// Log response
		logutil.LogHTTPResponse(logger, r, 200, time.Since(start))
	}

	// Create test request
	req := httptest.NewRequest("POST", "http://example.com/api/process", nil)
	w := httptest.NewRecorder()

	handler(w, req)
}

func processRequest(r *http.Request) error {

	_ = r
	return nil
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckError

func CheckError(logger log.Logger, err error, msg string) bool

CheckError logs an error if it's not nil and returns whether an error occurred. This is useful for error checking in conditional statements.

Example
package main

import (
	"errors"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	err := performOperation()
	if logutil.CheckError(logger, err, "Operation failed") {
		// Handle error case
		return
	}

	// Continue with success case
}

func performOperation() error {

	return errors.New("simulated error")
}

func DebugIf

func DebugIf(logger log.Logger, condition bool, msg string, args ...any)

DebugIf logs a debug message only if the condition is true. This helps reduce conditional logging boilerplate in application code.

func ErrorIf

func ErrorIf(logger log.Logger, condition bool, msg string, args ...any)

ErrorIf logs an error message only if the condition is true. This helps reduce conditional logging boilerplate in application code.

Example
package main

import (
	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)
	hasError := true

	logutil.ErrorIf(logger, hasError, "Validation failed", "field", "email")
	// Only logs if hasError is true
}

func FatalOnError

func FatalOnError(logger log.Logger, err error, msg string)

FatalOnError logs an error and exits the program if the error is not nil. This should be used sparingly, only for unrecoverable errors during startup.

func InfoIf

func InfoIf(logger log.Logger, condition bool, msg string, args ...any)

InfoIf logs an info message only if the condition is true. This helps reduce conditional logging boilerplate in application code.

Example
package main

import (
	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)
	debugMode := true

	logutil.InfoIf(logger, debugMode, "Debug mode is enabled", "config", "debug")
	// Only logs if debugMode is true
}

func LogError

func LogError(logger log.Logger, err error, msg string)

LogError logs an error if it's not nil. This is a convenience function to avoid repetitive error checking in code.

Example
package main

import (
	"errors"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)
	err := errors.New("database connection failed")

	logutil.LogError(logger, err, "Failed to connect to database")
	// Only logs if err is not nil
}

func LogHTTPRequest

func LogHTTPRequest(logger log.Logger, req *http.Request)

LogHTTPRequest logs details about an HTTP request. It records the HTTP method, URL, remote address, and user agent.

Example
package main

import (
	"net/http/httptest"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)
	req := httptest.NewRequest("GET", "http://example.com/api/users", nil)
	req.Header.Set("User-Agent", "MyApp/1.0")

	logutil.LogHTTPRequest(logger, req)
	// Output logs HTTP request details including method, URL, and user agent
}

func LogHTTPResponse

func LogHTTPResponse(logger log.Logger, req *http.Request, statusCode int, duration time.Duration)

LogHTTPResponse logs details about an HTTP response. It records the HTTP method, URL, status code, and response duration.

Example
package main

import (
	"net/http/httptest"
	"time"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)
	req := httptest.NewRequest("GET", "http://example.com/api/users", nil)

	// Simulate processing time
	duration := 150 * time.Millisecond
	statusCode := 200

	logutil.LogHTTPResponse(logger, req, statusCode, duration)
	// Output logs HTTP response details including status code and duration
}

func LogPanic

func LogPanic(logger log.Logger, operation string)

LogPanic recovers from a panic and logs it as an error. This should be used with defer in functions that might panic.

Example usage:

defer LogPanic(logger, "processing_request")

func LogPanicAsError

func LogPanicAsError(logger log.Logger, operation string)

LogPanicAsError recovers from a panic and logs it as an error without re-panicking. This is useful when you want to handle panics gracefully.

Example usage:

defer LogPanicAsError(logger, "background_task")
Example
package main

import (
	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	func() {
		defer logutil.LogPanicAsError(logger, "background_task")

		// This will panic but be caught and logged as an error
		panic("unexpected error occurred")
	}()
	// Function continues execution after panic is caught and logged
}

func LogShutdown

func LogShutdown(logger log.Logger, appName string, uptime time.Duration)

LogShutdown logs application shutdown information. This is a convenience function for logging shutdown details.

Example
package main

import (
	"time"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)
	startTime := time.Now()

	// Simulate application running
	time.Sleep(100 * time.Millisecond)

	uptime := time.Since(startTime)
	logutil.LogShutdown(logger, "my-web-service", uptime)
	// Logs application shutdown information including uptime
}

func LogStartup

func LogStartup(logger log.Logger, appName, version string, port int)

LogStartup logs application startup information. This is a convenience function for logging common startup details.

Example
package main

import (
	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	logutil.LogStartup(logger, "my-web-service", "v1.2.3", 8080)
	// Logs application startup information including name, version, and port
}

func Must

func Must(logger log.Logger, err error, msg string)

Must logs a fatal error and exits if err is not nil. This is similar to FatalOnError but with a shorter name for convenience.

func TimeFunction

func TimeFunction(logger log.Logger, name string, fn func())

TimeFunction executes a function and logs its execution time. This is a convenience wrapper around Timer for simple function timing.

Example
package main

import (
	"time"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	// Use TimeFunction to measure and log function execution time
	logutil.TimeFunction(logger, "data_processing", func() {
		// Simulate data processing
		time.Sleep(100 * time.Millisecond)
	})
	// Automatically logs the execution time of the function
}

func Timer

func Timer(logger log.Logger, name string) func()

Timer returns a function that, when called, logs the elapsed time since Timer was called. This is useful for measuring and logging the duration of operations.

Example usage:

defer Timer(logger, "database_query")()
Example
package main

import (
	"time"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	// Use Timer to measure operation duration
	defer logutil.Timer(logger, "database_query")()

	// Simulate database operation
	time.Sleep(50 * time.Millisecond)
	// When the function returns, it will log the operation duration
}

func WarnIf

func WarnIf(logger log.Logger, condition bool, msg string, args ...any)

WarnIf logs a warning message only if the condition is true. This helps reduce conditional logging boilerplate in application code.

func WithRequestID

func WithRequestID(ctx context.Context, logger log.Logger) log.Logger

WithRequestID extracts a request ID from context and returns a logger wrapper that automatically includes the request ID in all log messages. If no request ID is found in context, returns the original logger.

Example
package main

import (
	"context"

	"github.com/kydenul/log"
	"github.com/kydenul/log/logutil"
)

func main() {
	logger := log.NewLog(nil)

	// Create context with request ID
	ctx := context.WithValue(context.Background(), "request_id", "req-123-456")

	// Wrap logger to automatically include request ID
	requestLogger := logutil.WithRequestID(ctx, logger)

	// All log calls will now include the request ID
	requestLogger.Info("Processing user request")
	requestLogger.Error("Failed to process request")
}

Types

This section is empty.

Jump to

Keyboard shortcuts

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