slsh

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2022 License: MIT Imports: 22 Imported by: 1

README

Aliyun Log Hook for Logrus

godoc reference

此 Hook 用于将通过 logrus 记录的日志发送到阿里云日志服务.

特点:

  • 采用非阻塞设计, 由一个后台线程将日志批量刷到远端日志库.
  • 采用轻量级设计, 直接使用 PutLogs 接口, 不依赖于 github.com/aliyun/aliyun-log-go-sdk
  • 内存占用较低, 大约是直接使用 sdk 的 70%

安装

go get -u github.com/GotaX/logrus-aliyun-log-hook

使用指南

package main

import (
	"math/rand"
	"os"
	"time"

	"github.com/sirupsen/logrus"

	"github.com/GotaX/logrus-aliyun-log-hook"
)

func main() {
	hook, err := slsh.New(slsh.Config{
		Endpoint:     os.Getenv("ENDPOINT"),                // 接入点, 例如: "cn-hangzhou-intranet.log.aliyuncs.com",
		AccessKey:    os.Getenv("ACCESS_KEY"),              // 授权密钥对: key
		AccessSecret: os.Getenv("ACCESS_SECRET"),           // 授权密钥对: secret
		Project:      os.Getenv("PROJECT"),                 // 日志项目名称
		Store:        os.Getenv("STORE"),                   // 日志库名称
		Topic:        "demo",                               // 日志 __topic__ 字段
		Extra:        map[string]string{"service": "demo"}, // 日志附加字段, 可选
		// 更多配置说明, 参考字段注释
	})
	if err != nil {
		panic(err)
	}

	logrus.SetLevel(logrus.TraceLevel)
	logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
	logrus.AddHook(hook)

	// 加上这行关闭本地日志输出, 仅写入阿里云日志
	// logrus.SetOutput(ioutil.Discard)

	time.AfterFunc(5*time.Second, func() { _ = hook.Close() })

	for i := 0; i < 10; i++ {
		logrus.WithField("n", i).Info("Hi!")
		time.Sleep(time.Duration(rand.Intn(3) * int(time.Second)))
	}
}

Benchmark

I/O 部分对比, 配置: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz

go test -run ^BeachmarkWriter$ -bench=BenchmarkWriter -count 5 -benchmem

名称 CPU/op alloc/op allocs/op
hook 110µs ± 1% 9.51kB ± 0% 135 ± 0%
sls-sdk 127µs ± 3% 13.4kB ± 0% 165 ± 0%

外部依赖

.
  ├ github.com/golang/protobuf/proto
  ├ github.com/pierrec/lz4
  └ github.com/sirupsen/logrus

Documentation

Index

Examples

Constants

View Source
const (
	DefaultBufferSize = 100
	DefaultMessageKey = "message"
	DefaultLevelKey   = "level"
	DefaultTimeout    = 500 * time.Millisecond
	DefaultInterval   = 3 * time.Second
)

Variables

View Source
var (
	// levels >= info will be hooked
	DefaultVisibleLevels = []logrus.Level{
		logrus.PanicLevel,
		logrus.FatalLevel,
		logrus.ErrorLevel,
		logrus.WarnLevel,
		logrus.InfoLevel,
	}
	// Mapping to syslog level
	SyslogLevelMapping = func() LevelMapping {
		m := [7]int{0, 2, 3, 4, 6, 7, 8}
		return func(level logrus.Level) int { return m[level] }
	}()
)

Functions

func NewConverter

func NewConverter(messageKey, levelKey string,
	levelMapping LevelMapping,
	extra map[string]string,
	modifier ContentModifier,
) *converter

func NewService

func NewService(bufferSize int, interval time.Duration, flush func(...Message) error) *service

func NewWriter

func NewWriter(uri *url.URL, topic, source, accessKey string, accessSecret Secret, client *http.Client) *writer

Types

type AliyunError

type AliyunError struct {
	HTTPCode  int32  `json:"-"`
	Code      string `json:"errorCode"`
	Message   string `json:"errorMessage"`
	RequestID string `json:"-"`
}

