@@ -24,11 +24,19 @@ import (
2424 "strings"
2525 "time"
2626
27- "github.com/dustin/go-humanize"
27+ humanize "github.com/dustin/go-humanize"
2828 "github.com/rapidloop/pgmetrics"
2929)
3030
3131func writeHumanTo (fd io.Writer , o options , result * pgmetrics.Model ) {
32+ if result .PgBouncer != nil {
33+ pgbouncerWriteHumanTo (fd , o , result )
34+ } else {
35+ postgresWriteHumanTo (fd , o , result )
36+ }
37+ }
38+
39+ func postgresWriteHumanTo (fd io.Writer , o options , result * pgmetrics.Model ) {
3240 version := getVersion (result )
3341 sincePrior , _ := lsnDiff (result .RedoLSN , result .PriorLSN )
3442 sinceRedo , _ := lsnDiff (result .CheckpointLSN , result .RedoLSN )
@@ -1270,6 +1278,108 @@ System Information:
12701278 tw .write (fd , " " )
12711279}
12721280
1281+ //------------------------------------------------------------------------------
1282+ // pgbouncer
1283+
1284+ func pgbouncerWriteHumanTo (fd io.Writer , o options , result * pgmetrics.Model ) {
1285+ var tw tableWriter
1286+ fmt .Fprintf (fd , `
1287+ pgmetrics run at: %s
1288+ ` ,
1289+ fmtTimeAndSince (result .Metadata .At ),
1290+ )
1291+
1292+ // databases
1293+ fmt .Fprintf (fd , `
1294+ PgBouncer Databases:
1295+ ` )
1296+ tw .clear ()
1297+ tw .add ("Database" , "Maps To" , "Paused?" , "Disabled?" , "Clients" , "Xacts*" , "Queries*" , "Client Wait*" )
1298+ var dbs []string
1299+ for _ , db := range result .PgBouncer .Databases {
1300+ dbs = append (dbs , db .Database )
1301+ }
1302+ sort .Strings (dbs )
1303+ for _ , name := range dbs {
1304+ cols := []interface {}{name }
1305+ for _ , db := range result .PgBouncer .Databases {
1306+ if db .Database == name {
1307+ if name == "pgbouncer" {
1308+ cols = append (cols , "(internal)" )
1309+ } else {
1310+ host := db .Host
1311+ if strings .Index (host , ":" ) >= 0 {
1312+ host = "[" + host + "]"
1313+ }
1314+ user := db .User
1315+ if len (user ) > 0 {
1316+ user += "@"
1317+ }
1318+ cols = append (cols , fmt .Sprintf ("%s%s:%d/%s" , user , host , db .Port , db .SourceDatabase ))
1319+ }
1320+ cols = append (cols , fmtYesNo (db .Paused ), fmtYesNo (db .Disabled ))
1321+ if db .MaxConn != 0 {
1322+ cols = append (cols , fmt .Sprintf ("%d of %d" , db .CurrConn , db .MaxConn ))
1323+ } else {
1324+ cols = append (cols , db .CurrConn )
1325+ }
1326+ break
1327+ }
1328+ }
1329+ found := false
1330+ for _ , s := range result .PgBouncer .Stats {
1331+ if s .Database == name {
1332+ cols = append (cols ,
1333+ s .TotalXactCount ,
1334+ s .TotalQueryCount ,
1335+ time .Duration (s .TotalWaitTime * 1e9 ).Truncate (time .Millisecond ))
1336+ found = true
1337+ break
1338+ }
1339+ }
1340+ if ! found {
1341+ cols = append (cols , "0" , "0" , "0s" )
1342+ }
1343+ tw .add (cols ... )
1344+ }
1345+ w := tw .write (fd , " " )
1346+ msg := "* = cumulative values since start of PgBouncer"
1347+ fmt .Fprintf (fd , `%*s
1348+ ` ,
1349+ w , msg )
1350+
1351+ // pools
1352+ fmt .Fprintf (fd , `
1353+ PgBouncer Pools:
1354+ ` )
1355+ tw .clear ()
1356+ tw .add ("User" , "Database" , "Mode" , "Client Conns" , "Server Conns" , "Max Wait" )
1357+ for _ , p := range result .PgBouncer .Pools {
1358+ tw .add (
1359+ p .UserName ,
1360+ p .Database ,
1361+ p .Mode ,
1362+ fmt .Sprintf ("%d actv, %d wtng" , p .ClActive , p .ClWaiting ),
1363+ fmt .Sprintf ("%d actv, %d idle, %d othr" , p .SvActive , p .SvIdle , p .SvUsed + p .SvTested ),
1364+ time .Duration (p .MaxWait * 1e9 ).Truncate (time .Millisecond ))
1365+ }
1366+ tw .write (fd , " " )
1367+
1368+ // client connections
1369+ r := result .PgBouncer
1370+ fmt .Fprintf (fd , `
1371+ Current Connections:
1372+ Clients: %d active, %d waiting, %d idle, %d used
1373+ Servers: %d active, %d idle, %d used
1374+ Client Wait Times: max %v, avg %v
1375+
1376+ ` ,
1377+ r .CCActive , r .CCWaiting , r .CCIdle , r .CCUsed ,
1378+ r .SCActive , r .SCIdle , r .SCUsed ,
1379+ time .Duration (r .CCMaxWait * 1e9 ).Truncate (time .Millisecond ),
1380+ time .Duration (r .CCAvgWait * 1e9 ).Truncate (time .Millisecond ))
1381+ }
1382+
12731383//------------------------------------------------------------------------------
12741384
12751385func fmtTime (at int64 ) string {
@@ -1494,7 +1604,7 @@ func (t *tableWriter) cols() int {
14941604 return n
14951605}
14961606
1497- func (t * tableWriter ) write (fd io.Writer , pfx string ) {
1607+ func (t * tableWriter ) write (fd io.Writer , pfx string ) ( tw int ) {
14981608 if len (t .data ) == 0 {
14991609 return
15001610 }
@@ -1512,6 +1622,11 @@ func (t *tableWriter) write(fd io.Writer, pfx string) {
15121622 }
15131623 }
15141624 }
1625+ // calculate total width
1626+ tw = len (pfx ) + 1 // "prefix", "|"
1627+ for _ , w := range widths {
1628+ tw += 1 + w + 1 + 1 // blank, "value", blank, "|"
1629+ }
15151630 // print line
15161631 line := func () {
15171632 fmt .Fprintf (fd , "%s+" , pfx )
@@ -1533,4 +1648,5 @@ func (t *tableWriter) write(fd io.Writer, pfx string) {
15331648 fmt .Fprintln (fd )
15341649 }
15351650 line ()
1651+ return
15361652}
0 commit comments