一个支持 异步、批量、重试、多通道分发 的 Go logging 扩展库,适用于高吞吐日志处理与消息通知场景。
- 🚀 异步处理:解耦业务线程,提高性能
- 📦 批量写入:减少 IO / 网络开销
- 🔁 失败重试:提升日志可靠性
- 🔀 多通道分发:支持同时写入多个 sink
- 🔌 插件化 adapters:支持 zap、zerolog 等扩展
go get github.com/cnmax/gologging-ext- zap
go get github.com/cnmax/gologging-ext/adapters/zap
- zerolog
go get github.com/cnmax/gologging-ext/adapters/zerolog
package tests
import (
"context"
"log/slog"
"os"
"testing"
"time"
slogAdapter "github.com/cnmax/gologging-ext/adapters/slog"
"github.com/cnmax/gologging-ext/pipeline"
"github.com/cnmax/gologging-ext/sinks/cls"
"github.com/cnmax/gologging-ext/sinks/telegram"
"github.com/cnmax/gologging-ext/sinks/wechat"
)
func TestSlogAdapter(t *testing.T) {
ctx := context.Background()
clsSink := cls.New(
ctx,
"ap-shanghai.cls.tencentcs.com",
"your-secret-id",
"your-secret-key",
"your-topic-id",
)
wechatSink := wechat.New(
ctx,
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
)
telegramSink := telegram.New(
ctx,
"your-bot-token",
your-chat-id,
)
dispatcher := pipeline.NewDispatcher(
pipeline.Build(clsSink),
//pipeline.Build(telegramSink),
pipeline.NewAsync(
pipeline.NewRetry(telegramSink, 3, time.Second),
),
)
//logger := slog.New(slogAdapter.NewHandler(dispatcher, slog.LevelInfo))
multi := slog.NewMultiHandler(
slog.NewTextHandler(os.Stdout, nil),
slogAdapter.NewHandler(dispatcher, slog.LevelInfo),
slogAdapter.NewHandler(pipeline.NewAsync(wechatSink), slog.LevelError),
)
logger := slog.New(multi)
slog.SetDefault(logger)
slog.Error("发生错误了", "user", "xxx", "age", 18)
time.Sleep(10 * time.Second)
}package tests
import (
"context"
"os"
"testing"
"time"
zapAdapter "github.com/cnmax/gologging-ext/adapters/zap"
"github.com/cnmax/gologging-ext/pipeline"
"github.com/cnmax/gologging-ext/sinks/cls"
"github.com/cnmax/gologging-ext/sinks/telegram"
"github.com/cnmax/gologging-ext/sinks/wechat"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func TestZapAdapter(t *testing.T) {
ctx := context.Background()
clsSink := cls.New(
ctx,
"ap-shanghai.cls.tencentcs.com",
"your-secret-id",
"your-secret-key",
"your-topic-id",
)
wechatSink := wechat.New(
ctx,
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
)
telegramSink := telegram.New(
ctx,
"your-bot-token",
your-chat-id,
)
dispatcher := pipeline.NewDispatcher(
pipeline.Build(clsSink),
//pipeline.Build(telegramSink),
pipeline.NewAsync(
pipeline.NewRetry(telegramSink, 3, time.Second),
),
)
multi := zapcore.NewTee(
zapcore.NewCore(
zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()),
zapcore.AddSync(os.Stdout),
zapcore.InfoLevel,
),
zapAdapter.NewCore(dispatcher, zapcore.InfoLevel),
zapAdapter.NewCore(pipeline.NewAsync(wechatSink), zapcore.ErrorLevel),
)
logger := zap.New(
multi,
zap.AddCaller(),
//zap.AddStacktrace(zapcore.ErrorLevel),
)
zap.ReplaceGlobals(logger)
zap.L().Error(
"发生错误了",
zap.String("user", "xxx"),
zap.Int("age", 18),
)
time.Sleep(10 * time.Second)
}package tests
import (
"context"
"os"
"testing"
"time"
zerologAdapter "github.com/cnmax/gologging-ext/adapters/zerolog"
"github.com/cnmax/gologging-ext/pipeline"
"github.com/cnmax/gologging-ext/sinks/cls"
"github.com/cnmax/gologging-ext/sinks/telegram"
"github.com/cnmax/gologging-ext/sinks/wechat"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func TestZerologAdapter(t *testing.T) {
ctx := context.Background()
clsSink := cls.New(
ctx,
"ap-shanghai.cls.tencentcs.com",
"your-secret-id",
"your-secret-key",
"your-topic-id",
)
wechatSink := wechat.New(
ctx,
"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx",
)
telegramSink := telegram.New(
ctx,
"your-bot-token",
your-chat-id,
)
dispatcher := pipeline.NewDispatcher(
pipeline.Build(clsSink),
//pipeline.Build(telegramSink),
pipeline.NewAsync(
pipeline.NewRetry(telegramSink, 3, time.Second),
),
)
multi := zerolog.MultiLevelWriter(
zerolog.ConsoleWriter{Out: os.Stdout},
zerologAdapter.NewWriter(dispatcher, zerolog.InfoLevel),
zerologAdapter.NewWriter(pipeline.NewAsync(wechatSink), zerolog.ErrorLevel),
)
logger := zerolog.
New(multi).
With().Timestamp().Logger().
With().Caller().Logger()
log.Logger = logger
log.Error().
Str("user", "xxx").
Int("v", 18).
Msg("发生错误了")
time.Sleep(10 * time.Second)
}支持扩展多种输出目标(可结合 async / batch / retry 使用):
用于日志上报至 CLS(Cloud Log Service)
func New(ctx context.Context, endpoint, secretID, secretKey, topicID string, opts ...Option) core.WriterendpointCLS接入地址secretID腾讯云密钥secretKey腾讯云密钥topicID日志主题 ID
用于企业微信群告警通知
func New(ctx context.Context, webhook string, opts ...Option) core.Writerwebhook企业微信机器人地址
用于机器人消息推送
func New(ctx context.Context, token string, chatID int, opts ...Option) core.WritertokenTelegram Bot TokenchatID聊天 ID
用于企业告警通知
func New(ctx context.Context, accessToken, secret string, opts ...Option) core.WriteraccessTokenWebhook URL 中的 access_tokensecret签名密钥(开启加签时必填)
用于团队消息推送
func New(ctx context.Context, webhook, secret string, opts ...Option) core.Writerwebhook飞书机器人地址secret签名密钥(开启加签时必填)
实现 core.Writer 接口即可:
type Writer interface {
Write(entry *Entry) error
}示例:
type MySink struct{}
func (s *MySink) Write(entry *core.Entry) error {
// 自定义处理逻辑
return nil
}Pipeline Builder 提供了一种灵活的方式来配置日志处理管道,支持异步、批量、重试等特性的组合。
import (
"time"
"github.com/cnmax/gologging-ext/pipeline"
"github.com/cnmax/gologging-ext/sinks/cls"
)
// 默认配置
sink := cls.New(ctx, endpoint, secretID, secretKey, topicID)
writer := pipeline.Build(sink)
// 自定义配置
writer := pipeline.Build(sink, &pipeline.BuildOptions{
EnableAsync: true,
EnableBatch: true,
EnableRetry: true,
BatchSize: 200,
FlushInterval: 5 * time.Second,
MaxRetries: 5,
BaseDelay: 200 * time.Millisecond,
})
// 仅启用异步
writer := pipeline.Build(sink, &pipeline.BuildOptions{
EnableAsync: true,
EnableBatch: false,
EnableRetry: false,
})
// 与其他管道组合使用
dispatcher := pipeline.NewDispatcher(
pipeline.Build(clsSink), // CLS sink 使用默认配置
pipeline.Build(telegramSink, &pipeline.BuildOptions{ // Telegram 自定义配置
EnableAsync: true,
EnableRetry: true,
EnableBatch: false, // 消息通知不需要批量
MaxRetries: 3,
}),
pipeline.Build(wechatSink, &pipeline.BuildOptions{ // 微信告警
EnableAsync: true,
EnableBatch: false,
EnableRetry: true,
MaxRetries: 5,
BaseDelay: 1 * time.Second,
}),
)type BuildOptions struct {
// 功能开关
EnableAsync bool
EnableBatch bool
EnableRetry bool
// 批量配置
BatchSize int
FlushInterval time.Duration
// 重试配置
MaxRetries int
BaseDelay time.Duration
}DefaultBuildOptions() = &BuildOptions{
EnableAsync: true,
EnableBatch: true,
EnableRetry: true,
BatchSize: 100,
FlushInterval: 2 * time.Second,
MaxRetries: 3,
BaseDelay: 100 * time.Millisecond,
}- 日志聚合 / 转发
- 告警 / 通知系统(飞书、钉钉、Webhook 等)
- 多目标日志输出(文件 + 云服务)