golang结构化日志记录与HTTP请求感知插件库xlog的使用

Golang结构化日志记录与HTTP请求感知插件库xlog的使用

简介

xlog是一个针对基于net/context的HTTP应用程序设计的日志记录库。与其他日志库不同,xlog不会因为输出延迟而阻塞应用程序。日志命令通过缓冲通道连接到输出,如果缓冲区满了会优先丢弃消息。

主要特性

  • 每个请求的日志上下文
  • 每个请求和/或每条消息的键值字段
  • 日志级别(Debug, Info, Warn, Error)
  • 检测到终端时输出彩色日志
  • 自定义输出格式(JSON, logfmt等)
  • 自动收集请求上下文如User-Agent、IP等
  • 丢弃消息而非阻塞执行
  • 通过github.com/rs/xaccess轻松实现访问日志

安装

go get github.com/rs/xlog

使用示例

package main

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

	"github.com/rs/xlog"
)

func main() {
	// 创建中间件链
	c := alice.New()

	// 获取主机名并配置xlog
	host, _ := os.Hostname()
	conf := xlog.Config{
		// 记录info及以上级别的日志
		Level: xlog.LevelInfo,
		// 设置一些全局环境字段
		Fields: xlog.F{
			"role": "my-service",
			"host": host,
		},
		// 将所有日志输出到控制台
		Output: xlog.NewOutputChannel(xlog.NewConsoleOutput()),
	}

	// 安装日志处理器
	c = c.Append(xlog.NewHandler(conf))

	// 可选:将xlog处理器的输入连接到Go的默认日志记录器
	log.SetFlags(0)
	xlogger := xlog.New(conf)
	log.SetOutput(xlogger)

	// 安装一些提供的额外处理器来设置请求上下文字段
	c = c.Append(xlog.MethodHandler("method"))
	c = c.Append(xlog.URLHandler("url"))
	c = c.Append(xlog.RemoteAddrHandler("ip"))
	c = c.Append(xlog.UserAgentHandler("user_agent"))
	c = c.Append(xlog.RefererHandler("referer"))
	c = c.Append(xlog.RequestIDHandler("req_id", "Request-Id"))

	// 这里是最终的处理程序
	h := c.Then(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 从请求上下文中获取日志记录器
		l := xlog.FromRequest(r)

		// 记录一些错误
		if err := errors.New("some error from elsewhere"); err != nil {
			l.Errorf("Here is an error: %v", err)
		}

		// 或者记录带有字段的信息
		l.Info("Something happened", xlog.F{
			"user":   "current user id",
			"status": "ok",
		})
		// 输出示例:
		// {
		//   "message": "Something happened",
		//   "level": "info",
		//   "file": "main.go:34",
		//   "time": time.Time{...},
		//   "user": "current user id",
		//   "status": "ok",
		//   "ip": "1.2.3.4",
		//   "user-agent": "Mozilla/1.2.3...",
		//   "referer": "http://somewhere.com/path",
		//   "role": "my-service",
		//   "host": "somehost"
		// }
	}))
	http.Handle("/", h)

	if err := http.ListenAndServe(":8080", nil); err != nil {
		xlogger.Fatal(err)
	}
}

复制日志记录器

您可能需要获取当前日志记录器的副本,以便在不修改原始记录器的情况下将修改后的版本传递给函数:

l := xlog.FromContext(ctx)
l2 := xlog.Copy(l)
l2.SetField("foo", "bar")

全局日志记录器

您可以使用标准Go日志记录器并将xlog作为其输出,因为xlog实现了io.Writer接口:

xlogger := xlog.New(conf)
log.SetOutput(xlogger)

配置输出

默认情况下,输出设置为在STDOUT上输出调试和信息消息,在STDERR上输出警告和错误。您可以轻松更改此设置。

conf := xlog.Config{
    Output: xlog.NewOutputChannel(xlog.MultiOutput{
        // 将所有带有type=mymodule字段的日志发送到远程syslog
        0: xlog.FilterOutput{
            Cond: func(fields map[string]interface{}) bool {
                return fields["type"] == "mymodule"
            },
            Output: xlog.NewSyslogOutput("tcp", "1.2.3.4:1234", "mymodule"),
        },
        // 为每个日志级别设置不同的输出
        1: xlog.LevelOutput{
            // 将错误发送到控制台
            Error: xlog.NewConsoleOutput(),
            // 为info级别发送syslog输出
            Info: xlog.NewSyslogOutput("", "", ""),
        },
    }),
})

h = xlog.NewHandler(conf)

内置输出模块

名称 描述
OutputChannel 在发送前缓冲消息。此输出应始终直接设置为xlog的配置
MultiOutput 将相同消息路由到多个输出
FilterOutput 测试消息条件,如果为真则转发到子输出
LevelOutput 按级别路由消息
ConsoleOutput 以人类可读格式在stdout上打印消息,支持彩色输出
JSONOutput 以JSON格式序列化消息
LogfmtOutput 使用Heroku风格的logfmt序列化消息
LogstashOutput 使用Logstash 2.0结构化格式序列化JSON消息
SyslogOutput 将消息发送到syslog
UIDOutput 为每条消息附加全局唯一ID并转发到下一个输出

