Signed-off-by: Xe Iaso <me@xeiaso.net>
Instrument the three things an operator needs to see and serve them on a
dedicated listener (-metrics-bind, default :9090; empty disables):
- s3fs: count + latency per S3 API operation (GetObject, PutObject, …) via a
process-level observer set with s3fs.SetMetricsObserver, keeping s3fs free of
any prometheus import.
- git ops: count + latency + in-flight gauge per protocol+service+status,
wrapped once per transport handler (http/git/ssh).
- auth: count + latency per transport+operation+decision, routed through a new
(*daemon).authorize chokepoint that all three transports now call.
Extras: push-hook runs (ok/error/timeout) with latency, repos auto-created
counter, and the default registry's Go-runtime + process collectors.
Per the operator's call there is no repo label (unbounded cardinality); git
ops are keyed by protocol+service+status only.
All vectors live in internal/metrics via promauto on the default registry,
exposed by promhttp.Handler under the existing errgroup Serve/Shutdown idiom.
Hooks now run synchronously and stream stdout/stderr to the pushing client
as "remote: ..." lines over the git sideband progress channel (band 2).
Previously they ran asynchronously after the push response, and output was
captured to slog only — the client never saw it.
To support streaming, fork go-git's transport.ReceivePack (v6) into
cmd/objgitd/receivepack.go as receivePackStreaming(). go-git keeps the
sideband Muxer internal and sends the closing flush-pkt before returning,
so there's no public seam to inject progress. The fork adds one callback
onUpdated(progress io.Writer), invoked after report-status but before the
final flush. When sideband is negotiated, progress writes to band 2
(ProgressMessage); otherwise it's nil and hooks fall back to logging.
HTTP adds a flush-on-write wrapper (flushWriter) to the receive-pack
response so net/http buffering doesn't hold the "remote:" lines back.
git:// and SSH write through live sockets and need no such wrapper.
Remove the now-dead async machinery: hookWG field and its shutdown drain.
Hooks complete before receivePackStreaming returns, so the connection
already holds them until completion.
Update tests to assert hook output appears in the push output (as "remote:"
lines) rather than in logs. Add TestSmartHTTPHookStreams to cover the HTTP
flush path. All three transports (git://, HTTP, SSH) verified.
Note: Clients now wait for hooks to finish (bounded by -hook-timeout,
default 60s) before the push completes, rather than push completing while
hooks run in the background. This is inherent to streaming output live.
Assisted-by: Claude Opus 4.8 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>