sqltrace

package
v0.1.42 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package sqltrace runs live SQL Server Extended Events captures: it creates the XE session, drains its target, and commits every captured event as a row of a sql_xevent record stream, which is where every reader — a result profile, a follower, a step's checkpoint window — reads them back from.

Index

Constants

View Source
const RowKind = "sql_xevent"

RowKind is the record kind a capture's stream holds: one EventRow per captured event.

Variables

This section is empty.

Functions

func CreateXESession added in v0.1.42

func CreateXESession(ctx context.Context, db *sql.DB, opts xetrace.CreateOptions) (XESession, Opened, error)

CreateXESession is the production XEFactory: a session on db, over the ring buffer or — when opts.File is set — a .xel event_file target on the server, or the built-in system_health session when opts.Session names it.

func CurrentDatabase added in v0.1.42

func CurrentDatabase(ctx context.Context, db *sql.DB) (string, error)

CurrentDatabase is the production database resolver: DB_NAME() of one of db's connections.

Types

type ActiveTrace

type ActiveTrace struct {
	ID          string
	SessionName string
	// Statements created and started the XE session, as the factory ran them.
	Statements []string
	// Database is a readable label for the database patterns the capture's
	// session is predicated on (the context's database when none were asked for).
	Database  string
	StartedAt time.Time
	StopAt    time.Time
	StoppedAt time.Time
	Options   xetrace.CreateOptions
	Error     string
	// contains filtered or unexported fields
}

ActiveTrace is one live or finished XE capture. Its ID is the record stream its rows are committed to.

func (*ActiveTrace) Checkpoint added in v0.1.42

func (t *ActiveTrace) Checkpoint(ctx context.Context) (query.EventsRef, error)

Checkpoint blocks until every row captured so far has been committed and returns the stream's ref over them. See eventWriter.Checkpoint.

func (*ActiveTrace) Done added in v0.1.42

func (t *ActiveTrace) Done() <-chan struct{}

Done is closed once the capture has finished: rows committed, stream sealed, session dropped and lease released.

func (*ActiveTrace) Err

func (t *ActiveTrace) Err() error

Err returns the terminal capture, store or cleanup failure, if one occurred.

func (*ActiveTrace) EventsRef added in v0.1.42

func (t *ActiveTrace) EventsRef() query.EventsRef

EventsRef is the stream's ref as of its last commit, without waiting.

func (*ActiveTrace) Preview added in v0.1.42

func (t *ActiveTrace) Preview(from, to int64) []xetrace.Event

Preview returns the latest committed events whose seq is within from..to; a bound of 0 is open.

func (*ActiveTrace) Result

func (t *ActiveTrace) Result() xetrace.TraceResult

Result is the capture's metadata and whole-capture summary. Its rows are in the record stream; a caller attaches the ref and preview it reports.

func (*ActiveTrace) Running

func (t *ActiveTrace) Running() bool

Running reports whether the drain goroutine is still polling.

func (*ActiveTrace) Summary added in v0.1.42

func (t *ActiveTrace) Summary() xetrace.Summary

Summary is the IO/CPU/timing aggregate over every committed event.

type EventRow added in v0.1.42

type EventRow struct {
	Name          string    `json:"name" pretty:"label=Event" filter:"terms"`
	StatementType string    `json:"statementType" pretty:"label=Type" filter:"terms"`
	Timestamp     time.Time `json:"timestamp" pretty:"label=Time" sort:"timestamp"`
	DurationMs    float64   `json:"durationMs" pretty:"label=Duration,type=duration,unit=ms" sort:"durationMs"`
	CPUMs         float64   `json:"cpuMs" pretty:"label=CPU,type=duration,unit=ms" sort:"cpuMs"`
	LogicalReads  int64     `json:"logicalReads" pretty:"label=Logical reads" sort:"logicalReads"`
	PhysicalReads int64     `json:"physicalReads" pretty:"label=Physical reads" sort:"physicalReads"`
	Writes        int64     `json:"writes" sort:"writes"`
	RowCount      int64     `json:"rowCount" pretty:"label=Rows" sort:"rowCount"`
	Database      string    `json:"database" filter:"terms"`
	ClientApp     string    `json:"clientApp" pretty:"label=App" filter:"terms"`
	ClientHost    string    `json:"clientHost" pretty:"label=Host" filter:"terms"`
	Username      string    `json:"username" pretty:"label=User" filter:"terms"`
	SessionID     int       `json:"sessionId" pretty:"label=Session" filter:"exact"`

	SQL          string   `json:"sql" pretty:"label=SQL" filter:"text"`
	RawStatement string   `json:"rawStatement" pretty:"hide"`
	Tables       []string `json:"tables"`

	ErrorNumber       int              `json:"errorNumber" pretty:"label=Error"`
	ErrorMessage      string           `json:"errorMessage" pretty:"label=Error message" filter:"text"`
	ObjectName        string           `json:"objectName" pretty:"label=Object" filter:"terms"`
	ObjectType        string           `json:"objectType" pretty:"label=Object type" filter:"terms"`
	ParamsUnavailable bool             `json:"paramsUnavailable" pretty:"label=Params unavailable"`
	AdditionalFields  map[string]any   `json:"additionalFields,omitempty" pretty:"hide"`
	Deadlock          *deadlocks.Graph `json:"deadlock,omitempty" pretty:"hide"`

	ActivityID  string     `json:"activityId" pretty:"hide"`
	ActivitySeq int        `json:"activitySeq" pretty:"hide"`
	Children    []EventRow `json:"children" pretty:"hide"`
}

EventRow is one captured event as a capture stores it: its metrics in milliseconds, its identity and text, and, for a deadlock report, the decoded graph.

func FromEvent added in v0.1.42

func FromEvent(event xetrace.Event) EventRow

FromEvent is the row a capture stores for event, with its nested statements.

func (EventRow) Columns added in v0.1.42

func (EventRow) Columns() []api.ColumnDef

func (EventRow) Row added in v0.1.42

func (r EventRow) Row() map[string]any

type Opened added in v0.1.42

type Opened struct {
	Name       string
	Statements []string
	FinalDelay time.Duration
}

Opened is what an XEFactory reports about the session it created: its name and the statements that created and started it.

type RecordStore added in v0.1.42

type RecordStore interface {
	Append(ctx context.Context, stream, kind string, rows []recordstore.Row) (recordstore.AppendResult, error)
	Seal(ctx context.Context, stream string) error
	EventsRef(ctx context.Context, stream string, from, to int64) (query.EventsRef, error)
}

RecordStore is where a capture commits its rows. EventsRef describes a window of a stream the way the store holding it reports it, so a reader can replay the rows after the capturing process is gone.

type Registry

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

Registry starts and stops XE captures. One is built per capture start, over the record store the starting request's environment routes to.

func NewRegistry

func NewRegistry(opts RegistryOptions) (*Registry, error)

NewRegistry builds a Registry over opts, refusing a missing seam.

func (*Registry) Start

func (r *Registry) Start(ctx context.Context, opts StartOptions) (*ActiveTrace, error)

Start creates the XE session, opens its record stream and starts the drain. Every store call the capture makes runs under ctx's values with its cancellation detached, so the rows reach the environment ctx names even after the request that started the capture has ended.

func (*Registry) Stop

func (r *Registry) Stop(id string) (*ActiveTrace, error)

Stop cancels a trace and waits for its final drain. Idempotent.

func (*Registry) StopAll

func (r *Registry) StopAll()

StopAll stops every trace this registry started.

type RegistryOptions added in v0.1.42

type RegistryOptions struct {
	// DB leases the context's write pool for one capture; the release runs
	// after the capture's final drain and session drop.
	DB func(context.Context) (*sql.DB, func(), error)
	// Store is where captured rows are committed.
	Store RecordStore
	// NewSession creates the XE session (CreateXESession in production).
	NewSession XEFactory
	// CurrentDatabase names the context's database, which a capture scopes to
	// when it names none (CurrentDatabase in production).
	CurrentDatabase func(context.Context, *sql.DB) (string, error)
}

RegistryOptions are the seams a Registry needs. Every one is required.

type StartOptions

type StartOptions struct {
	xetrace.CreateOptions
	// Duration bounds the trace. Zero means run until Stop.
	Duration time.Duration
	// Poll is the ring-buffer poll interval. Zero defaults to 1s.
	Poll time.Duration
}

StartOptions collapses everything a caller can pass to Start. An XE session is server-wide: CreateOptions.Databases narrows it in SQL Server's own predicate, and an empty Databases scopes the capture to the context's database.

type XEFactory added in v0.1.42

type XEFactory func(ctx context.Context, db *sql.DB, opts xetrace.CreateOptions) (XESession, Opened, error)

XEFactory creates the XE session for a capture.

type XESession added in v0.1.42

type XESession interface {
	Poll(ctx context.Context) (xetrace.TargetSnapshot, error)
	Drop(ctx context.Context) error
}

XESession is the slice of *xetrace.Session a capture drives.

Jump to

Keyboard shortcuts

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