tracking

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package tracking provides performance tracking for database operations. This package implements query tracking, slow query detection, and structured logging for database operations across all supported database backends.

Index

Constants

View Source
const (
	// DefaultSlowQueryThreshold defines the default threshold for slow query detection
	DefaultSlowQueryThreshold = 200 * time.Millisecond
	// DefaultMaxQueryLength defines the default maximum query length for logging
	DefaultMaxQueryLength = 1000
)
View Source
const (
	// SELECT queries
	TestQuerySelectUsers       = "SELECT * FROM users"
	TestQuerySelectUsersParams = "SELECT * FROM users WHERE id = $1"
	TestQuerySelectOrders      = "SELECT * FROM orders"
	TestQuerySelectOne         = "SELECT 1"

	// INSERT queries
	TestQueryInsertUsers       = "INSERT INTO users VALUES (1)"
	TestQueryInsertUsersParams = "INSERT INTO users (name) VALUES ($1)"

	// UPDATE queries
	TestQueryUpdateUsers = "UPDATE users SET name = 'test'"

	// DELETE queries
	TestQueryDeleteUsers = "DELETE FROM users WHERE id = 1"
)

Shared test query constants for use across all test files in the tracking package. These constants eliminate duplication and provide a single source of truth for test SQL queries.

Usage: Import these constants in *_test.go files instead of defining local duplicates.

Variables

This section is empty.

Functions

func BuildMongoDBNamespace added in v0.12.0

func BuildMongoDBNamespace(database string) string

BuildMongoDBNamespace builds the db.namespace attribute for MongoDB. BuildMongoDBNamespace builds the db.namespace value for MongoDB according to OpenTelemetry conventions by returning the provided database name. If database is empty, an empty string is returned.

func BuildOracleNamespace added in v0.12.0

func BuildOracleNamespace(serviceName, sid, database string) string

BuildOracleNamespace builds the db.namespace attribute for Oracle. Per OTel spec, format is "{service_name}|{sid}|{database}". Returns empty string only when all inputs are empty. When any value is provided, returns the full format with empty placeholders for missing values. Examples: "PRODDB||", "|ORCL|", "||mydb", "PRODDB|ORCL|mydb"

func BuildPostgreSQLNamespace added in v0.12.0

func BuildPostgreSQLNamespace(database, schema string) string