func (AliyunError) Error

func (a AliyunError) Error() string

type Config

type Config struct {
	// 阿里云日志接入地址, 格式: "<region>.log.aliyuncs.com",
	// 例如: "cn-hangzhou-intranet.log.aliyuncs.com",
	// 更多接入点参考: https://help.aliyun.com/document_detail/29008.html?spm=a2c4g.11174283.6.1118.292a1caaVMpfPu
	Endpoint        string
	AccessKey       string            // 密钥对: key
	AccessSecret    string            // 密钥对: secret
	Project         string            // 日志项目名称
	Store           string            // 日志库名称
	Topic           string            // 日志 __topic__ 字段
	Source          string            // 日志 __source__ 字段, 可选, 默认为 hostname
	Extra           map[string]string // 日志附加字段, 可选
	BufferSize      int               // 本地缓存日志条数, 可选, 默认为 100
	Timeout         time.Duration     // 写缓存最大等待时间, 可选, 默认为 500ms
	Interval        time.Duration     // 缓存刷新间隔, 可选, 默认为 3s
	MessageKey      string            // 日志 Message 字段映射, 可选, 默认为 "message"
	LevelKey        string            // 日志 Level 字段映射, 可选, 默认为 "level"
	LevelMapping    LevelMapping      // 日志 Level 内容映射, 可选, 默认按照 syslog 规则映射
	VisibleLevels   []logrus.Level    // 日志推送 Level, 可选, 默认推送 level >= info 的日志
	HttpClient      *http.Client      // HTTP 客户端, 可选, 默认为 DefaultClient
	ContentModifier ContentModifier   // 在发送前编辑日志内容, 可选, 默认为空
	// contains filtered or unexported fields
}

日志配置

type ContentModifier added in v1.1.0

type ContentModifier interface {
	Modify(contents map[string]string)
}

type ContentModifierFunc added in v1.1.0

type ContentModifierFunc func(map[string]string)

func (ContentModifierFunc) Modify added in v1.1.0

func (f ContentModifierFunc) Modify(contents map[string]string)

type Converter

type Converter interface {
	Message(entry *logrus.Entry) Message
}

type Hook

type Hook struct {
	// contains filtered or unexported fields
}
Example
hook, err := New(Config{
	Endpoint:     os.Getenv("ENDPOINT"),
	AccessKey:    os.Getenv("ACCESS_KEY"),
	AccessSecret: os.Getenv("ACCESS_SECRET"),
	Project:      os.Getenv("PROJECT"),
	Store:        os.Getenv("STORE"),
	Topic:        "demo",
	Extra:        map[string]string{"service": "demo"},
})
if err != nil {
	panic(err)
}

logrus.SetLevel(logrus.TraceLevel)
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
logrus.AddHook(hook)

time.AfterFunc(5*time.Second, func() { _ = hook.Close() })

for i := 0; i < 5; i++ {
	logrus.WithField("n", i).Info("Hi!")
	time.Sleep(time.Duration(rand.Intn(3) * int(time.Second)))
}
Output:

func New

func New(c Config) (*Hook, error)

func NewCustom

func NewCustom(timeout time.Duration, visibleLevels []logrus.Level,
	converter Converter, writer Writer, service Service) *Hook

func (*Hook) Close

func (h *Hook) Close() error

func (*Hook) CloseContext

func (h *Hook) CloseContext(ctx context.Context) error

func (*Hook) Fire

func (h *Hook) Fire(entry *logrus.Entry) error

func (*Hook) Levels

func (h *Hook) Levels() []logrus.Level

type LevelMapping

type LevelMapping func(level logrus.Level) int

日志级别映射

type Message

type Message struct {
	Time     time.Time
	Contents map[string]string
}

type Secret

type Secret []byte

func (Secret) String

func (s Secret) String() string

type Service

type Service interface {
	Push(ctx context.Context, message Message) error
	Start()
	Stop(ctx context.Context) error
}

type Writer

type Writer interface {
	WriteMessage(messages ...Message) error
}

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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