leakwatch

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: MIT Imports: 15 Imported by: 0

README

leakwatch

Library-first goroutine leak detection for Go 1.27+, built on the runtime's goroutine leak profile. A thin CLI supports offline analysis of exported profiles and live pprof inspection.

Requirements

  • Go 1.27 or newer.

Install

go get github.com/KoJaco/leakwatch@v0.1.0

For the CLI binary, see GitHub Releases.

Usage

package main

import (
    "context"
    "time"

    "github.com/KoJaco/leakwatch"
)

func main() {
    watcher := leakwatch.New(
        leakwatch.WithInterval(5 * time.Minute),
        leakwatch.WithJitter(30 * time.Second),
    )

    watcher.Start(context.Background())
    _ = watcher.ServeDebug("/debug/leaks")
}

CLI

# Analyze an exported goroutine leak profile offline
leakwatch analyze profile.pb.gz

# JSON output
leakwatch analyze -json profile.pb.gz

# Fetch and inspect a live pprof endpoint (localhost only by default)
leakwatch inspect http://127.0.0.1:6060/debug/pprof/goroutineleak
leakwatch inspect -json http://localhost:6060/debug/pprof/goroutineleak

# Fetch a remote host explicitly
leakwatch inspect --allow-remote https://staging.example/debug/pprof/goroutineleak

Pipeline

Scheduler → Observer.Sample()
              ├── Collector  → Profile
              ├── Fingerprinter → []LeakCluster
              ├── History.Record()
              └── Analyze() → []Leak → Snapshot
                                              ↓
                                    Prometheus / HTTP / JSON

Four core concepts

Concept Meaning
Profile Immutable point-in-time runtime snapshot
Fingerprint Stable machine identity for a leak cluster
Observation Timestamped cluster counts — raw historical data
Leak Current interpreted state of a cluster

Who should use this?

leakwatch is an early release (v0.1.0) for teams running Go 1.27+ who want ongoing monitoring of runtime-classified goroutine leaks.

Good fit when you:

  • Already expose net/http/pprof (or equivalent) with the goroutineleak profile
  • Can accept periodic leak-detection GC during sampling (sampling.md)
  • Need Prometheus metrics and/or a debug HTTP handler for leak attribution

Not a fit when you need:

  • General goroutine profiling or counting (see limitations.md)
  • Detection of slow-but-runnable goroutines or leaks on reachable channels
  • A stability guarantee equivalent to v1.0.0 — validate in your environment first

Security

The debug HTTP handler (ServeDebug) and Prometheus metrics expose goroutine stack traces and opaque leak_id labels. Treat them as sensitive operational data.

  • Bind debug and pprof endpoints to loopback (127.0.0.1) unless traffic is restricted by network policy.
  • Never register ServeDebug on a public HTTP mux without protection. Wrap the handler with middleware:
import (
    "net/http"

    httpexport "github.com/KoJaco/leakwatch/export/http"
)

auth := func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w, r) {
        if r.Header.Get("Authorization") != "Bearer "+token {
            http.Error(w, "unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}
_ = watcher.ServeDebug("/debug/leaks", httpexport.WithMiddleware(auth))
  • leakwatch inspect accepts localhost URLs only by default. Pass --allow-remote to fetch other hosts (use only with trusted URLs).
  • Profile fetch uses bounded reads and HTTP timeouts (see WithMaxProfileBytes and WithHTTPTimeout).
  • See SECURITY.md for vulnerability reporting and deployment guidance.

Documentation

Doc Topic
SECURITY.md Vulnerability reporting and operational security
architecture.md Pipeline, package boundaries, implementation order, testing strategy
sampling.md Scheduler, jitter, sample gate, GC impact
fingerprinting.md ID vs Key vs LeakSite, normalization, clustering
limitations.md Runtime detector boundaries, metric interpretation
metrics.md Prometheus metrics and query examples
pr-checklist.md Per-phase PR checklist for implementation

License

MIT — see LICENSE.

Documentation

Overview

Package leakwatch detects goroutine leaks using the Go 1.27+ runtime leak profile.

The public API is intentionally small. Create a Watcher, start it, and optionally expose debug endpoints for human-readable leak attribution.

watcher := leakwatch.New(leakwatch.WithInterval(5 * time.Minute))
watcher.Start(context.Background())

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Option

type Option func(*config)

Option configures a Watcher.

func WithHTTPClient

func WithHTTPClient(client *http.Client) Option

WithHTTPClient sets the HTTP client used to fetch pprof profiles.

func WithHTTPTimeout

func WithHTTPTimeout(d time.Duration) Option

WithHTTPTimeout sets the timeout for the default pprof HTTP client. Ignored when WithHTTPClient is also set.

func WithHistoryCapacity

func WithHistoryCapacity(n int) Option

WithHistoryCapacity sets the number of observations retained in memory.

func WithInterval

func WithInterval(d time.Duration) Option

WithInterval sets the sampling interval.

func WithJitter

func WithJitter(d time.Duration) Option

WithJitter sets random jitter applied before each sample.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger sets the logger used for sample failures and watcher lifecycle events.

func WithMaxProfileBytes

func WithMaxProfileBytes(n int64) Option

WithMaxProfileBytes sets the maximum pprof response body size.

func WithPProfURL

func WithPProfURL(url string) Option

WithPProfURL sets the pprof goroutine leak endpoint for the default collector.

func WithSampleGate

func WithSampleGate(gate collector.SampleGate) Option

WithSampleGate sets a gate that can skip individual samples.

type Watcher

type Watcher struct {
	// contains filtered or unexported fields
}

Watcher samples goroutine leak profiles on a schedule and maintains leak state.

func New

func New(opts ...Option) *Watcher

New creates a Watcher with the given options.

func (*Watcher) LastSampleError

func (w *Watcher) LastSampleError() error

LastSampleError returns the most recent sample failure, if any.

func (*Watcher) Observations

func (w *Watcher) Observations() []domain.Observation

Observations returns the retained observation history.

func (*Watcher) ServeDebug

func (w *Watcher) ServeDebug(path string, opts ...httpexport.RegisterOption) error

ServeDebug registers leak debug handlers on http.DefaultServeMux at path. Pass httpexport.WithMiddleware to add auth or other protection before exposing stack traces on a shared HTTP server.

func (*Watcher) Snapshot

func (w *Watcher) Snapshot() analysis.Snapshot

Snapshot returns the current export-ready leak state.

func (*Watcher) Start

func (w *Watcher) Start(ctx context.Context)

Start begins periodic sampling in a background goroutine.

func (*Watcher) Stop

func (w *Watcher) Stop()

Stop cancels periodic sampling.

Directories

Path Synopsis
cmd
leakwatch command
export
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL