zerolog
zerolog copied to clipboard
QUESTION: How to encode caller information to match GCP LogEntrySourceLocation?
Hey there! 🙂
I am trying to encode the caller information (file, line & function) so it matches the requirements for GCP LogEntry's LogEntrySourceLocation field. This is important so the caller information can be automatically extracted by GCP's LogAgent.
A result should look something like the following:
{
"caller":{
"file":"get_data.go",
"line":"142",
"function":""
}
}
Unfortunately I could not see a way to implement a custom zerolog.CallerMarshalFunc() to match the required format with a nested object.
// excerpt from event.go:743
func (e *Event) caller(skip int) *Event {
if e == nil {
return e
}
pc, file, line, ok := runtime.Caller(skip + e.skipFrame)
if !ok {
return e
}
e.buf = enc.AppendString(enc.AppendKey(e.buf, CallerFieldName), CallerMarshalFunc(pc, file, line))
return e
}
I am wondering whether it is possible to achieve this functionality with how the caller func is currently implemented with enc.AppendString().
I hope I was able to explain the problem in an understandable way.
Great regards, Dario
Hi @capthiron,
currently I'm looking into this as well. I really do want to have a possibility to get the caller in GCP LogEntrySourceLocation format. My current workaround works, but is really not a good practice I guess. I completely ignore the build in possibilities of zerolog and do not use With().Caller() at all. I build a hook for getting the caller information in every log entry:
type CallerHook struct{}
type logEntrySourceLocation struct {
File string `json:"file"`
Line int `json:"line,string"`
Function string `json:"function,omitempty"`
}
func (h *CallerHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
if pc, file, line, ok := runtime.Caller(3); ok {
sourceLocation := logEntrySourceLocation{
File: file,
Line: line,
Function: runtime.FuncForPC(pc).Name(),
}
e.Interface("sourceLocation", sourceLocation)
}
}
This hook is added to my global zerolog logger. That works very nicely, but actually ignores the options zerolog gives.
Another idea I had was using the CallerMarshalFunc in zerolog:
func marshalCaller(pc uintptr, file string, line int) string {
sourceLocation := logEntrySourceLocation{
File: file,
Line: line,
Function: runtime.FuncForPC(pc).Name(),
}
bs, err := json.Marshal(sourceLocation)
if err != nil {
panic(err)
}
return string(bs)
}
But this gives you a quoted string when zerolog internally calls enc.AppendString in func (e *Event) caller(skip int) *Event as Encoder.AppendString quotes the JSON string from my marshalCaller func (at least from my understanding)
Probably anybody who is reading this issue has some others ideas, but for now I guess zerolog's caller function has to be rewritten to handle caller information in JSON format.
Regards, Marcel