Ali Farhoudi
Ali Farhoudi

Reputation: 6020

UberZap with gelf driver writes whole log into message field

I'm using uber-zap for logging and I'm trying to log to graylog in GELF format. Log is written successfully but the whole json is being sent as message key of log record.

message: {"level":3,"timestamp":"2022-05-23T12:20:00.746+0430","caller":"log/log_zap.go:53","short_message":"Get Product Detail Error ","message":"product not found"}

But what I need the fields to be written in separated fields, like:

message: "product not found"
level:3
timestamp:"2022-05-23T12:20:00.746+0430"
caller:"log/log_zap.go:53"
short_message:"Get Product Detail Error "

So that I can search among fields.

This is my code:

writers = make([]io.Writer, 0, len(ws))
udpWriter, _ := gelf.NewUDPWriter(NewGraylogWriterConfig(cnf))
writers = append(writers, udpWriter)

var writeSyncers = make([]zapcore.WriteSyncer, len(writers))
for i, w := range writers {
    writeSyncers[i] = zapcore.AddSync(w)
}

encoderConfig := uberzap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
enc := zapcore.NewJSONEncoder(encoderConfig)

core := zapcore.NewCore(enc, zapcore.NewMultiWriteSyncer(writeSyncers...), uberzap.InfoLevel)
sugar := uberzap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)).Sugar()

sugar.Errorw(msg, FieldsToArray(fields)...)

I'm using Graylog2/go-gelf.v2 for my graylog writer.

I also have tried NewConsoleEncoder instead of NewJSONEncoder. (not working either)

Any help is appreciated.

Upvotes: 1

Views: 476

Answers (1)

Elad Aharon
Elad Aharon

Reputation: 570

Here's the thing, your library offers a simple way of sending messages over gelf without extra care to message fields like "level" or "message".

zap logger is build with "zap core" interface which is the main engine, composed of 3 components:

  1. Encoder - controls message encoding process i.e: to JSON format, console format ..
  2. WriteSyncer - controls where to send (write and sync) the final output i.e: stdout, sterr, some UDP address..
  3. LevelEnabler - controls which log level should be logged i.e: debug, info..

gelf protocol defines JSON messages with required fields and their types. gelf might be sent via TCP / UDP over network (each one has it's own pros and cons). From the last 2 sentences we can infer we need 2 things:

  1. encoder our message to gelf format (with version, host, short_message..).
  2. write it to some TCP / UDP address.

Your library only offers the "WriterSyncer" part but we also MUST interfere in the encoding part. If you'll look at your library implementation you will see they simply got your msg (probably in JSON format by default) and send it under "short/long_message" field without extracting inner fields as you wanted.

Lucky us, someone already wrote a nice, highly configurable library for "gelf zap core" https://github.com/snovichkov/zap-gelf

Good luck and happy gelfing!

Upvotes: 0

Related Questions