What it does

lambdalog is a ~400-line Go package that wraps slog with the set of defaults I’ve ended up writing on every Lambda I ship:

  • JSON output to stderr (Lambda captures this and CloudWatch is happy)
  • automatically includes request_id, function_name, function_version, cold_start as fields
  • a helper to pull a correlation id from common event shapes (API Gateway, SQS, EventBridge) and put it on the logger’s context
  • sane level defaulting from the LOG_LEVEL env var
  • no dependencies besides stdlib

It is not a replacement for a real observability setup. It just makes the CloudWatch view halfway readable.

Why I made it

At a previous job we ran ~80 Lambdas and every single one rolled its own logging. When production caught fire we’d find out some log lines had requestId, some had reqId, some had request_id, and half were plain text. I vendored this into one of them, liked it, open-sourced it, and it’s the thing I reach for every time now.

How it works

It’s a thin constructor that builds an slog.Logger with a JSON handler and a pre-populated attribute set derived from Lambda environment variables. There’s one helper for context propagation:

func Handler(ctx context.Context, ev events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    log := lambdalog.FromContext(ctx).With("path", ev.Path)
    log.Info("handling request")
    // ...
}

FromContext knows about lambdacontext.LambdaContext and enriches the logger with the invocation’s request id; if you pass a context without one, it returns a sensible default logger.

Install

No module hosting. Copy the package tree from /src/lambdalog/ into your project’s internal/lambdalog/ and go from there. It’s small (~600 lines), pinning it locally is the sensible move.

Go 1.21+ (for slog).

Roadmap

Mostly stable. I occasionally add a helper for a new event shape. If you’re looking at this and want to add one for CloudFrontEvent or Kinesis, PRs welcome.