bundle

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: BSD-3-Clause Imports: 15 Imported by: 0

Documentation

Overview

Package bundle implements the external-analyser capture artifact: a tar stream containing a heap dump, a snapshot of the target's read-only memory segments (so literal pprof label strings can be recovered out of process), and metadata. The target process produces a bundle cheaply (no parsing); the analyser CLI feeds it into the same memusage.AnalyzeDump pipeline used by the in-process endpoint.

Index

Constants

View Source
const (
	MetaMember     = "meta.json"
	SegmentsMember = "rodata/segments.json"
	HeapDumpMember = "heap.dump"
)

Tar member names. heap.dump is emitted last (largest member); meta.json first so consumers can inspect a bundle cheaply. Readers must not rely on member order.

View Source
const (
	RodataOK          = "ok"
	RodataUnavailable = "unavailable"
	RodataDisabled    = "disabled"
	RodataTruncated   = "truncated"
)

Rodata status values recorded in Meta.Rodata.Status.

View Source
const DefaultMaxRodataBytes = 256 << 20

DefaultMaxRodataBytes caps the total read-only segment bytes embedded in a bundle when CaptureOptions.MaxRodataBytes is zero.

View Source
const FormatVersion = 1

FormatVersion is the bundle format produced by this package. Readers reject bundles with a greater version; unknown extra tar members are ignored for forward compatibility within a version.

Variables

This section is empty.

Functions

func CaptureSelf

func CaptureSelf(ctx context.Context, w io.Writer, opts CaptureOptions) error

CaptureSelf dumps the calling process's heap, snapshots its eligible read-only memory ranges, and streams a format-version-1 bundle tar to w. The heap dump is written to a temp file first (debug.WriteHeapDump needs a file descriptor and the tar header needs the size up front) and removed before returning.

The dump is captured before the rodata ranges are read; the ranges are read-only program data, so the two views are consistent without stopping the world twice.

func Handler

func Handler(hopts HandlerOptions) http.Handler

Handler returns an http.Handler that serves GET /debug/memusage/bundle by streaming a capture bundle of the current process.

HTTP semantics:

GET            -> application/x-tar bundle stream
GET?gc=0|1     -> overrides Capture.GCBeforeHeapDump for this request
other methods  -> 405 with Allow: GET

Errors before the first body byte produce a JSON ErrorResponse (capture_failed, 500). Once streaming has started the only honest failure mode is aborting the connection, so the client sees a truncated tar instead of a falsely complete one.

func Write

func Write(w io.Writer, in WriteInput) error

Write streams a format-version-1 bundle tar to w: meta.json, then rodata/segments.json and rodata/NNNNN.bin members, then heap.dump.

Types

type Bundle

type Bundle struct {
	Meta Meta
	// HeapDumpPath is the heap dump extracted to a temp file (removed
	// by Close).
	HeapDumpPath string
	// Segments serves the saved read-only segments as an
	// addrspace.Reader; nil when the bundle carries no rodata snapshot.
	Segments *SegmentsReader
	// Warnings to append to analysis diagnostics: the bundle's own
	// warnings plus the standard literal-label phrasing when the rodata
	// snapshot is absent or partial.
	Warnings []string
}

Bundle is an opened capture artifact ready for analysis.

func Open

func Open(r io.Reader) (*Bundle, error)

Open reads a bundle tar in a single pass. Member order is not significant; unknown members are ignored for forward compatibility. Callers must Close the returned Bundle.

func (*Bundle) Close

func (b *Bundle) Close() error

Close removes the extracted heap dump temp file. Safe to call multiple times.

type CaptureOptions

type CaptureOptions struct {
	// GCBeforeHeapDump triggers runtime.GC() before the dump so the
	// bundle reflects live memory rather than floating garbage.
	GCBeforeHeapDump bool
	// DisableRodata skips the read-only segment snapshot; literal pprof
	// label strings then surface as string_missing during analysis.
	DisableRodata bool
	// MaxRodataBytes caps total embedded segment bytes; 0 means
	// DefaultMaxRodataBytes. Segments that do not fit are dropped and
	// the rodata status becomes "truncated".
	MaxRodataBytes int64
	// Producer is recorded in meta.json (e.g. "bubblepprof/v0.2.0").
	Producer string
}

