Как добавить в логгер место, откуда вызван код?



@veryoriginalnickname

Есть логгер zerolog, инициализирую его в переменную Logger, чтоб потом использовать по всему приложению. Хотелось бы добавить в логгер такую штуку, чтоб он выводил еще и место, откуда вызвана функция, типа «main.go:23». Я находил несколько функций, которые позволяют это сделать, имена функций и строка действительно выводились. Но только они все время были в одном месте, независимо от того откуда была вызвана функция, все время было условное «main.go:23».
Если кратко, то: как сделать так, чтоб при каждом вызове Logger, в лог добавлялась функция и строка, откуда он был вызван?
Пока что я остановился на таком неработающем коде:

package _core

import (
	"github.com/rs/zerolog"
	"os"
	"runtime"
	"strconv"
	"strings"
)

var Logger zerolog.Logger

func logger(){
	consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
	multi := zerolog.MultiLevelWriter(consoleWriter, os.Stdout)
	Logger = zerolog.New(multi).With().Timestamp().Logger()
}


func getFuncName() *zerolog.Logger {
	pc, file, line, ok := runtime.Caller(1)
	if !ok {
		panic("Could not get context info for logger!")
	}
	filename := file[strings.LastIndex(file, "https://qna.habr.com/")+1:] + ":" + strconv.Itoa(line)
	funcname := runtime.FuncForPC(pc).Name()
	fn := funcname[strings.LastIndex(funcname, ".")+1:]
	return Logger.With().Str("file", filename).Str("function", fn).Logger()
}


Решения вопроса 1



@veryoriginalnickname Автор вопроса

Кажется, теперь работает. Взял кусок кода отсюда и отсюда.
Как я понял: инициализируется Logger, и устанавливается на него хук, в хуке можно получить место, откуда вызвана функция, получаем, и подмешиваем в Logger.
Код получается такой (пишет лог в консоль и в .txt, но тут еще доделать надо чтоб переключался режим дебага на прод и так далее):

logger.go

package _core

import (
	"flag"
	"fmt"
	"github.com/rs/zerolog"
	"log"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
)

var Logger zerolog.Logger

func logger(){
	debug := flag.Bool("debug", false, "sets log level to debug")
	flag.Parse()
	zerolog.SetGlobalLevel(zerolog.InfoLevel)
	if *debug {
		zerolog.SetGlobalLevel(zerolog.DebugLevel)
	}
	var logsPath = fmt.Sprintf("%v/_temp/logs/log.txt", GetSrcDir())
	logFile, err := os.Create(logsPath)
	if err != nil {
		log.Fatal(err)
	}
	consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
	multi := zerolog.MultiLevelWriter(consoleWriter, logFile)
	Logger = zerolog.New(multi).With().Timestamp().Logger()
	Logger = Logger.Hook(CallerHook{})
}

type CallerHook struct{}
func (h CallerHook) Run(event *zerolog.Event, level zerolog.Level, msg string) {
	if _, file, line, ok := runtime.Caller(3); ok {
		var file = path.Base(file)
		var line = line
		filename := file[strings.LastIndex(file, "https://qna.habr.com/")+1:] + ":" + strconv.Itoa(line)
		event.Str("caller", filename)
	}
}

Пример использования (boot.go)

package _core

func Boot()  {
	logger()
	Logger.Info().Msg("boot settings...")
	settings()
	Logger.Info().Msg("boot database...")
	database()
	Logger.Info().Msg("boot routes...")
	routes()
	Logger.Info().Msg("done.")
}

Вывод (консоль):

5:59PM INF boot.go:5 > boot settings...
5:59PM INF boot.go:7 > boot database...
5:59PM INF boot.go:9 > boot routes...
5:59PM INF boot.go:11 > done.

Вывод (.txt):

{"level":"info","time":"2021-08-10T17:59:19+03:00","caller":"boot.go:5","message":"boot settings..."}
{"level":"info","time":"2021-08-10T17:59:19+03:00","caller":"boot.go:7","message":"boot database..."}
{"level":"info","time":"2021-08-10T17:59:20+03:00","caller":"boot.go:9","message":"boot routes..."}
{"level":"info","time":"2021-08-10T17:59:20+03:00","caller":"boot.go:11","message":"done."}

Комментировать

Ответы на вопрос 1



@dimuska139

Вот такой способ вы рассматривали? Тогда в самом верху будет стек вызовов сформирован

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *