samber / slog-graylog

🚨 slog: Graylog handler
https://pkg.go.dev/github.com/samber/slog-graylog/v2
MIT License
4 stars 4 forks source link

Messages don't make it to Graylog when called at end of program #4

Open bencromwell opened 1 month ago

bencromwell commented 1 month ago

Hello,

In handler.go there is a goroutine for writing the message.

func (h *GraylogHandler) Handle(ctx context.Context, record slog.Record) error {
        // snip

    go func() {
        _ = h.option.Writer.WriteMessage(msg)
    }()

        // snip
}

I'm finding that when a program attempts to write to Graylog immediately before it exits (such as a final error message), that message consistently never makes it to Graylog. The goroutines are all cancelled as soon as it exits, so it never finishes.

Changing this to just:

func (h *GraylogHandler) Handle(ctx context.Context, record slog.Record) error {
        // snip

        = h.option.Writer.WriteMessage(msg)

        // snip
}

Does ensure the logs are written. However, I assume it was made into a routine for a reason.

Is there a better way to resolve this?

samber commented 1 month ago

I moved this call into a goroutine, to prevent blocking the main thread.

After reviewing the library, I confirm a potential blocking behavior when you write to the socket.

I would suggest an update of the Graylog lib, to add buffering, followed by a defer graylog.Close() in your program, to flush before exiting.

WDYT?

bencromwell commented 1 month ago

Would this library need to change to depend on an interface in order to support such a change?

samber commented 1 month ago

If github.com/Graylog2/go-gelf could buffer logs and flush periodically to the connection, this slog-graylog lib would be non-blocking without goroutine.

But go-gelf would need a method to flush before program exit as well.