BuildPostgreSQLNamespace builds the db.namespace attribute for PostgreSQL. Per OTel spec, this combines database and schema name as "{database}.{schema}". Returns empty string when schema is unknown (don't assume defaults like "public"). Only returns "{database}.{schema}" when both database and schema are provided.

func NewConnection

func NewConnection(conn types.Interface, log logger.Logger, cfg *config.DatabaseConfig) types.Interface

NewConnection returns a database.Interface that wraps conn and records query/operation metrics and logs. The wrapper delegates all calls to the provided conn, uses conn.DatabaseType() NewConnection returns a types.Interface that wraps conn and records per-operation performance metrics, slow queries, and errors using the provided logger.

The wrapper uses conn.DatabaseType() as the vendor identifier and derives per-connection tracking settings from cfg via NewSettings.

func NewStatement

func NewStatement(stmt types.Statement, log logger.Logger, vendor, query string, settings Settings) types.Statement

NewStatement creates a Statement wrapper that tracks performance for prepared statements. NewStatement wraps the provided statement with a tracking implementation that records execution metrics for Query, QueryRow, and Exec.

The returned types.Statement uses the supplied logger, vendor identifier, optional query string, and settings to control tracking behavior.

func NewTransaction

func NewTransaction(tx types.Tx, log logger.Logger, vendor string, settings Settings) types.Tx

NewTransaction creates a Transaction wrapper that tracks performance for database transactions. NewTransaction creates a Transaction wrapper around the provided tx that records execution metrics for all transaction operations. The wrapper delegates calls to the given tx while capturing timing and error information, stores the provided logger, vendor, and settings, and initializes an internal Context used for tracking.

func RegisterConnectionPoolMetrics added in v0.12.0

func RegisterConnectionPoolMetrics(conn interface {
	Stats() (map[string]any, error)
}, vendor, serverAddress string, serverPort int, namespace string) func()

RegisterConnectionPoolMetrics registers ObservableGauges for connection pool metrics following OpenTelemetry semantic conventions v1.32.0.

This function should be called once per database connection during initialization.

Metrics registered per OTel spec: - db.client.connection.count{state="used"}: Active connections in use - db.client.connection.count{state="idle"}: Idle connections in pool - db.client.connection.idle.max: Maximum configured idle connections - db.client.connection.max: Maximum configured connections

Server Metadata Attributes: All metrics include server.address, server.port, and db.namespace (when available) in addition to db.system.name for full OTel compliance and correlation with operation metrics.

The gauges are updated automatically when metrics are collected (typically every 30s). Returns a cleanup function that can be called to unregister the metrics (optional).

This function uses graceful degradation - if any gauge fails to register, it continues with others and provides partial metrics coverage.

func SanitizeArgs

func SanitizeArgs(args []any, maxLen int) []any

SanitizeArgs returns a sanitized copy of the input argument slice suitable for logging.

For string values the returned element is truncated to at most maxLen runes. For []byte values the returned element is the placeholder "<bytes len=N>" where N is the byte length. For all other values the element is formatted with "%v" and then truncated to at most maxLen runes. The returned slice preserves the input order and length. If args is empty, nil is returned.

func TrackDBOperation

func TrackDBOperation(ctx context.Context, tc *Context, query string, args []any, start time.Time, rowsAffected int64, err error)

TrackDBOperation logs database operation performance metrics and errors. It provides centralized tracking for all database operations including queries, statements, and transactions. The function handles slow query detection, TrackDBOperation records metrics and emits a log event for a completed database operation.

TrackDBOperation is a no-op if tc or its Logger is nil. It records the operation's duration to request-scoped metrics, clamps the query string to the configured maximum length, and — when enabled — includes a sanitized form of parameters suitable for logging. If err is non-nil the error is logged (with sql.ErrNoRows logged at debug level); if there is no error and the duration exceeds the configured slow-query threshold a warning is emitted, otherwise a debug message is emitted.

The rowsAffected parameter represents the number of rows affected by write operations (INSERT, UPDATE, DELETE). For read operations (SELECT), pass 0.

func TruncateString

func TruncateString(value string, maxLen int) string

TruncateString returns value truncated to at most maxLen characters. If maxLen <= 0 or value is already shorter than or equal to maxLen, the original string is returned. When maxLen <= 3 the function returns the first maxLen characters (no ellipsis); otherwise it returns the first TruncateString truncates value to at most maxLen runes, adding "..." when space allows to indicate truncation.

If maxLen <= 0 the original value is returned unchanged. If the string's rune count is less than or equal to maxLen the original value is returned. When maxLen <= 3 the function returns the first maxLen runes without an ellipsis. For maxLen > 3 the result contains the first (maxLen-3) runes followed by "...". Multi-byte characters are handled safely by operating on runes.

Types

type BasicStatement

type BasicStatement struct {
	*sql.Stmt
}

BasicStatement wraps sql.Stmt to implement types.Statement interface. It provides a simple adapter between sql.Stmt and the types.Statement interface without any performance tracking (tracking is handled at higher levels).

func (*BasicStatement) Close

func (s *BasicStatement) Close() error

Close closes the prepared statement

func (*BasicStatement) Exec

func (s *BasicStatement) Exec(ctx context.Context, args ...any) (sql.Result, error)

Exec executes the prepared statement without returning rows

func (*BasicStatement) Query

func (s *BasicStatement) Query(ctx context.Context, args ...any) (*sql.Rows, error)

Query executes the prepared statement as a query

func (*BasicStatement) QueryRow

func (s *BasicStatement) QueryRow(ctx context.Context, args ...any) types.Row

QueryRow executes the prepared statement as a single row query

type Connection

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

Connection wraps database.Interface to provide comprehensive performance tracking. It delegates all operations to the wrapped connection while intercepting calls to log performance metrics, detect slow queries, and track errors.

func (*Connection) Begin

func (tc *Connection) Begin(ctx context.Context) (types.Tx, error)

Begin starts a transaction with performance tracking

func (*Connection) BeginTx

func (tc *Connection) BeginTx(ctx context.Context, opts *sql.TxOptions) (types.Tx, error)

BeginTx starts a transaction with options and performance tracking

func (*Connection) Close

func (tc *Connection) Close() error

Close closes the database connection (no tracking needed)

func (*Connection) CreateMigrationTable

func (tc *Connection) CreateMigrationTable(ctx context.Context) error

CreateMigrationTable creates the migration table if it doesn't exist with tracking

func (*Connection) DatabaseType

func (tc *Connection) DatabaseType() string

DatabaseType returns the database type (no tracking needed)

func (*Connection) Exec

func (tc *Connection) Exec(ctx context.Context, query string, args ...any) (sql.Result, error)

Exec executes a query without returning rows with performance tracking

func (*Connection) Health

func (tc *Connection) Health(ctx context.Context) error

Health checks database connection health (no tracking needed)

func (*Connection) MigrationTable added in v0.19.0

func (tc *Connection) MigrationTable() string

MigrationTable returns the migration table name (no tracking needed)

func (*Connection) Prepare

func (tc *Connection) Prepare(ctx context.Context, query string) (types.Statement, error)

Prepare prepares a statement with performance tracking

func (*Connection) Query

func (tc *Connection) Query(ctx context.Context, query string, args ...any) (*sql.Rows, error)

Query executes a query with performance tracking

func (*Connection) QueryRow

func (tc *Connection) QueryRow(ctx context.Context, query string, args ...any) types.Row

func (*Connection) SetServerInfo added in v0.12.0

func (tc *Connection) SetServerInfo(address string, port int, namespace string)

SetServerInfo sets the server connection metadata for OTel attributes. This should be called after creating the Connection to populate server address, port, and namespace.

func (*Connection) Stats

func (tc *Connection) Stats() (map[string]any, error)

Stats returns database connection statistics (no tracking needed)

type Context

type Context struct {
	Logger   logger.Logger
	Vendor   string
	Settings Settings

	// Server connection metadata for OTel attributes
	ServerAddress string // server.address attribute (database host)
	ServerPort    int    // server.port attribute (database port)
	Namespace     string // db.namespace attribute (vendor-specific format)
}

Context groups tracking-related parameters to reduce function parameter count. This context is passed to tracking functions to provide consistent access to logger, database vendor information, tracking settings, and server connection metadata for OpenTelemetry semantic convention attributes.

type DB

type DB struct {
	*sql.DB
	// contains filtered or unexported fields
}

DB wraps sql.DB to provide request-scoped performance tracking. It intercepts all database operations and logs performance metrics, slow queries, and errors using structured logging.

func NewDB

func NewDB(db *sql.DB, log logger.Logger, vendor string, cfg *config.DatabaseConfig) *DB

NewDB creates a DB wrapper that tracks performance for the provided *sql.DB. It records query and execution metrics (durations, truncated queries, optional parameter logging). Uses log for emitting structured logs, vendor to identify the database type, and NewDB returns a DB wrapper around the provided *sql.DB that records per-request performance metrics, slow queries, and errors using the provided logger. The wrapper is configured for the given vendor and derives per-connection tracking settings from cfg when provided.

func (*DB) ExecContext

func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)

ExecContext executes a query without returning rows and tracks performance

func (*DB) PrepareContext

func (db *DB) PrepareContext(ctx context.Context, query string) (types.Statement, error)

PrepareContext prepares a statement with context and tracks performance

func (*DB) QueryContext

func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)

QueryContext executes a query with context and tracks performance

func (*DB) QueryRowContext

func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) types.Row

type Settings

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

Settings holds configuration for database query tracking and logging. These settings control how database operations are monitored and logged.

func NewSettings

func NewSettings(cfg *config.DatabaseConfig) Settings

NewSettings creates Settings populated from the provided database configuration. If cfg is nil or a numeric field is non-positive, sensible defaults are used: DefaultSlowQueryThreshold for slowQueryThreshold and DefaultMaxQueryLength for maxQueryLength. NewSettings creates a Settings configured from the provided DatabaseConfig.

It initializes defaults from DefaultSlowQueryThreshold, DefaultMaxQueryLength, and a default of false for logging query parameters. If cfg is nil the defaults are returned. When cfg is provided, cfg.Query.Slow.Threshold > 0 overrides the slow query threshold, cfg.Query.Log.MaxLength > 0 overrides the max query length, and cfg.Query.Log.Parameters is copied into the logQueryParameters flag.

func (Settings) LogQueryParameters

func (s Settings) LogQueryParameters() bool

LogQueryParameters returns whether query parameters should be logged

func (Settings) MaxQueryLength

func (s Settings) MaxQueryLength() int

MaxQueryLength returns the maximum query length for logging

func (Settings) SlowQueryThreshold

func (s Settings) SlowQueryThreshold() time.Duration

SlowQueryThreshold returns the threshold for slow query detection

type Statement

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

Statement wraps types.Statement to provide performance tracking for prepared statements. It intercepts all statement operations and logs performance metrics, slow queries, and errors using structured logging.

func (*Statement) Close

func (s *Statement) Close() error

Close closes the prepared statement

func (*Statement) Exec

func (s *Statement) Exec(ctx context.Context, args ...any) (sql.Result, error)

Exec executes the prepared statement without returning rows with tracking

func (*Statement) Query

func (s *Statement) Query(ctx context.Context, args ...any) (*sql.Rows, error)

Query executes the prepared statement as a query with tracking

func (*Statement) QueryRow

func (s *Statement) QueryRow(ctx context.Context, args ...any) types.Row

type Transaction

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

Transaction wraps types.Tx to provide performance tracking for database transactions. It intercepts all transaction operations and logs performance metrics, slow queries, and errors using structured logging.

func (*Transaction) Commit

func (tx *Transaction) Commit(ctx context.Context) error

Commit commits the transaction

func (*Transaction) Exec

func (tx *Transaction) Exec(ctx context.Context, query string, args ...any) (sql.Result, error)

Exec executes a query within a transaction without returning rows with performance tracking

func (*Transaction) Prepare

func (tx *Transaction) Prepare(ctx context.Context, query string) (types.Statement, error)

Prepare prepares a statement within a transaction with performance tracking

func (*Transaction) Query

func (tx *Transaction) Query(ctx context.Context, query string, args ...any) (*sql.Rows, error)

Query executes a query within a transaction with performance tracking

func (*Transaction) QueryRow

func (tx *Transaction) QueryRow(ctx context.Context, query string, args ...any) types.Row

func (*Transaction) Rollback

func (tx *Transaction) Rollback(ctx context.Context) error

Rollback rolls back the transaction

Jump to

Keyboard shortcuts

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