CaptureOptions configures CaptureSelf.

type HandlerOptions

type HandlerOptions struct {
	Capture CaptureOptions

	// Semaphore is the single-flight gate (capacity-1 channel). When nil
	// the handler creates a private one. Supplying the same channel used
	// by the /debug/memusage handler serializes the two endpoints, since
	// each triggers a stop-the-world WriteHeapDump.
	Semaphore chan struct{}
}

HandlerOptions configures Handler.

type HexUint64

type HexUint64 uint64

HexUint64 marshals as a "0x..."-prefixed JSON string: virtual addresses routinely exceed JSON's exact float53 integer range.

func (HexUint64) MarshalJSON

func (h HexUint64) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*HexUint64) UnmarshalJSON

func (h *HexUint64) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type Meta

type Meta struct {
	FormatVersion int    `json:"format_version"`
	CreatedAt     string `json:"created_at"` // RFC 3339, UTC
	Producer      string `json:"producer"`

	GoVersion string `json:"go_version"`
	GOARCH    string `json:"goarch"`
	PtrSize   int    `json:"ptr_size"`
	BigEndian bool   `json:"big_endian"`

	Rodata   RodataMeta `json:"rodata"`
	Warnings []string   `json:"warnings"`
}

Meta is the meta.json member. The go_version/goarch/ptr_size/ big_endian fields are convenience copies for humans inspecting a bundle; the heap dump's own Params record remains the authoritative source for runtime layout lookup during analysis.

type RodataMeta

type RodataMeta struct {
	// Status is one of the Rodata* constants.
	Status string `json:"status"`
	// Reason is human-readable context when Status is not "ok".
	Reason string `json:"reason,omitempty"`
	// Segments is the number of rodata/NNNNN.bin members.
	Segments int `json:"segments"`
	// TotalBytes is the sum of segment sizes.
	TotalBytes uint64 `json:"total_bytes"`
}

RodataMeta describes the read-only segment snapshot carried by the bundle.

type Segment

type Segment struct {
	Addr  uint64
	Size  uint64
	Perms string
	Path  string
	R     io.Reader
}

Segment is one read-only memory segment to embed in a bundle. R must yield exactly Size bytes.

type SegmentInfo

type SegmentInfo struct {
	// Member is the tar member holding the segment bytes.
	Member string `json:"member"`
	// Addr is the runtime virtual address of the first byte.
	Addr HexUint64 `json:"addr"`
	// Size is the segment length in bytes (always < 2^53, safe as a
	// plain JSON number).
	Size uint64 `json:"size"`
	// Perms is the mapping permission string, e.g. "r--" or "r-x".
	Perms string `json:"perms"`
	// Path is the backing file of the mapping, when known.
	Path string `json:"path,omitempty"`
}

SegmentInfo is one entry of the rodata/segments.json member, index-aligned with the rodata/NNNNN.bin members.

type SegmentsReader

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

SegmentsReader implements addrspace.Reader over the read-only segments saved in a bundle, keyed by their original runtime virtual addresses. It mirrors the ProcessReader contract: a read must lie entirely within a single segment; size==0 succeeds; addr==0 and overflowing ranges fail.

func NewSegmentsReader

func NewSegmentsReader(infos []SegmentInfo, data [][]byte) (*SegmentsReader, error)

NewSegmentsReader builds a SegmentsReader. Each data slice i covers [infos[i].Addr, infos[i].Addr+len(data[i])); infos and data must be index-aligned with len(data[i]) == infos[i].Size.

func (*SegmentsReader) Name

func (r *SegmentsReader) Name() string

Name implements addrspace.NamedReader.

func (*SegmentsReader) ReadAtAddr

func (r *SegmentsReader) ReadAtAddr(addr uint64, size uint64) ([]byte, bool)

ReadAtAddr implements addrspace.Reader.

type WriteInput

type WriteInput struct {
	Meta         Meta
	Segments     []Segment
	HeapDump     io.Reader
	HeapDumpSize int64
}

WriteInput is the content of one bundle. The writer fills Meta.FormatVersion and the rodata segment/byte counts; everything else (including Rodata.Status) is the caller's responsibility.

Jump to

Keyboard shortcuts

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