更多关于golang结构化日志记录与HTTP请求感知插件库xlog的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang结构化日志记录与HTTP请求感知插件库xlog的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang结构化日志记录与HTTP请求感知插件库xlog使用指南

xlog简介

xlog是一个功能强大的Golang结构化日志记录库,特别适合在HTTP服务中使用。它提供了请求感知的日志记录能力,可以自动关联请求上下文,支持结构化日志输出(如JSON),并且具有丰富的插件系统。

安装xlog

go get github.com/rs/xlog

基本使用

1. 简单日志记录

package main

import (
	"github.com/rs/xlog"
)

func main() {
	// 配置xlog
	config := xlog.Config{
		Output: xlog.NewConsoleOutput(),
		Fields: xlog.F{"version": "1.0.0"},
	}
	
	// 创建logger
	logger := xlog.New(config)
	
	// 记录不同级别的日志
	logger.Info("Application started")
	logger.Debugf("Debug message with value: %d", 42)
	logger.Warn("This is a warning")
	logger.Error("An error occurred")
}

2. 结构化日志输出

func main() {
	logger := xlog.New(xlog.Config{
		Output: xlog.NewConsoleOutput(),
	})
	
	// 结构化日志记录
	logger.Infof("User logged in", xlog.F{
		"user_id": 12345,
		"ip":      "192.168.1.1",
		"action":  "login",
	})
}

HTTP请求感知

xlog最强大的特性之一是它与HTTP请求的深度集成。

1. 基本HTTP集成

package main

import (
	"net/http"
	
	"github.com/rs/xlog"
	"github.com/rs/xhandler"
	"github.com/rs/xmux"
)

func main() {
	c := xhandler.Chain{}
	
	// 添加xlog中间件
	c.UseC(xlog.NewHandler(xlog.Config{
		Output: xlog.NewConsoleOutput(),
	}))
	
	// 添加其他中间件...
	
	mux := xmux.New()
	mux.GET("/", c.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
		// 从上下文中获取logger
		logger := xlog.FromContext(ctx)
		
		// 记录请求相关信息
		logger.Info("Handling request", xlog.F{
			"path":   r.URL.Path,
			"method": r.Method,
		})
		
		w.Write([]byte("Hello World"))
	}))
	
	http.ListenAndServe(":8080", mux)
}

2. 自动请求ID生成

c.UseC(xlog.NewHandler(xlog.Config{
	Output: xlog.NewConsoleOutput(),
}))

// 添加请求ID中间件
c.UseC(xlog.RequestIDHandler("req_id", "Request-Id"))

高级特性

1. 自定义输出格式

// 自定义JSON输出
logger := xlog.New(xlog.Config{
	Output: xlog.NewJSONOutput(xlog.JSONOutput{
		Out: os.Stdout,
	}),
})

2. 多输出目标

// 同时输出到控制台和文件
file, _ := os.Create("app.log")
logger := xlog.New(xlog.Config{
	Output: xlog.MultiOutput{
		xlog.NewConsoleOutput(),
		xlog.NewJSONOutput(xlog.JSONOutput{Out: file}),
	},
})

3. 插件系统

xlog支持通过插件扩展功能:

// 自定义插件示例
type MetricsPlugin struct{}

func (p *MetricsPlugin) Log(le xlog.LogEntry) {
	// 根据日志级别更新指标
	switch le.Level {
	case xlog.LevelInfo:
		metrics.Increment("log.info")
	case xlog.LevelError:
		metrics.Increment("log.error")
	}
}

func main() {
	logger := xlog.New(xlog.Config{
		Output: xlog.NewConsoleOutput(),
	})
	
	// 注册插件
	logger.AddPlugin(&MetricsPlugin{})
	
	logger.Info("This will trigger metrics update")
}

最佳实践

  1. 为每个请求创建子logger:
func handler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	logger := xlog.FromContext(ctx).Copy()
	
	// 添加请求特定字段
	logger.SetField("user_agent", r.UserAgent())
	
	// 使用子logger记录
	logger.Info("Processing request")
}
  1. 在生产环境使用JSON格式:
func productionLogger() xlog.Logger {
	return xlog.New(xlog.Config{
		Output: xlog.NewJSONOutput(xlog.JSONOutput{
			Out: os.Stdout,
		}),
		Level: xlog.LevelInfo,
	})
}
  1. 动态调整日志级别:
logger := xlog.New(xlog.Config{
	Output: xlog.NewConsoleOutput(),
	Level:  xlog.LevelInfo,
})

// 在需要时动态调整
if debugMode {
	logger.(*xlog.Logger).SetLevel(xlog.LevelDebug)
}

xlog为Golang应用提供了强大而灵活的日志记录解决方案,特别适合需要请求上下文感知的HTTP服务。通过结构化日志和丰富的插件系统,可以轻松实现复杂的日志记录需求。

回到顶部