Skip to content

tawAsh1/resolog

Repository files navigation

resolog

A resource-aware CloudWatch log tailer. resolog = resolve + log.

CI Go Reference 日本語 README

Most tools answer "how do I tail a log group?" (aws logs tail, lucagrulla/cw, StartLiveTail). resolog answers the question that comes first: given a resource, what should I even tail? — then interleaves every stream it finds, docker-compose style.

Main use: hand it a Step Functions execution ARN and it tails the state machine plus every Lambda, Batch, and ECS task that execution ran, all together.

Install

go install github.com/tawAsh1/resolog/cmd/resolog@latest

Or download a binary from Releases. They carry build-provenance attestations:

gh attestation verify resolog_*.tar.gz --repo tawAsh1/resolog

Usage

The real backends use the standard AWS credential chain. The default backend is live (StartLiveTail).

resolog log-group:/aws/lambda/my-fn                 # real-time tail
resolog --backend poll -f log-group:/my/group       # historical, then follow
resolog --backend poll --since 1h --sort -t sfn-execution:<execution-arn>   # a finished run, in time order
resolog --backend poll --since "2026-07-05 09:00" --until "2026-07-05 10:00" --filter '?ERROR ?WARN' log-group:/my/group   # a window, server-side filtered
resolog --output json log-group:/my/group | jq .message               # machine-readable, one JSON object per line
resolog --fields level,msg log-group:/my/group                        # structured logs: show just these fields

resolog arn:aws:ecs:us-east-1:123:task/prod/abc123  # paste a raw ARN, no scheme needed

resolog ls sfn-execution <state-machine-arn>        # list executions, pick one
resolog ls batch-job <queue>
resolog ls ecs-task <cluster>
resolog ls log-group /aws/lambda/

resolog pick --backend poll --sort sfn-execution <state-machine-arn>   # list, choose, tail in one step

pick shows the same listing as ls, lets you choose one entry interactively (through fzf when it is installed, else a numbered prompt), and tails it — tail flags come first, then <scheme> [filter].

References are a raw resource ARN, <scheme>:<rest>, or a bare log group name. A raw ARN dispatches by its service, so you can paste one as-is. Schemes: log-group, sfn-execution, sfn-state-machine (tails its most recent execution), batch-job, batch-queue (every active job in a queue), lambda, ecs-task (one stream per container), ecs-service (every task in a service), codebuild (a build id/ARN or a project name), cfn-stack (everything a CloudFormation stack logs).

Flag Description
--backend live|poll live (StartLiveTail, default) or poll (FilterLogEvents, historical)
-f keep polling for new events (poll backend)
--since only fetch events at/after this time: a duration ago (10m, 1h30m) or an absolute time (RFC3339, 2026-07-05 09:00, 15:04)
--until only fetch events at/before this time; pair with --since for a window. Same forms as --since
--filter CloudWatch Logs filter pattern, applied server-side (both backends)
--grep client-side regexp; only events whose message matches are shown
--output text|json json writes one compact JSON object per line ({"time","group","stream","label","message"}); -t/--no-color are ignored there
--fields comma-separated JSON fields (dot paths like log.level) to show instead of the full message; text output only. Non-JSON lines pass through unchanged
--sort poll only; buffer and print in time order across streams (see Ordering)
-t show timestamps
--no-color disable colored output

--filter and --grep compose: --filter narrows what CloudWatch sends over the wire, --grep further narrows what gets printed. With --fields, --grep matches the extracted view — what you see is what it greps.

Ordering

By default lines print in arrival order — interleaved across sources, like docker compose logs. Across different streams this is not time order.

--sort (poll, finished resources only) buffers everything and prints in time order by each resource's own reported clock. Honest caveats:

  • Clocks differ across resources; resolog never claims causal order between them.
  • CloudWatch ingestion lags, so a finished task's last lines (e.g. a failure stack trace) can land late and fall outside the window.
  • A whole-log-group source (e.g. a Lambda tailed by group) can include lines from other invocations within the window.
  • --sort waits for the fetch to finish before printing; on Ctrl-C it flushes the ordered prefix it has so far.
  • --sort holds everything in memory; it errors past --sort-max events (default 1,000,000) rather than risk running out of memory. Narrow with --since/--until.

Live output — the newest lines as they arrive — is intentionally never reordered. Without --sort, streaming uses a fixed amount of memory (a page at a time) no matter how much you tail.

Library

resolog is also a Go library; the CLI is just one consumer. See the package docs.

res, _ := sfn.New(sfnClient, sfn.WithBatchResolver(batch.New(batchClient))).
	Resolve(ctx, executionARN)
sink := resolog.NewRenderer(os.Stdout, true, false)
resolog.Tail(ctx, res, livetail.New(logsClient), sink)

Integration tests

Unit tests use fakes; integration/ (build tag integration) exercises the loggroup + poll backend, the sfn resolver, the sfn-state-machine resolver, and the cfn-stack resolver against a real-ish AWS API via LocalStack (community edition). Run them with:

make integration-test   # spins up LocalStack in Docker, runs the tests, tears down

They're skipped by plain go test ./... and require Docker; see integration/*_test.go for what's covered, and integration/unsupported_test.go for the resolvers LocalStack community can't back (Batch, ECS, CodeBuild are Pro-only there).

Status

v0, still young, but now exercised against real production AWS workloads, not just unit tests. Extracted from batchkoi's log tailer.

License

MIT

About

Resource-aware CloudWatch log tailer: resolve which logs a resource (Step Functions execution, Batch job, Lambda) emits, then interleave them. Go library + CLI.

Topics

Resources

License

Security policy

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors