Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
137
plugins/inputs/pgbouncer/README.md
Normal file
137
plugins/inputs/pgbouncer/README.md
Normal file
|
@ -0,0 +1,137 @@
|
|||
# PgBouncer Input Plugin
|
||||
|
||||
The `pgbouncer` plugin provides metrics for your PgBouncer load balancer.
|
||||
|
||||
More information about the meaning of these metrics can be found in the
|
||||
[PgBouncer Documentation](https://pgbouncer.github.io/usage.html).
|
||||
|
||||
- PgBouncer minimum tested version: 1.5
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Read metrics from one or many pgbouncer servers
|
||||
[[inputs.pgbouncer]]
|
||||
## specify address via a url matching:
|
||||
## postgres://[pqgotest[:password]]@host:port[/dbname]\
|
||||
## ?sslmode=[disable|verify-ca|verify-full]
|
||||
## or a simple string:
|
||||
## host=localhost port=5432 user=pqgotest password=... sslmode=... dbname=app_production
|
||||
##
|
||||
## All connection parameters are optional.
|
||||
##
|
||||
address = "host=localhost user=pgbouncer sslmode=disable"
|
||||
|
||||
## Specify which "show" commands to gather metrics for.
|
||||
## Choose from: "stats", "pools", "lists", "databases"
|
||||
# show_commands = ["stats", "pools"]
|
||||
```
|
||||
|
||||
### `address`
|
||||
|
||||
Specify address via a postgresql connection string:
|
||||
|
||||
```text
|
||||
host=/run/postgresql port=6432 user=telegraf database=pgbouncer
|
||||
```
|
||||
|
||||
Or via an url matching:
|
||||
|
||||
```text
|
||||
postgres://[pqgotest[:password]]@host:port[/dbname]?sslmode=[disable|verify-ca|verify-full]
|
||||
```
|
||||
|
||||
All connection parameters are optional.
|
||||
|
||||
Without the dbname parameter, the driver will default to a database with the
|
||||
same name as the user. This dbname is just for instantiating a connection with
|
||||
the server and doesn't restrict the databases we are trying to grab metrics for.
|
||||
|
||||
## Metrics
|
||||
|
||||
- pgbouncer
|
||||
- tags:
|
||||
- db
|
||||
- server
|
||||
- fields:
|
||||
- avg_query_count
|
||||
- avg_query_time
|
||||
- avg_wait_time
|
||||
- avg_xact_count
|
||||
- avg_xact_time
|
||||
- total_query_count
|
||||
- total_query_time
|
||||
- total_received
|
||||
- total_sent
|
||||
- total_wait_time
|
||||
- total_xact_count
|
||||
- total_xact_time
|
||||
|
||||
- pgbouncer_pools
|
||||
- tags:
|
||||
- db
|
||||
- pool_mode
|
||||
- server
|
||||
- user
|
||||
- fields:
|
||||
- cl_active
|
||||
- cl_waiting
|
||||
- maxwait
|
||||
- maxwait_us
|
||||
- sv_active
|
||||
- sv_idle
|
||||
- sv_login
|
||||
- sv_tested
|
||||
- sv_used
|
||||
|
||||
- pgbouncer_lists
|
||||
- tags:
|
||||
- db
|
||||
- server
|
||||
- user
|
||||
- fields:
|
||||
- databases
|
||||
- users
|
||||
- pools
|
||||
- free_clients
|
||||
- used_clients
|
||||
- login_clients
|
||||
- free_servers
|
||||
- used_servers
|
||||
- dns_names
|
||||
- dns_zones
|
||||
- dns_queries
|
||||
|
||||
- pgbouncer_databases
|
||||
- tags:
|
||||
- db
|
||||
- pg_dbname
|
||||
- server
|
||||
- user
|
||||
- fields:
|
||||
- current_connections
|
||||
- pool_size
|
||||
- min_pool_size
|
||||
- reserve_pool
|
||||
- max_connections
|
||||
- paused
|
||||
- disabled
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
pgbouncer,db=pgbouncer,server=host\=debian-buster-postgres\ user\=dbn\ port\=6432\ dbname\=pgbouncer\ avg_query_count=0i,avg_query_time=0i,avg_wait_time=0i,avg_xact_count=0i,avg_xact_time=0i,total_query_count=26i,total_query_time=0i,total_received=0i,total_sent=0i,total_wait_time=0i,total_xact_count=26i,total_xact_time=0i 1581569936000000000
|
||||
pgbouncer_pools,db=pgbouncer,pool_mode=statement,server=host\=debian-buster-postgres\ user\=dbn\ port\=6432\ dbname\=pgbouncer\ ,user=pgbouncer cl_active=1i,cl_waiting=0i,maxwait=0i,maxwait_us=0i,sv_active=0i,sv_idle=0i,sv_login=0i,sv_tested=0i,sv_used=0i 1581569936000000000
|
||||
pgbouncer_lists,db=pgbouncer,server=host\=debian-buster-postgres\ user\=dbn\ port\=6432\ dbname\=pgbouncer\ ,user=pgbouncer databases=1i,dns_names=0i,dns_queries=0i,dns_zones=0i,free_clients=47i,free_servers=0i,login_clients=0i,pools=1i,used_clients=3i,used_servers=0i,users=4i 1581569936000000000
|
||||
pgbouncer_databases,db=pgbouncer,pg_dbname=pgbouncer,server=host\=debian-buster-postgres\ user\=dbn\ port\=6432\ dbname\=pgbouncer\ name=pgbouncer disabled=0i,pool_size=2i,current_connections=0i,min_pool_size=0i,reserve_pool=0i,max_connections=0i,paused=0i 1581569936000000000
|
||||
pgbouncer_databases,db=postgres,pg_dbname=postgres,server=host\=debian-buster-postgres\ user\=dbn\ port\=6432\ dbname\=pgbouncer\ name=postgres current_connections=0i,disabled=0i,pool_size=20i,min_pool_size=0i,reserve_pool=0i,paused=0i,max_connections=0i 1581569936000000000
|
||||
```
|
317
plugins/inputs/pgbouncer/pgbouncer.go
Normal file
317
plugins/inputs/pgbouncer/pgbouncer.go
Normal file
|
@ -0,0 +1,317 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package pgbouncer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/common/postgresql"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
var ignoredColumns = map[string]bool{"user": true, "database": true, "pool_mode": true,
|
||||
"avg_req": true, "avg_recv": true, "avg_sent": true, "avg_query": true,
|
||||
"force_user": true, "host": true, "port": true, "name": true,
|
||||
}
|
||||
|
||||
type PgBouncer struct {
|
||||
ShowCommands []string `toml:"show_commands"`
|
||||
postgresql.Config
|
||||
|
||||
service *postgresql.Service
|
||||
}
|
||||
|
||||
func (*PgBouncer) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (p *PgBouncer) Init() error {
|
||||
// Set defaults and check settings
|
||||
if len(p.ShowCommands) == 0 {
|
||||
p.ShowCommands = []string{"stats", "pools"}
|
||||
}
|
||||
for _, cmd := range p.ShowCommands {
|
||||
switch cmd {
|
||||
case "stats", "pools", "lists", "databases":
|
||||
default:
|
||||
return fmt.Errorf("invalid setting %q for 'show_command'", cmd)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a postgres service for the queries
|
||||
service, err := p.Config.CreateService()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.service = service
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PgBouncer) Start(_ telegraf.Accumulator) error {
|
||||
return p.service.Start()
|
||||
}
|
||||
|
||||
func (p *PgBouncer) Gather(acc telegraf.Accumulator) error {
|
||||
for _, cmd := range p.ShowCommands {
|
||||
switch cmd {
|
||||
case "stats":
|
||||
if err := p.showStats(acc); err != nil {
|
||||
return err
|
||||
}
|
||||
case "pools":
|
||||
if err := p.showPools(acc); err != nil {
|
||||
return err
|
||||
}
|
||||
case "lists":
|
||||
if err := p.showLists(acc); err != nil {
|
||||
return err
|
||||
}
|
||||
case "databases":
|
||||
if err := p.showDatabase(acc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PgBouncer) Stop() {
|
||||
p.service.Stop()
|
||||
}
|
||||
|
||||
func (p *PgBouncer) accRow(row *sql.Rows, columns []string) (map[string]string, map[string]*interface{}, error) {
|
||||
var dbname bytes.Buffer
|
||||
|
||||
// this is where we'll store the column name with its *interface{}
|
||||
columnMap := make(map[string]*interface{})
|
||||
for _, column := range columns {
|
||||
columnMap[column] = new(interface{})
|
||||
}
|
||||
|
||||
columnVars := make([]interface{}, 0, len(columnMap))
|
||||
// populate the array of interface{} with the pointers in the right order
|
||||
for i := 0; i < len(columnMap); i++ {
|
||||
columnVars = append(columnVars, columnMap[columns[i]])
|
||||
}
|
||||
|
||||
// deconstruct array of variables and send to Scan
|
||||
err := row.Scan(columnVars...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("couldn't copy the data: %w", err)
|
||||
}
|
||||
if columnMap["database"] != nil {
|
||||
// extract the database name from the column map
|
||||
name, ok := (*columnMap["database"]).(string)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("database not a string, but %T", *columnMap["database"])
|
||||
}
|
||||
dbname.WriteString(name)
|
||||
} else {
|
||||
dbname.WriteString("pgbouncer")
|
||||
}
|
||||
|
||||
// Return basic tags and the mapped columns
|
||||
return map[string]string{"server": p.service.SanitizedAddress, "db": dbname.String()}, columnMap, nil
|
||||
}
|
||||
|
||||
func (p *PgBouncer) showStats(acc telegraf.Accumulator) error {
|
||||
// STATS
|
||||
rows, err := p.service.DB.Query(`SHOW STATS`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("execution error 'show stats': %w", err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
// grab the column information from the result
|
||||
columns, err := rows.Columns()
|
||||
if err != nil {
|
||||
return fmt.Errorf("don't get column names 'show stats': %w", err)
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
tags, columnMap, err := p.accRow(rows, columns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
for col, val := range columnMap {
|
||||
_, ignore := ignoredColumns[col]
|
||||
if ignore {
|
||||
continue
|
||||
}
|
||||
|
||||
switch v := (*val).(type) {
|
||||
case int64:
|
||||
// Integer fields are returned in pgbouncer 1.5 through 1.9
|
||||
fields[col] = v
|
||||
case string:
|
||||
// Integer fields are returned in pgbouncer 1.12
|
||||
integer, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't convert metrics 'show stats': %w", err)
|
||||
}
|
||||
|
||||
fields[col] = integer
|
||||
}
|
||||
}
|
||||
acc.AddFields("pgbouncer", fields, tags)
|
||||
}
|
||||
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func (p *PgBouncer) showPools(acc telegraf.Accumulator) error {
|
||||
// POOLS
|
||||
poolRows, err := p.service.DB.Query(`SHOW POOLS`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("execution error 'show pools': %w", err)
|
||||
}
|
||||
|
||||
defer poolRows.Close()
|
||||
|
||||
// grab the column information from the result
|
||||
columns, err := poolRows.Columns()
|
||||
if err != nil {
|
||||
return fmt.Errorf("don't get column names 'show pools': %w", err)
|
||||
}
|
||||
|
||||
for poolRows.Next() {
|
||||
tags, columnMap, err := p.accRow(poolRows, columns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if user, ok := columnMap["user"]; ok {
|
||||
if s, ok := (*user).(string); ok && s != "" {
|
||||
tags["user"] = s
|
||||
}
|
||||
}
|
||||
|
||||
if poolMode, ok := columnMap["pool_mode"]; ok {
|
||||
if s, ok := (*poolMode).(string); ok && s != "" {
|
||||
tags["pool_mode"] = s
|
||||
}
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
for col, val := range columnMap {
|
||||
_, ignore := ignoredColumns[col]
|
||||
if !ignore {
|
||||
fields[col] = *val
|
||||
}
|
||||
}
|
||||
acc.AddFields("pgbouncer_pools", fields, tags)
|
||||
}
|
||||
|
||||
return poolRows.Err()
|
||||
}
|
||||
|
||||
func (p *PgBouncer) showLists(acc telegraf.Accumulator) error {
|
||||
// LISTS
|
||||
rows, err := p.service.DB.Query(`SHOW LISTS`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("execution error 'show lists': %w", err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
// grab the column information from the result
|
||||
columns, err := rows.Columns()
|
||||
if err != nil {
|
||||
return fmt.Errorf("don't get column names 'show lists': %w", err)
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
tags := make(map[string]string)
|
||||
for rows.Next() {
|
||||
tag, columnMap, err := p.accRow(rows, columns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name, ok := (*columnMap["list"]).(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("metric name(show lists) not a string, but %T", *columnMap["list"])
|
||||
}
|
||||
if name != "dns_pending" {
|
||||
value, ok := (*columnMap["items"]).(int64)
|
||||
if !ok {
|
||||
return fmt.Errorf("metric value(show lists) not a int64, but %T", *columnMap["items"])
|
||||
}
|
||||
fields[name] = value
|
||||
tags = tag
|
||||
}
|
||||
}
|
||||
acc.AddFields("pgbouncer_lists", fields, tags)
|
||||
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func (p *PgBouncer) showDatabase(acc telegraf.Accumulator) error {
|
||||
// DATABASES
|
||||
rows, err := p.service.DB.Query(`SHOW DATABASES`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("execution error 'show database': %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
// grab the column information from the result
|
||||
columns, err := rows.Columns()
|
||||
if err != nil {
|
||||
return fmt.Errorf("don't get column names 'show database': %w", err)
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
tags, columnMap, err := p.accRow(rows, columns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// SHOW DATABASES displays pgbouncer database name under name column,
|
||||
// while using database column to store Postgres database name.
|
||||
if database, ok := columnMap["database"]; ok {
|
||||
if s, ok := (*database).(string); ok && s != "" {
|
||||
tags["pg_dbname"] = s
|
||||
}
|
||||
}
|
||||
|
||||
// pass it under db tag to be compatible with the rest of the measurements
|
||||
if name, ok := columnMap["name"]; ok {
|
||||
if s, ok := (*name).(string); ok && s != "" {
|
||||
tags["db"] = s
|
||||
}
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
for col, val := range columnMap {
|
||||
_, ignore := ignoredColumns[col]
|
||||
if !ignore {
|
||||
fields[col] = *val
|
||||
}
|
||||
}
|
||||
acc.AddFields("pgbouncer_databases", fields, tags)
|
||||
}
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("pgbouncer", func() telegraf.Input {
|
||||
return &PgBouncer{
|
||||
Config: postgresql.Config{
|
||||
MaxIdle: 1,
|
||||
MaxOpen: 1,
|
||||
IsPgBouncer: true,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
215
plugins/inputs/pgbouncer/pgbouncer_test.go
Normal file
215
plugins/inputs/pgbouncer/pgbouncer_test.go
Normal file
|
@ -0,0 +1,215 @@
|
|||
package pgbouncer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/plugins/common/postgresql"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestPgBouncerGeneratesMetricsIntegration(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
postgresServicePort := "5432"
|
||||
pgBouncerServicePort := "6432"
|
||||
|
||||
backend := testutil.Container{
|
||||
Image: "postgres:alpine",
|
||||
ExposedPorts: []string{postgresServicePort},
|
||||
Env: map[string]string{
|
||||
"POSTGRES_HOST_AUTH_METHOD": "trust",
|
||||
},
|
||||
WaitingFor: wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
|
||||
}
|
||||
require.NoError(t, backend.Start(), "failed to start container")
|
||||
defer backend.Terminate()
|
||||
|
||||
container := testutil.Container{
|
||||
Image: "z9pascal/pgbouncer-container:1.23.1-latest",
|
||||
ExposedPorts: []string{pgBouncerServicePort},
|
||||
Env: map[string]string{
|
||||
"PG_ENV_POSTGRESQL_USER": "pgbouncer",
|
||||
"PG_ENV_POSTGRESQL_PASS": "pgbouncer",
|
||||
},
|
||||
WaitingFor: wait.ForAll(
|
||||
wait.ForListeningPort(nat.Port(pgBouncerServicePort)),
|
||||
wait.ForLog("LOG process up"),
|
||||
),
|
||||
}
|
||||
require.NoError(t, container.Start(), "failed to start container")
|
||||
defer container.Terminate()
|
||||
|
||||
addr := fmt.Sprintf(
|
||||
"host=%s user=pgbouncer password=pgbouncer dbname=pgbouncer port=%s sslmode=disable",
|
||||
container.Address,
|
||||
container.Ports[pgBouncerServicePort],
|
||||
)
|
||||
|
||||
p := &PgBouncer{
|
||||
Config: postgresql.Config{
|
||||
Address: config.NewSecret([]byte(addr)),
|
||||
IsPgBouncer: true,
|
||||
},
|
||||
}
|
||||
require.NoError(t, p.Init())
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, p.Start(&acc))
|
||||
defer p.Stop()
|
||||
require.NoError(t, p.Gather(&acc))
|
||||
|
||||
intMetricsPgBouncer := []string{
|
||||
"total_received",
|
||||
"total_sent",
|
||||
"total_query_time",
|
||||
"avg_query_count",
|
||||
"avg_query_time",
|
||||
"avg_wait_time",
|
||||
}
|
||||
|
||||
intMetricsPgBouncerPools := []string{
|
||||
"cl_active",
|
||||
"cl_waiting",
|
||||
"sv_active",
|
||||
"sv_idle",
|
||||
"sv_used",
|
||||
"sv_tested",
|
||||
"sv_login",
|
||||
"maxwait",
|
||||
}
|
||||
|
||||
metricsCounted := 0
|
||||
|
||||
for _, metric := range intMetricsPgBouncer {
|
||||
require.True(t, acc.HasInt64Field("pgbouncer", metric))
|
||||
metricsCounted++
|
||||
}
|
||||
|
||||
for _, metric := range intMetricsPgBouncerPools {
|
||||
require.True(t, acc.HasInt64Field("pgbouncer_pools", metric))
|
||||
metricsCounted++
|
||||
}
|
||||
|
||||
require.Positive(t, metricsCounted)
|
||||
require.Equal(t, len(intMetricsPgBouncer)+len(intMetricsPgBouncerPools), metricsCounted)
|
||||
}
|
||||
|
||||
func TestPgBouncerGeneratesMetricsIntegrationShowCommands(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
postgresServicePort := "5432"
|
||||
pgBouncerServicePort := "6432"
|
||||
|
||||
backend := testutil.Container{
|
||||
Image: "postgres:alpine",
|
||||
ExposedPorts: []string{postgresServicePort},
|
||||
Env: map[string]string{
|
||||
"POSTGRES_HOST_AUTH_METHOD": "trust",
|
||||
},
|
||||
WaitingFor: wait.ForLog("database system is ready to accept connections").WithOccurrence(2),
|
||||
}
|
||||
err := backend.Start()
|
||||
require.NoError(t, err, "failed to start container")
|
||||
defer backend.Terminate()
|
||||
|
||||
container := testutil.Container{
|
||||
Image: "z9pascal/pgbouncer-container:1.23.1-latest",
|
||||
ExposedPorts: []string{pgBouncerServicePort},
|
||||
Env: map[string]string{
|
||||
"PG_ENV_POSTGRESQL_USER": "pgbouncer",
|
||||
"PG_ENV_POSTGRESQL_PASS": "pgbouncer",
|
||||
},
|
||||
WaitingFor: wait.ForAll(
|
||||
wait.ForListeningPort(nat.Port(pgBouncerServicePort)),
|
||||
wait.ForLog("LOG process up"),
|
||||
),
|
||||
}
|
||||
err = container.Start()
|
||||
require.NoError(t, err, "failed to start container")
|
||||
defer container.Terminate()
|
||||
|
||||
addr := fmt.Sprintf(
|
||||
"host=%s user=pgbouncer password=pgbouncer dbname=pgbouncer port=%s sslmode=disable",
|
||||
container.Address,
|
||||
container.Ports[pgBouncerServicePort],
|
||||
)
|
||||
|
||||
p := &PgBouncer{
|
||||
Config: postgresql.Config{
|
||||
Address: config.NewSecret([]byte(addr)),
|
||||
IsPgBouncer: true,
|
||||
},
|
||||
ShowCommands: []string{"pools", "lists", "databases"},
|
||||
}
|
||||
require.NoError(t, p.Init())
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, p.Start(&acc))
|
||||
defer p.Stop()
|
||||
require.NoError(t, p.Gather(&acc))
|
||||
|
||||
intMetricsPgBouncerPools := []string{
|
||||
"cl_active",
|
||||
"cl_waiting",
|
||||
"sv_active",
|
||||
"sv_idle",
|
||||
"sv_used",
|
||||
"sv_tested",
|
||||
"sv_login",
|
||||
"maxwait",
|
||||
}
|
||||
|
||||
intMetricsPgBouncerLists := []string{
|
||||
"databases",
|
||||
"users",
|
||||
"pools",
|
||||
"free_clients",
|
||||
"used_clients",
|
||||
"login_clients",
|
||||
"free_servers",
|
||||
"used_servers",
|
||||
"dns_names",
|
||||
"dns_zones",
|
||||
"dns_queries",
|
||||
}
|
||||
|
||||
intMetricsPgBouncerDatabases := []string{
|
||||
"pool_size",
|
||||
"min_pool_size",
|
||||
"reserve_pool",
|
||||
"max_connections",
|
||||
"current_connections",
|
||||
"paused",
|
||||
"disabled",
|
||||
}
|
||||
|
||||
metricsCounted := 0
|
||||
|
||||
for _, metric := range intMetricsPgBouncerPools {
|
||||
require.True(t, acc.HasInt64Field("pgbouncer_pools", metric))
|
||||
metricsCounted++
|
||||
}
|
||||
|
||||
for _, metric := range intMetricsPgBouncerLists {
|
||||
require.True(t, acc.HasInt64Field("pgbouncer_lists", metric))
|
||||
metricsCounted++
|
||||
}
|
||||
|
||||
for _, metric := range intMetricsPgBouncerDatabases {
|
||||
require.True(t, acc.HasInt64Field("pgbouncer_databases", metric))
|
||||
metricsCounted++
|
||||
}
|
||||
|
||||
require.Positive(t, metricsCounted)
|
||||
require.Equal(t, len(intMetricsPgBouncerPools)+len(intMetricsPgBouncerLists)+len(intMetricsPgBouncerDatabases), metricsCounted)
|
||||
}
|
15
plugins/inputs/pgbouncer/sample.conf
Normal file
15
plugins/inputs/pgbouncer/sample.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Read metrics from one or many pgbouncer servers
|
||||
[[inputs.pgbouncer]]
|
||||
## specify address via a url matching:
|
||||
## postgres://[pqgotest[:password]]@host:port[/dbname]\
|
||||
## ?sslmode=[disable|verify-ca|verify-full]
|
||||
## or a simple string:
|
||||
## host=localhost port=5432 user=pqgotest password=... sslmode=... dbname=app_production
|
||||
##
|
||||
## All connection parameters are optional.
|
||||
##
|
||||
address = "host=localhost user=pgbouncer sslmode=disable"
|
||||
|
||||
## Specify which "show" commands to gather metrics for.
|
||||
## Choose from: "stats", "pools", "lists", "databases"
|
||||
# show_commands = ["stats", "pools"]
|
Loading…
Add table
Add a link
Reference in a new issue