From 6a07bc5b0f81626d613bbceef2ca6696095c82d7 Mon Sep 17 00:00:00 2001 From: Trevor Judice <tjudice@gfx.io> Date: Mon, 3 Oct 2022 14:00:41 -0500 Subject: [PATCH] remove old stats --- README.md | 10 - lib/gat/admin/admin.go | 363 +---------------------------------- lib/gat/database/database.go | 10 +- lib/gat/interfaces.go | 7 +- lib/gat/stats.go | 128 ------------ 5 files changed, 6 insertions(+), 512 deletions(-) delete mode 100644 lib/gat/stats.go diff --git a/README.md b/README.md index 2bd10e1f..7b657b17 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ i'll lyk when its done | Load balancing of read queries | :white_check_mark: | :white_check_mark: | Using random between replicas. Primary is included when `primary_reads_enabled` is enabled (default). | | Sharding | :white_check_mark: | :white_check_mark: | Transactions are sharded using `SET SHARD TO` and `SET SHARDING KEY TO` syntax extensions; see examples below. | | Failover | :white_check_mark: | :white_check_mark: | Replicas are tested with a health check. If a health check fails, remaining replicas are attempted; see below for algorithm description and examples. | -| Statistics | :white_check_mark: | :white_check_mark: | Statistics available in the admin database (`pgcat` and `pgbouncer`) with `SHOW STATS`, `SHOW POOLS` and others. | | Live configuration reloading | :white_check_mark: | kind of | Reload supported settings with a `SIGHUP` to the process, e.g. `kill -s SIGHUP $(pgrep pgcat)` or `RELOAD` query issued to the admin database. | | Client authentication | :white_check_mark: :wrench: | same as them | MD5 password authentication is supported, SCRAM is on the roadmap; one user is used to connect to Postgres with both SCRAM and MD5 supported. | | Admin database | :white_check_mark: | :white_check_mark: | The admin database, similar to PgBouncer's, allows to query for statistics and reload the configuration. | @@ -123,7 +122,6 @@ docker compose up --exit-code-from main # This will also produce coverage report | Load balancing | :white_check_mark: | :white_check_mark: | We could test this by emitting statistics for each replica and compare them. | | Failover | :white_check_mark: | :white_check_mark: | Misconfigure a replica in `pgcat.toml` and watch it forward queries to spares. CI testing is using Toxiproxy. | | Sharding | :white_check_mark: | :white_check_mark: | See `tests/sharding` and `tests/ruby` for an Rails/ActiveRecord example. | -| Statistics | :white_check_mark: | :white_check_mark: | Query the admin database with `psql -h 127.0.0.1 -p 6432 -d pgbouncer -c 'SHOW STATS'`. | | Live config reloading | :white_check_mark: | :white_check_mark: | Run `kill -s SIGHUP $(pgrep pgcat)` and watch the config reload. | ## Usage @@ -264,14 +262,6 @@ SET SERVER ROLE TO 'auto'; -- let the query router figure out where the query sh SELECT * FROM users WHERE email = 'test@example.com'; -- shard setting lasts until set again; we are reading from the primary ``` -### Statistics reporting - -The stats are very similar to what Pgbouncer reports and the names are kept to be comparable. They are accessible by querying the admin database `pgcat`, and `pgbouncer` for compatibility. - -``` -psql -h 127.0.0.1 -p 6432 -d pgbouncer -c 'SHOW DATABASES' -``` - ### Live configuration reloading The config can be reloaded by sending a `kill -s SIGHUP` to the process or by querying `RELOAD` to the admin database. Not all settings are currently supported by live reload: diff --git a/lib/gat/admin/admin.go b/lib/gat/admin/admin.go index 8780ac73..79c34b57 100644 --- a/lib/gat/admin/admin.go +++ b/lib/gat/admin/admin.go @@ -3,8 +3,6 @@ package admin import ( "context" "errors" - "fmt" - "time" "gfx.cafe/gfx/pggat/lib/config" "gfx.cafe/gfx/pggat/lib/gat" @@ -87,18 +85,7 @@ func New(g gat.Gat) *Database { database: out, } out.r = cmux.NewMapMux[gat.Client, error]() - out.r.Register([]string{"show", "stats_totals"}, func(client gat.Client, _ []string) error { - return out.showStats(client, true, false) - }) - out.r.Register([]string{"show", "stats_averages"}, func(client gat.Client, _ []string) error { - return out.showStats(client, false, true) - }) - out.r.Register([]string{"show", "stats"}, func(client gat.Client, _ []string) error { - return out.showStats(client, true, true) - }) - out.r.Register([]string{"show", "totals"}, func(client gat.Client, _ []string) error { - return out.showTotals(client) - }) + out.r.Register([]string{"show", "servers"}, func(_ gat.Client, _ []string) error { return nil }) @@ -177,350 +164,6 @@ func New(g gat.Gat) *Database { return out } -func (p *Database) showStats(client gat.Client, totals, averages bool) error { - rowDesc := new(protocol.RowDescription) - rowDesc.Fields.Fields = []protocol.FieldsRowDescriptionFields{ - { - Name: "database", - DataType: DataType_String, - DataTypeSize: -1, - TypeModifier: -1, - }, - } - if totals { - rowDesc.Fields.Fields = append(rowDesc.Fields.Fields, - protocol.FieldsRowDescriptionFields{ - Name: "total_xact_count", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "total_query_count", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "total_received", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "total_sent", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "total_xact_time", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "total_query_time", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "total_wait_time", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }) - } - if averages { - rowDesc.Fields.Fields = append(rowDesc.Fields.Fields, - protocol.FieldsRowDescriptionFields{ - Name: "avg_xact_count", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "avg_query_count", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "avg_recv", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "avg_sent", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "avg_xact_time", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "avg_query_time", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - protocol.FieldsRowDescriptionFields{ - Name: "avg_wait_time", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }) - } - err := client.Send(rowDesc) - if err != nil { - return err - } - for name, pl := range p.gat.GetDatabases() { - stats := pl.GetStats() - if stats == nil { - continue - } - row := new(protocol.DataRow) - row.Fields.Columns = []protocol.FieldsDataRowColumns{ - { - []byte(name), - }, - } - if totals { - row.Fields.Columns = append(row.Fields.Columns, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalXactCount())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalQueryCount())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalReceived())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalSent())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalXactTime())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalQueryTime())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%d", stats.TotalWaitTime())), - }) - } - if averages { - row.Fields.Columns = append(row.Fields.Columns, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgXactCount())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgQueryCount())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgRecv())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgSent())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgXactTime())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgQueryTime())), - }, - protocol.FieldsDataRowColumns{ - []byte(fmt.Sprintf("%f", stats.AvgWaitTime())), - }) - } - err = client.Send(row) - if err != nil { - return err - } - } - return nil -} - -func (p *Database) showTotals(client gat.Client) error { - rowDesc := new(protocol.RowDescription) - rowDesc.Fields.Fields = []protocol.FieldsRowDescriptionFields{ - { - Name: "total_xact_count", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "total_query_count", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "total_received", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "total_sent", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "total_xact_time", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "total_query_time", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "total_wait_time", - DataType: DataType_Int64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_xact_count", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_query_count", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_recv", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_sent", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_xact_time", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_query_time", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - { - Name: "avg_wait_time", - DataType: DataType_Float64, - DataTypeSize: 8, - TypeModifier: -1, - }, - } - err := client.Send(rowDesc) - if err != nil { - return err - } - - var totalXactCount, totalQueryCount, totalWaitCount, totalReceived, totalSent, totalXactTime, totalQueryTime, totalWaitTime int64 - var alive time.Duration - - for _, pl := range p.gat.GetDatabases() { - stats := pl.GetStats() - if stats == nil { - continue - } - totalXactCount += stats.TotalXactCount() - totalQueryCount += stats.TotalQueryCount() - totalWaitCount += stats.TotalWaitCount() - totalReceived += stats.TotalReceived() - totalSent += stats.TotalSent() - totalXactTime += stats.TotalXactTime() - totalQueryTime += stats.TotalQueryTime() - totalWaitTime += stats.TotalWaitTime() - - active := stats.TimeActive() - if active > alive { - alive = active - } - } - - avgXactCount := float64(totalXactCount) / alive.Seconds() - avgQueryCount := float64(totalQueryCount) / alive.Seconds() - avgReceive := float64(totalReceived) / alive.Seconds() - avgSent := float64(totalSent) / alive.Seconds() - avgXactTime := float64(totalXactTime) / float64(totalXactCount) - avgQueryTime := float64(totalQueryTime) / float64(totalQueryCount) - avgWaitTime := float64(totalWaitTime) / float64(totalWaitCount) - - row := new(protocol.DataRow) - row.Fields.Columns = []protocol.FieldsDataRowColumns{ - { - []byte(fmt.Sprintf("%d", totalXactCount)), - }, - { - []byte(fmt.Sprintf("%d", totalQueryCount)), - }, - { - []byte(fmt.Sprintf("%d", totalReceived)), - }, - { - []byte(fmt.Sprintf("%d", totalSent)), - }, - { - []byte(fmt.Sprintf("%d", totalXactTime)), - }, - { - []byte(fmt.Sprintf("%d", totalQueryTime)), - }, - { - []byte(fmt.Sprintf("%d", totalWaitTime)), - }, - { - []byte(fmt.Sprintf("%f", avgXactCount)), - }, - { - []byte(fmt.Sprintf("%f", avgQueryCount)), - }, - { - []byte(fmt.Sprintf("%f", avgReceive)), - }, - { - []byte(fmt.Sprintf("%f", avgSent)), - }, - { - []byte(fmt.Sprintf("%f", avgXactTime)), - }, - { - []byte(fmt.Sprintf("%f", avgQueryTime)), - }, - { - []byte(fmt.Sprintf("%f", avgWaitTime)), - }, - } - - return client.Send(row) -} - func (p *Database) GetUser(name string) *config.User { u := getAdminUser(p.gat) if name != u.Name { @@ -551,10 +194,6 @@ func (p *Database) GetPools() []gat.Pool { } } -func (p *Database) GetStats() *gat.PoolStats { - return nil -} - func (p *Database) EnsureConfig(c *config.Pool) { // TODO } diff --git a/lib/gat/database/database.go b/lib/gat/database/database.go index a54060b6..51ecefee 100644 --- a/lib/gat/database/database.go +++ b/lib/gat/database/database.go @@ -1,10 +1,11 @@ package database import ( + "sync" + "gfx.cafe/gfx/pggat/lib/gat/database/query_router" "gfx.cafe/gfx/pggat/lib/gat/pool/session" "gfx.cafe/gfx/pggat/lib/gat/pool/transaction" - "sync" "gfx.cafe/gfx/pggat/lib/config" "gfx.cafe/gfx/pggat/lib/gat" @@ -16,8 +17,6 @@ type Database struct { connPools map[string]gat.Pool name string - stats *gat.PoolStats - router *query_router.QueryRouter dialer gat.Dialer @@ -28,7 +27,6 @@ type Database struct { func New(dialer gat.Dialer, name string, conf *config.Pool) *Database { pool := &Database{ connPools: make(map[string]gat.Pool), - stats: gat.NewPoolStats(), router: query_router.DefaultRouter(conf), name: name, @@ -102,8 +100,4 @@ func (p *Database) GetPools() []gat.Pool { return out } -func (p *Database) GetStats() *gat.PoolStats { - return p.stats -} - var _ gat.Database = (*Database)(nil) diff --git a/lib/gat/interfaces.go b/lib/gat/interfaces.go index 6c13c30c..0a02ebed 100644 --- a/lib/gat/interfaces.go +++ b/lib/gat/interfaces.go @@ -2,10 +2,11 @@ package gat import ( "context" - "gfx.cafe/gfx/pggat/lib/config" - "gfx.cafe/gfx/pggat/lib/gat/protocol" "net" "time" + + "gfx.cafe/gfx/pggat/lib/config" + "gfx.cafe/gfx/pggat/lib/gat/protocol" ) type ClientID struct { @@ -68,8 +69,6 @@ type Database interface { WithUser(name string) Pool GetPools() []Pool - GetStats() *PoolStats - EnsureConfig(c *config.Pool) } diff --git a/lib/gat/stats.go b/lib/gat/stats.go deleted file mode 100644 index ec56eb64..00000000 --- a/lib/gat/stats.go +++ /dev/null @@ -1,128 +0,0 @@ -package gat - -import ( - "sync/atomic" - "time" -) - -type PoolStats struct { - start time.Time - - xactCount atomic.Int64 - queryCount atomic.Int64 - waitCount atomic.Int64 - received atomic.Int64 - sent atomic.Int64 - xactTime atomic.Int64 - queryTime atomic.Int64 - waitTime atomic.Int64 -} - -func NewPoolStats() *PoolStats { - return &PoolStats{ - start: time.Now(), - } -} - -func (s *PoolStats) TimeActive() time.Duration { - return time.Now().Sub(s.start) -} - -func (s *PoolStats) TotalXactCount() int64 { - return s.xactCount.Load() -} - -func (s *PoolStats) TotalQueryCount() int64 { - return s.queryCount.Load() -} - -func (s *PoolStats) TotalWaitCount() int64 { - return s.waitCount.Load() -} - -func (s *PoolStats) TotalReceived() int64 { - return s.received.Load() -} - -func (s *PoolStats) AddTotalReceived(amount int64) { - s.received.Add(amount) -} - -func (s *PoolStats) TotalSent() int64 { - return s.sent.Load() -} - -func (s *PoolStats) AddTotalSent(amount int64) { - s.sent.Add(amount) -} - -func (s *PoolStats) TotalXactTime() int64 { - return s.xactTime.Load() -} - -func (s *PoolStats) AddXactTime(time int64) { - s.xactCount.Add(1) - s.xactTime.Add(time) -} - -func (s *PoolStats) TotalQueryTime() int64 { - return s.queryTime.Load() -} - -func (s *PoolStats) AddQueryTime(time int64) { - s.queryCount.Add(1) - s.queryTime.Add(time) -} - -func (s *PoolStats) TotalWaitTime() int64 { - return s.waitTime.Load() -} - -func (s *PoolStats) AddWaitTime(time int64) { - s.waitCount.Add(1) - s.waitTime.Add(time) -} - -func (s *PoolStats) AvgXactCount() float64 { - seconds := s.TimeActive().Seconds() - return float64(s.xactCount.Load()) / seconds -} - -func (s *PoolStats) AvgQueryCount() float64 { - seconds := s.TimeActive().Seconds() - return float64(s.queryCount.Load()) / seconds -} - -func (s *PoolStats) AvgRecv() float64 { - seconds := s.TimeActive().Seconds() - return float64(s.received.Load()) / seconds -} - -func (s *PoolStats) AvgSent() float64 { - seconds := s.TimeActive().Seconds() - return float64(s.sent.Load()) / seconds -} - -func (s *PoolStats) AvgXactTime() float64 { - xactCount := s.xactCount.Load() - if xactCount == 0 { - return 0 - } - return float64(s.xactTime.Load()) / float64(xactCount) -} - -func (s *PoolStats) AvgQueryTime() float64 { - queryCount := s.queryCount.Load() - if queryCount == 0 { - return 0 - } - return float64(s.queryTime.Load()) / float64(queryCount) -} - -func (s *PoolStats) AvgWaitTime() float64 { - waitCount := s.waitCount.Load() - if waitCount == 0 { - return 0 - } - return float64(s.waitTime.Load()) / float64(waitCount) -} -- GitLab