Documentation
¶
Overview ¶
Package goldfish provides query sampling and comparison functionality for the querytee and Goldfish UI. It enables A/B testing between two query backends (cells) by sampling queries, comparing their responses (including performance metrics and content hashes), and persisting results for analysis. This package provides the data structures and SQL queries to persist and retrieve the results of this analysis.
Index ¶
- type APIResponse
- type ComparisonResult
- type ComparisonStatus
- type MySQLStorage
- func (s *MySQLStorage) Close() error
- func (s *MySQLStorage) GetQueryByCorrelationID(ctx context.Context, correlationID string) (*QuerySample, error)
- func (s *MySQLStorage) GetSampledQueries(ctx context.Context, page, pageSize int, filter QueryFilter) (*APIResponse, error)
- func (s *MySQLStorage) GetStatistics(ctx context.Context, filter StatsFilter) (*Statistics, error)
- func (s *MySQLStorage) StoreComparisonResult(ctx context.Context, result *ComparisonResult) error
- func (s *MySQLStorage) StoreQuerySample(ctx context.Context, sample *QuerySample, comparison *ComparisonResult) error
- type NoopStorage
- func (n *NoopStorage) Close() error
- func (n *NoopStorage) GetQueryByCorrelationID(_ context.Context, _ string) (*QuerySample, error)
- func (n *NoopStorage) GetSampledQueries(_ context.Context, _, _ int, _ QueryFilter) (*APIResponse, error)
- func (n *NoopStorage) GetStatistics(_ context.Context, _ StatsFilter) (*Statistics, error)
- func (n *NoopStorage) StoreComparisonResult(_ context.Context, _ *ComparisonResult) error
- func (n *NoopStorage) StoreQuerySample(_ context.Context, _ *QuerySample, _ *ComparisonResult) error
- type PerformanceMetrics
- type QueryFilter
- type QuerySample
- type QueryStats
- type Statistics
- type StatsFilter
- type Storage
- type StorageConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIResponse ¶
type APIResponse struct {
Queries []QuerySample `json:"queries"`
HasMore bool `json:"hasMore"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
APIResponse represents the paginated API response for UI
type ComparisonResult ¶
type ComparisonResult struct {
CorrelationID string
ComparisonStatus ComparisonStatus
MatchWithinTolerance bool
MismatchCause string
DifferenceDetails map[string]any
PerformanceMetrics PerformanceMetrics
ComparedAt time.Time
}
ComparisonResult represents the outcome of comparing two responses
type ComparisonStatus ¶
type ComparisonStatus string
ComparisonStatus represents the outcome of a comparison
const ( ComparisonStatusMatch ComparisonStatus = "match" ComparisonStatusMismatch ComparisonStatus = "mismatch" ComparisonStatusError ComparisonStatus = "error" ComparisonStatusPartial ComparisonStatus = "partial" ComparisonStatusMatchWithinTolerance ComparisonStatus = "match_within_tolerance" )
func (ComparisonStatus) IsValid ¶ added in v3.7.0
func (cs ComparisonStatus) IsValid() bool
IsValid checks if the ComparisonStatus value is valid
type MySQLStorage ¶
type MySQLStorage struct {
// contains filtered or unexported fields
}
MySQLStorage provides MySQL storage implementation
func NewMySQLStorage ¶
func NewMySQLStorage(config StorageConfig, logger log.Logger) (*MySQLStorage, error)
NewMySQLStorage creates a new MySQL storage backend
func (*MySQLStorage) Close ¶
func (s *MySQLStorage) Close() error
Close closes the storage connection
func (*MySQLStorage) GetQueryByCorrelationID ¶ added in v3.7.0
func (s *MySQLStorage) GetQueryByCorrelationID(ctx context.Context, correlationID string) (*QuerySample, error)
GetQueryByCorrelationID retrieves a single query sample by correlation ID
func (*MySQLStorage) GetSampledQueries ¶
func (s *MySQLStorage) GetSampledQueries(ctx context.Context, page, pageSize int, filter QueryFilter) (*APIResponse, error)
GetSampledQueries retrieves sampled queries from the database with pagination and outcome filtering
func (*MySQLStorage) GetStatistics ¶ added in v3.7.0
func (s *MySQLStorage) GetStatistics(ctx context.Context, filter StatsFilter) (*Statistics, error)
GetStatistics retrieves aggregated statistics from the database
func (*MySQLStorage) StoreComparisonResult ¶
func (s *MySQLStorage) StoreComparisonResult(ctx context.Context, result *ComparisonResult) error
StoreComparisonResult stores the outcome of comparing two responses
func (*MySQLStorage) StoreQuerySample ¶
func (s *MySQLStorage) StoreQuerySample(ctx context.Context, sample *QuerySample, comparison *ComparisonResult) error
StoreQuerySample stores a sampled query with performance statistics
type NoopStorage ¶
type NoopStorage struct{}
NoopStorage is a no-op implementation of the Storage interface
func NewNoopStorage ¶
func NewNoopStorage() *NoopStorage
NewNoopStorage creates a new no-op storage backend
func (*NoopStorage) GetQueryByCorrelationID ¶ added in v3.7.0
func (n *NoopStorage) GetQueryByCorrelationID(_ context.Context, _ string) (*QuerySample, error)
GetQueryByCorrelationID returns an error as goldfish is disabled
func (*NoopStorage) GetSampledQueries ¶
func (n *NoopStorage) GetSampledQueries(_ context.Context, _, _ int, _ QueryFilter) (*APIResponse, error)
GetSampledQueries returns an error as goldfish is disabled
func (*NoopStorage) GetStatistics ¶ added in v3.7.0
func (n *NoopStorage) GetStatistics(_ context.Context, _ StatsFilter) (*Statistics, error)
GetStatistics returns an error as goldfish is disabled
func (*NoopStorage) StoreComparisonResult ¶
func (n *NoopStorage) StoreComparisonResult(_ context.Context, _ *ComparisonResult) error
StoreComparisonResult is a no-op
func (*NoopStorage) StoreQuerySample ¶
func (n *NoopStorage) StoreQuerySample(_ context.Context, _ *QuerySample, _ *ComparisonResult) error
StoreQuerySample is a no-op
type PerformanceMetrics ¶
type PerformanceMetrics struct {
CellAQueryTime time.Duration
CellBQueryTime time.Duration
QueryTimeRatio float64
CellABytesTotal int64
CellBBytesTotal int64
BytesRatio float64
}
PerformanceMetrics contains performance comparison data
type QueryFilter ¶
type QueryFilter struct {
Tenant string
User string
IsLogsDrilldown *bool // pointer to handle true/false/nil states
UsedNewEngine *bool // pointer to handle true/false/nil states
ComparisonStatus ComparisonStatus
From, To time.Time
}
QueryFilter contains filters for querying sampled queries
type QuerySample ¶
type QuerySample struct {
CorrelationID string `json:"correlationId"`
TenantID string `json:"tenantId"`
User string `json:"user"`
Issuer string `json:"issuer"`
IsLogsDrilldown bool `json:"isLogsDrilldown"`
Query string `json:"query"`
QueryType string `json:"queryType"`
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
Step time.Duration `json:"step"`
// Performance statistics instead of raw responses
CellAStats QueryStats `json:"cellAStats"`
CellBStats QueryStats `json:"cellBStats"`
// Response metadata without sensitive content
CellAResponseHash string `json:"cellAResponseHash"`
CellBResponseHash string `json:"cellBResponseHash"`
CellAResponseSize int64 `json:"cellAResponseSize"`
CellBResponseSize int64 `json:"cellBResponseSize"`
CellAStatusCode int `json:"cellAStatusCode"`
CellBStatusCode int `json:"cellBStatusCode"`
CellATraceID string `json:"cellATraceID"`
CellBTraceID string `json:"cellBTraceID"`
CellASpanID string `json:"cellASpanID"`
CellBSpanID string `json:"cellBSpanID"`
// Result storage metadata
CellAResultURI string `json:"cellAResultURI"`
CellBResultURI string `json:"cellBResultURI"`
CellAResultSize int64 `json:"cellAResultSize"`
CellBResultSize int64 `json:"cellBResultSize"`
CellAResultCompression string `json:"cellAResultCompression"`
CellBResultCompression string `json:"cellBResultCompression"`
// Query engine version tracking
CellAUsedNewEngine bool `json:"cellAUsedNewEngine"`
CellBUsedNewEngine bool `json:"cellBUsedNewEngine"`
// Comparison outcome
ComparisonStatus ComparisonStatus `json:"comparisonStatus"`
MatchWithinTolerance bool `json:"matchWithinTolerance"`
MismatchCause string `json:"mismatchCause,omitempty"` // Set when ComparisonStatus is mismatch
SampledAt time.Time `json:"sampledAt"`
}
QuerySample represents a sampled query with performance stats from both cells
type QueryStats ¶
type QueryStats struct {
ExecTimeMs int64 `json:"execTimeMs"` // Execution time in milliseconds
QueueTimeMs int64 `json:"queueTimeMs"` // Queue time in milliseconds
BytesProcessed int64 `json:"bytesProcessed"` // Total bytes processed
LinesProcessed int64 `json:"linesProcessed"` // Total lines processed
BytesPerSecond int64 `json:"bytesPerSecond"` // Bytes processed per second
LinesPerSecond int64 `json:"linesPerSecond"` // Lines processed per second
TotalEntriesReturned int64 `json:"totalEntriesReturned"` // Number of result entries
Splits int64 `json:"splits"` // Number of splits
Shards int64 `json:"shards"` // Number of shards
}
QueryStats contains extracted performance statistics
type Statistics ¶ added in v3.7.0
type Statistics struct {
QueriesExecuted int64 `json:"queriesExecuted"` // Count of queries executed with new engine
EngineCoverage float64 `json:"engineCoverage"` // Ratio of queries using new engine
MatchingQueries float64 `json:"matchingQueries"` // Ratio of queries with matching responses
PerformanceDifference float64 `json:"performanceDifference"` // Geometric mean of performance ratio
}
Statistics contains aggregated statistics across sampled queries
type StatsFilter ¶ added in v3.7.0
type StatsFilter struct {
From time.Time
To time.Time
UsesRecentData bool // When false, exclude queries that touch data within the last 3h
}
StatsFilter contains filters for statistics queries
type Storage ¶
type Storage interface {
// Write operations (used by querytee)
StoreQuerySample(ctx context.Context, sample *QuerySample, comparison *ComparisonResult) error
StoreComparisonResult(ctx context.Context, result *ComparisonResult) error
// Read operations (used by UI)
GetSampledQueries(ctx context.Context, page, pageSize int, filter QueryFilter) (*APIResponse, error)
GetQueryByCorrelationID(ctx context.Context, correlationID string) (*QuerySample, error)
GetStatistics(ctx context.Context, filter StatsFilter) (*Statistics, error)
// Lifecycle
Close() error
}
Storage defines the interface for storing and retrieving query samples and comparison results
type StorageConfig ¶
type StorageConfig struct {
Type string `yaml:"type"` // "cloudsql", "rds", "mysql", or empty string for no storage
// Direct MySQL connection
MySQLHost string `yaml:"mysql_host"`
MySQLPort int `yaml:"mysql_port"`
MySQLDatabase string `yaml:"mysql_database"`
MySQLUser string `yaml:"mysql_user"`
// CloudSQL specific (via proxy)
CloudSQLHost string `yaml:"cloudsql_host"`
CloudSQLPort int `yaml:"cloudsql_port"`
CloudSQLDatabase string `yaml:"cloudsql_database"`
CloudSQLUser string `yaml:"cloudsql_user"`
// RDS specific
RDSEndpoint string `yaml:"rds_endpoint"` // e.g., "mydb.123456789012.us-east-1.rds.amazonaws.com:3306"
RDSDatabase string `yaml:"rds_database"`
RDSUser string `yaml:"rds_user"`
// Common settings
MaxConnections int `yaml:"max_connections"`
MaxIdleTime int `yaml:"max_idle_time_seconds"`
}
StorageConfig defines storage backend configuration