Created
August 31, 2025 15:44
-
-
Save arsharaj/b4f7748171bf24650f565198e208148c to your computer and use it in GitHub Desktop.
go : slog and log to elasticsearch handler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "context" | |
| "encoding/json" | |
| "fmt" | |
| "log" | |
| "log/slog" | |
| "time" | |
| "github.com/elastic/go-elasticsearch/v8" | |
| ) | |
| // ElasticHandler is a slog handler that sends logs to elasticsearch | |
| type ElasticHandler struct { | |
| es *elasticsearch.Client | |
| index string | |
| level slog.Level | |
| attr []slog.Attr | |
| withGroup string | |
| } | |
| func NewElasticHandler(es *elasticsearch.Client, index string, level slog.Level) *ElasticHandler { | |
| return &ElasticHandler{ | |
| es: es, | |
| index: index, | |
| level: level, | |
| } | |
| } | |
| func (esh *ElasticHandler) Enabled(ctx context.Context, level slog.Level) bool { | |
| return level >= esh.level | |
| } | |
| func (esh *ElasticHandler) Handle(ctx context.Context, r slog.Record) error { | |
| data := make(map[string]any) | |
| data["time"] = r.Time.Format(time.RFC3339) | |
| data["level"] = r.Level.String() | |
| data["msg"] = r.Message | |
| r.Attrs(func(a slog.Attr) bool { | |
| data[a.Key] = a.Value.Any() | |
| return true | |
| }) | |
| body, err := json.Marshal(data) | |
| if err != nil { | |
| return err | |
| } | |
| // Send to elasticsearch | |
| res, err := esh.es.Index( | |
| esh.index, | |
| bytes.NewReader(body), | |
| esh.es.Index.WithContext(ctx), | |
| esh.es.Index.WithRefresh("true"), | |
| ) | |
| if err != nil { | |
| return err | |
| } | |
| defer res.Body.Close() | |
| if res.IsError() { | |
| return fmt.Errorf("error indexing log: %s", res.String()) | |
| } | |
| return nil | |
| } | |
| func (esh *ElasticHandler) WithAttrs(attrs []slog.Attr) slog.Handler { | |
| newEsh := *esh | |
| newEsh.attr = append(newEsh.attr, attrs...) | |
| return &newEsh | |
| } | |
| func (esh *ElasticHandler) WithGroup(name string) slog.Handler { | |
| newEsh := *esh | |
| newEsh.withGroup = name | |
| return &newEsh | |
| } | |
| func main() { | |
| // Connect to elasticsearch | |
| es, err := elasticsearch.NewDefaultClient() | |
| if err != nil { | |
| log.Fatalf("error creating es client : %v", err) | |
| } | |
| // Create handler | |
| esHandler := NewElasticHandler(es, "system-logs", slog.LevelInfo) | |
| // Create logger | |
| logger := slog.New(esHandler) | |
| // Example logs | |
| logger.Info("System stated", slog.String("host", "server-01"), slog.Int("pid", 1234)) | |
| logger.Error("Disk space low", slog.String("path", "/var/log"), slog.Float64("usage", 92.4)) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment