sqltrace

package
v0.1.41 Latest Latest
Warning

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

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

Documentation

Overview

Package sqltrace owns the server-side state for live SQL Server Extended Events traces that the web UI tails via polling. One Registry is created per oipa-cli serve process and shared across browser tabs — matching the shared-observability model used by internal/arthas.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActiveTrace

type ActiveTrace struct {
	ID          string                `json:"id"`
	SessionName string                `json:"sessionName"`
	Database    string                `json:"database"`
	StartedAt   time.Time             `json:"startedAt"`
	StopAt      time.Time             `json:"stopAt,omitzero"`
	StoppedAt   time.Time             `json:"stoppedAt,omitzero"`
	Options     xetrace.CreateOptions `json:"options"`
	Error       string                `json:"error,omitempty"`
	// contains filtered or unexported fields
}

ActiveTrace is the server-side record of one live or recently-stopped XE session. The mu-guarded fields are read by HTTP handlers polling for new events while the drain goroutine writes into them.

func (*ActiveTrace) Err

func (t *ActiveTrace) Err() error

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

func (*ActiveTrace) EventsSince

func (t *ActiveTrace) EventsSince(sinceKey string) ([]xetrace.Event, error)

EventsSince returns every event whose Key is newer than sinceKey (i.e. everything after the first match). An empty sinceKey returns the full buffer. A sinceKey that is not found returns the full buffer too, so the caller re-syncs rather than silently missing events.

A store failure is returned, never swallowed: an empty slice would render as "this trace captured no events", which is indistinguishable from a real empty capture.

func (*ActiveTrace) Result

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

Result renders the final TraceResult for post-run display in the UI (via CommandOutput + application/clicky+json). Safe to call while running.

func (*ActiveTrace) Running

func (t *ActiveTrace) Running() bool

Running reports whether the drain goroutine is still polling.

func (*ActiveTrace) Status

func (t *ActiveTrace) Status() (time.Time, string)

Status is the trace's outcome: when it stopped, and why it failed if it did. Both are read under the lock the drain writes them with, so a caller cannot see a half-written stop.

type EventLog

type EventLog interface {
	// Append stores one poll's events under an increasing sequence number.
	Append(traceID string, seq int, events []xetrace.Event) error

	// All returns every event captured for a trace, in delivery order.
	All(traceID string) ([]xetrace.Event, error)

	// Since returns the events after the one whose Key is sinceKey. An empty
	// cursor returns everything, and a cursor the log no longer holds returns
	// everything rather than nothing — a re-send is visible to a caller, a
	// silent hole is not.
	Since(traceID, sinceKey string) ([]xetrace.Event, error)

	// Forget removes a trace's events.
	Forget(traceID string)

	// Flush settles buffered writes, so a reader sees everything recorded.
	Flush() error
}

EventLog is where a Registry records what it captures, and where it reads those events back. It is an interface because a capture outlives neither the process nor the request that started it: the events have to go somewhere the host chooses, and this package should not choose for it.

type Registry

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

Registry holds every active and recently-stopped trace for one CLI process. Safe for concurrent use by HTTP handlers.

func NewRegistry

func NewRegistry(dbFor func(context.Context) (*sql.DB, func(), error), events EventLog) *Registry

NewRegistry builds a Registry wired to the supplied DB provider and event log. dbFor is called once per Start, and its release function runs after the trace's final drain and session drop.

Captured events live in the log rather than in this process, so a Registry built without one can only fail: Start rejects it rather than pretending to capture. Constructing without one is still allowed, so a caller can surface the registry's capabilities and fail at Start rather than at construction.

func (*Registry) Delete

func (r *Registry) Delete(id string) (bool, error)

Delete removes a trace after stopping it if still running. Returns false if unknown.

func (*Registry) GC

func (r *Registry) GC()

GC evicts traces whose StoppedAt is older than traceTTL. Call periodically; a sweep on every List call is cheap enough for single-process use.

func (*Registry) Get

func (r *Registry) Get(id string) (*ActiveTrace, bool)

Get returns a trace by ID.

func (*Registry) List

func (r *Registry) List() []*ActiveTrace

List returns a snapshot sorted newest-first.

func (*Registry) Start

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

Start creates an XE session and kicks off the drain goroutine. The returned *ActiveTrace is registered before this function returns so subsequent List/Get calls are consistent.

func (*Registry) Stop

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

Stop cancels a running trace. Idempotent: stopping an already-stopped trace is a no-op.

func (*Registry) StopAll

func (r *Registry) StopAll()

StopAll tears down every active trace. Intended for server shutdown.

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 client can pass to Start.

Jump to

Keyboard shortcuts

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