Golang HTTP日志工具 - 基于Gorilla Handlers的可组合HTTP记录器

Golang HTTP日志工具 - 基于Gorilla Handlers的可组合HTTP记录器 GitHub: https://github.com/lassik/go-httplog
GoDoc: https://godoc.org/github.com/lassik/go-httplog

这是一个可组合的 HTTP 日志记录库。它不会强制规定你应如何记录日志,而是提供一套工具集来帮助你构建自己的日志记录器。你可以使用喜欢的部分,忽略其余部分。

  • 它基于包含 HTTP 请求解析信息的 LogRequest 结构体。
  • LogHandler 中间件允许你记录任何 HTTP 请求。你只需提供一个接收 LogRequest 的函数,该函数可以按任意方式格式化和写入日志条目。
  • 要格式化日志条目,你可以使用 CommonLogLineCombinedLogLine 函数。自定义格式化也很容易:LogRequest 应包含你需要的所有信息。

该库的核心部分提取自 Gorilla Handlers 包。此日志记录库与框架无关,不依赖 Gorilla 或 Go 标准库之外的任何其他组件。


更多关于Golang HTTP日志工具 - 基于Gorilla Handlers的可组合HTTP记录器的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang HTTP日志工具 - 基于Gorilla Handlers的可组合HTTP记录器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个非常实用的HTTP日志记录库,它基于Gorilla Handlers的设计理念,提供了灵活的可组合性。让我通过示例代码来展示如何使用它:

package main

import (
    "log"
    "net/http"
    "os"

    "github.com/lassik/go-httplog"
)

// 自定义日志格式函数
func customLogger(req httplog.LogRequest) {
    log.Printf("[%s] %s %s %d %d",
        req.StartTime.Format("2006-01-02 15:04:05"),
        req.Method,
        req.URL.Path,
        req.StatusCode,
        req.Size)
}

func main() {
    // 创建基础handler
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World!"))
    })

    // 使用Common Log Format
    commonLogHandler := httplog.LogHandler(handler, func(req httplog.LogRequest) {
        log.Println(httplog.CommonLogLine(req))
    })

    // 使用Combined Log Format  
    combinedLogHandler := httplog.LogHandler(handler, func(req httplog.LogRequest) {
        log.Println(httplog.CombinedLogLine(req))
    })

    // 使用自定义日志格式
    customLogHandler := httplog.LogHandler(handler, customLogger)

    // 启动多个服务器演示不同格式
    go func() {
        log.Println("Common Log Format server starting on :8080")
        http.ListenAndServe(":8080", commonLogHandler)
    }()

    go func() {
        log.Println("Combined Log Format server starting on :8081") 
        http.ListenAndServe(":8081", combinedLogHandler)
    }()

    log.Println("Custom Format server starting on :8082")
    http.ListenAndServe(":8082", customLogHandler)
}

更复杂的自定义日志记录示例:

package main

import (
    "encoding/json"
    "net/http"
    "time"

    "github.com/lassik/go-httplog"
)

type JSONLogEntry struct {
    Timestamp  string `json:"timestamp"`
    Method     string `json:"method"`
    Path       string `json:"path"`
    Status     int    `json:"status"`
    Duration   int64  `json:"duration_ms"`
    UserAgent  string `json:"user_agent"`
    RemoteAddr string `json:"remote_addr"`
}

func jsonLogger(req httplog.LogRequest) {
    entry := JSONLogEntry{
        Timestamp:  req.StartTime.Format(time.RFC3339),
        Method:     req.Method,
        Path:       req.URL.Path,
        Status:     req.StatusCode,
        Duration:   req.Duration.Nanoseconds() / 1e6,
        UserAgent:  req.UserAgent(),
        RemoteAddr: req.RemoteAddr,
    }

    if jsonData, err := json.Marshal(entry); err == nil {
        println(string(jsonData))
    }
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte(`{"message": "success"}`))
    })

    mux.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
        time.Sleep(100 * time.Millisecond) // 模拟处理时间
        w.WriteHeader(http.StatusCreated)
        w.Write([]byte(`{"id": 123}`))
    })

    // 包装handler进行JSON格式日志记录
    loggedHandler := httplog.LogHandler(mux, jsonLogger)

    http.ListenAndServe(":3000", loggedHandler)
}

与现有日志库集成示例:

package main

import (
    "net/http"

    "github.com/lassik/go-httplog"
    "github.com/sirupsen/logrus"
)

func setupLogrusLogger() func(httplog.LogRequest) {
    logger := logrus.New()
    logger.SetFormatter(&logrus.JSONFormatter{})

    return func(req httplog.LogRequest) {
        logger.WithFields(logrus.Fields{
            "method":      req.Method,
            "path":        req.URL.Path,
            "status":      req.StatusCode,
            "duration_ms": req.Duration.Seconds() * 1000,
            "user_agent":  req.UserAgent(),
            "remote_addr": req.RemoteAddr,
        }).Info("http_request")
    }
}

func main() {
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Logged with Logrus!"))
    })

    logrusLogger := setupLogrusLogger()
    loggedHandler := httplog.LogHandler(handler, logrusLogger)

    http.ListenAndServe(":8080", loggedHandler)
}

这个库的核心优势在于其可组合性,你可以轻松地集成到任何现有的HTTP服务器中,并使用任何你喜欢的日志格式或日志库。LogRequest结构体提供了完整的请求上下文信息,使得自定义日志格式变得非常简单直接。

回到顶部