[Go] Практика анализа логов на основе Zap и ELK

Kibana

Zap — это высокопроизводительный инструмент ведения журналов с открытым исходным кодом от Uber.

Архитектура ELK, реализованная в этой статье, показана на рисунке ниже.Множественные источники вывода реализованы через настроенный Zap, а журналы выводятся в консоль (стандартный ввод-вывод) и MQ, а вход Logstash настроен на чтение журналов в MQ и их запись. в ES., и, наконец, отображается в Kibana.

В этой статье Redis используется в качестве реализации MQ, которую можно заменить другими MQ.

image.png

Индивидуальный Зап

Компонент Logger ZAP, который понимает, что автор понимает, как показано на рисунке ниже. Создание различных Zapcores, Multi-Format и многоуровневой вывод журнала может быть достигнут.

image.png

Сначала мы создаем логгер, у которого есть только один zapcore, который выводит на консоль.

func NewLogger() *zap.Logger {
	// 限制日志输出级别, >= DebugLevel 会打印所有级别的日志
	// 生产环境中一般使用 >= ErrorLevel
	lowPriority := zap.LevelEnablerFunc(func(lv zapcore.Level) bool {
		return lv >= zapcore.DebugLevel
	})

	// 使用 JSON 格式日志
	jsonEnc := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
	stdCore := zapcore.NewCore(jsonEnc, zapcore.Lock(os.Stdout), lowPriority)

	// logger 输出到 console 且标识调用代码行
	return zap.New(stdCore).WithOptions(zap.AddCaller())
}

func main() {
	logger := NewLogger()

	logger.Info("test logger info", zap.String("hello", "logger"))
}

Формат вывода журнала:

{"level":"info","ts":1578372154.69565,"caller":"hello/main.go:28","msg":"test logger info","hello":"logger"}

Далее добавляем лог синхронизации в zapcore redis,LevelEnablerиEncoderбез изменений, черезzapcore.AddSyncможет реализоватьio.WriterОбъект интерфейса преобразуется в то, что нужно zapWriteSyncer.

import (
	"os"

	"github.com/go-redis/redis"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

func NewRedisWriter(key string, cli *redis.Client) *redisWriter{
	return &redisWriter{
		cli: cli, listKey: key,
	}
}
// 为 logger 提供写入 redis 队列的 io 接口
type redisWriter struct {
	cli *redis.Client
	listKey string
}

func (w *redisWriter) Write(p []byte) (int, error) {
	n, err := w.cli.RPush(w.listKey, p).Result()
	return int(n), err
}

func NewLogger(writer *redisWriter) *zap.Logger {
	// 限制日志输出级别, >= DebugLevel 会打印所有级别的日志
	// 生产环境中一般使用 >= ErrorLevel
	lowPriority := zap.LevelEnablerFunc(func(lv zapcore.Level) bool {
		return lv >= zapcore.DebugLevel
	})

	// 使用 JSON 格式日志
	jsonEnc := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
	stdCore := zapcore.NewCore(jsonEnc, zapcore.Lock(os.Stdout), lowPriority)

	// addSync 将 io.Writer 装饰为 WriteSyncer
	// 故只需要一个实现 io.Writer 接口的对象即可
	syncer := zapcore.AddSync(writer)
	redisCore := zapcore.NewCore(jsonEnc, syncer, lowPriority)

	// 集成多个 core
	core := zapcore.NewTee(stdCore, redisCore)

	// logger 输出到 console 且标识调用代码行
	return zap.New(core).WithOptions(zap.AddCaller())
}

func main() {
	cli := redis.NewClient(&redis.Options{
		Addr: "127.0.0.1:6379",
	})
	writer := NewRedisWriter("log_list", cli)
	logger := NewLogger(writer)

	logger.Info("test logger info", zap.String("hello", "logger"))
}

Проверить наличие push в Redis:

127.0.0.1:6379> lpop log_list
"{\"level\":\"info\",\"ts\":1578373888.516468,\"caller\":\"hello/main.go:58\",\"msg\":\"test logger info\",\"hello\":\"logger\"}\n"

Создайте среду для лосей

Этот репозиторий содержит очень удобную среду elk, которую можно запустить напрямую с помощью docker и docker-compose, а также поддерживает изменение конфигурации через yml.

git clone https://github.com/deviantony/docker-elk.git

Изменить ввод logstash, расположение файла конфигурацииdocker-elk/logstash/pipeline/logstash.conf:

input {
	tcp {
		port => 5000
	}
	redis {
		data_type => "list"
		key => "log_list"
		host => "127.0.0.1"
		port => 6379
		db => 0
		threads => 2
	}
}

После модификации запустите elk и получите доступ к Kibana (http://localhost:5601), имя пользователя по умолчанию:elastic,пароль:changeme.

docker-compose up

При первом запуске необходимо создать шаблон индекса, который можно ввести в разделе «Шаблоны индекса» в разделе «Управление и администрирование эластичного стека» в правом нижнем углу домашней страницы.

image.png

Введите регулярное выражение для соответствия logstash

image.png

image.png

Выберите временную метку в качестве фильтра

image.png

Вернуться на страницу Discover после создания

image.png

Вызовите логгер для вывода лога, который можно увидеть на Kibana.

image.png

Суммировать

Zap и Elk также имеют много мощных функций, здесь показаны только самые основные, только для справки.