Help us shape the future of Go! Take the 2026 Go Developer Survey

nettrace

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 17 Imported by: 0

README

go-nettrace

Go


Reads .NET EventPipe NetTrace streams into resolved CPU-sample stacks and attaches to a running .NET process over its diagnostics IPC. Package nettrace, module github.com/Rethunk-Tech/go-nettrace.

Parse turns a NetTrace V4/V5 stream (what dotnet-trace and the runtime's diagnostics IPC write) into thread samples whose stack frames are named from the trace's own JIT, loader and rundown events, so no symbol files are needed. StartTracing starts such a stream from a running .NET process.

Quick start

go get github.com/Rethunk-Tech/go-nettrace

A worked example and the contracts: HUMANS.md.

Features

  • Frames resolve to method, declaring type and assembly by address.
  • Samples carry a 64-bit thread ID and whether the thread was in managed code.
  • Newer or unknown formats (NetTrace V6) are refused with ErrUnsupportedVersion, never guessed at.
  • Finds a process's diagnostics socket or named pipe, including a containerised process's TMPDIR on Linux.
  • Every call is bound to its context.Context, and Stop never outlives it.
  • Standard library only.

Documentation

Doc Audience
HUMANS.md Running and using the package
AGENTS.md Internals, invariants, and why
CONTRIBUTING.md Process — commits, tests, docs
SECURITY.md Vulnerability disclosure
CHANGELOG.md Release notes

License

MIT — see LICENSE. © 2026 Rethunk.Tech, LLC.

Documentation

Overview

Package nettrace reads .NET EventPipe NetTrace streams into resolved CPU-sample stacks and attaches to a running .NET process over its diagnostics IPC.

Index

Constants

View Source
const (
	ProviderSampleProfiler = "Microsoft-DotNETCore-SampleProfiler"
	ProviderRuntime        = "Microsoft-Windows-DotNETRuntime"

	KeywordLoader uint64 = 0x8  // module and assembly load events
	KeywordJit    uint64 = 0x10 // method load events
)

The providers whose events the reader understands, and the keywords that make the runtime emit the loader and JIT events frame resolution needs.

View Source
const DefaultBufferMB uint32 = 256

DefaultBufferMB is the runtime-side event buffer a zero Config.BufferMB selects.

Variables

View Source
var (
	// ErrNotNettrace means the stream does not start with the NetTrace magic.
	ErrNotNettrace = errors.New("nettrace: not a nettrace stream")
	// ErrUnsupportedVersion means the stream is a NetTrace this reader does not read: a V6 file, a Trace object
	// that requires a newer reader, or a stream that does not begin with a Trace object.
	ErrUnsupportedVersion = errors.New("nettrace: unsupported nettrace format version")
	// ErrNoEvents means the stream holds no blocks at all, so there is nothing to read.
	ErrNoEvents = errors.New("nettrace: stream has no event or stack blocks")
)
View Source
var ErrNoEndpoint = errors.New("nettrace: no diagnostics endpoint for the process")

ErrNoEndpoint means no diagnostics endpoint exists for the process: it is not a .NET process, has not created its endpoint yet, or has diagnostics disabled. It also matches os.ErrNotExist.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Providers defaults to the sample profiler plus the runtime's loader and JIT events, which is what Parse
	// needs to resolve stacks.
	Providers []Provider
	BufferMB  uint32 // zero selects DefaultBufferMB
	// NoRundown skips the rundown the runtime performs when the session stops. Rundown is on by default: without
	// it, every method JIT-compiled before the session started stays unresolved.
	NoRundown bool
}

Config describes a tracing session. A zero field selects its default.

type Frame

type Frame struct {
	IP       uint64
	Method   string // the method name
	Type     string // the declaring type's full name
	Assembly string // the fully qualified assembly name
}

Frame is a resolved instruction in a sampled stack. A frame whose address no method load event covers keeps its IP and has empty names.

type Method

type Method struct {
	StartAddress uint64
	Size         uint64
	Namespace    string
	Name         string
	ModuleID     uint64
	Assembly     string
}

Method is a method-load record that sampled instruction addresses resolve against.

type Provider

type Provider struct {
	Name     string
	Keywords uint64
	// Level is the verbosity; zero selects 5 (verbose), which the method-load events need.
	Level uint32
	// Arguments is the provider's filter data as "key=value;..." pairs; empty sends none.
	Arguments string
}

Provider is one event provider to enable in a session.

type RuntimeError

type RuntimeError struct {
	// HResult is the runtime's failure code, zero when the reply carried none.
	HResult uint32
}

RuntimeError is the runtime's error reply to a request, such as a refused session or a provider it rejects.

func (*RuntimeError) Error

func (e *RuntimeError) Error() string

type Sample

type Sample struct {
	Timestamp uint64 // nanoseconds on the trace clock
	ThreadID  uint64
	// Managed is true when the thread was running managed code, false when it was in native code.
	Managed bool
	// Frames is the stack, innermost first. Samples on one stack share this slice, so callers must not modify it.
	Frames []Frame
}

Sample is one thread sample.

type Session

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

Session is one running EventPipe session.

func StartTracing

func StartTracing(ctx context.Context, pid int, cfg Config, w io.Writer) (*Session, error)

StartTracing dials pid's diagnostics endpoint, sends CollectTracing2, and copies the nettrace stream into w until the runtime closes it. It returns an error wrapping ErrNoEndpoint while the process has no endpoint yet, so a caller may retry. A refused request is a *RuntimeError. Canceling ctx before the reply closes the connection and returns ctx.Err(). The stream is copied from a goroutine, so w must be safe to write while the caller does other work; it is not written after Stop returns.

func (*Session) Stop

func (s *Session) Stop(ctx context.Context) error

Stop sends StopTracing on a second connection, waits for the stream to end, and returns the stop and copy errors joined. It may be called again and by several goroutines: the stop runs once, and every call waits for it under its own ctx. Canceling ctx closes both connections, so Stop never outlives its context. Stop returns only after the copy goroutine has exited: nothing is written to the writer after it returns, so the caller may read or close it at once.

type Trace

type Trace struct {
	TimestampFrequency uint64 // the trace clock's ticks per second
	PointerSize        int
	Samples            []Sample // ordered by timestamp
	Methods            []Method
	Assemblies         map[uint64]string // assembly ID to fully qualified name
	Modules            map[uint64]uint64 // module ID to assembly ID
}

Trace is the samples and symbols of a nettrace stream.

func Parse

func Parse(r io.Reader) (*Trace, error)

Parse reads a NetTrace V4/V5 stream, the format the runtime streams over its diagnostics IPC and dotnet-trace writes. It reads the whole stream into memory: wrap an untrusted reader in io.LimitReader.

Jump to

Keyboard shortcuts

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