pangolin_exporter
150 строк · 3.9 Кб
1// Copyright 2022 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// По просьбе НТ, для совместимости оставил pg_database_size_bytes
15package collector
16
17import (
18"context"
19"database/sql"
20
21"github.com/go-kit/log"
22"github.com/prometheus/client_golang/prometheus"
23)
24
25const databaseSubsystem = "database"
26
27func init() {
28registerCollector(databaseSubsystem, defaultEnabled, NewPGDatabaseCollector)
29}
30
31type PGDatabaseCollector struct {
32log log.Logger
33excludedDatabases []string
34}
35
36func NewPGDatabaseCollector(config collectorConfig) (Collector, error) {
37exclude := config.excludeDatabases
38if exclude == nil {
39exclude = []string{}
40}
41return &PGDatabaseCollector{
42log: config.logger,
43excludedDatabases: exclude,
44}, nil
45}
46
47var (
48pgDatabaseSizeDesc = prometheus.NewDesc(
49prometheus.BuildFQName(
50namespace,
51databaseSubsystem,
52"size_bytes",
53),
54"Disk space used by the database",
55[]string{"datname"}, nil,
56)
57pgDatabaseConnectionLimitsDesc = prometheus.NewDesc(
58prometheus.BuildFQName(
59namespace,
60databaseSubsystem,
61"connection_limit",
62),
63"Connection limit set for the database",
64[]string{"datname"}, nil,
65)
66
67pgDatabaseQuery = "SELECT pg_database.datname, pg_database.datconnlimit FROM pg_database;"
68pgDatabaseSizeQuery = "SELECT pg_database_size($1)"
69)
70
71// Update implements Collector and exposes database size and connection limits.
72// It is called by the Prometheus registry when collecting metrics.
73// The list of databases is retrieved from pg_database and filtered
74// by the excludeDatabase config parameter. The tradeoff here is that
75// we have to query the list of databases and then query the size of
76// each database individually. This is because we can't filter the
77// list of databases in the query because the list of excluded
78// databases is dynamic.
79func (c PGDatabaseCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
80db := instance.getDB()
81// Query the list of databases
82rows, err := db.QueryContext(ctx,
83pgDatabaseQuery,
84)
85if err != nil {
86return err
87}
88defer rows.Close()
89
90var databases []string
91
92for rows.Next() {
93var datname sql.NullString
94var connLimit sql.NullInt64
95if err := rows.Scan(&datname, &connLimit); err != nil {
96return err
97}
98
99if !datname.Valid {
100continue
101}
102database := datname.String
103// Ignore excluded databases
104// Filtering is done here instead of in the query to avoid
105// a complicated NOT IN query with a variable number of parameters
106if sliceContains(c.excludedDatabases, database) {
107continue
108}
109
110databases = append(databases, database)
111
112connLimitMetric := 0.0
113if connLimit.Valid {
114connLimitMetric = float64(connLimit.Int64)
115}
116ch <- prometheus.MustNewConstMetric(
117pgDatabaseConnectionLimitsDesc,
118prometheus.GaugeValue, connLimitMetric, database,
119)
120}
121
122// Query the size of the databases
123for _, datname := range databases {
124var size sql.NullFloat64
125err = db.QueryRowContext(ctx, pgDatabaseSizeQuery, datname).Scan(&size)
126if err != nil {
127return err
128}
129
130sizeMetric := 0.0
131if size.Valid {
132sizeMetric = size.Float64
133}
134ch <- prometheus.MustNewConstMetric(
135pgDatabaseSizeDesc,
136prometheus.GaugeValue, sizeMetric, datname,
137)
138
139}
140return rows.Err()
141}
142
143func sliceContains(slice []string, s string) bool {
144for _, item := range slice {
145if item == s {
146return true
147}
148}
149return false
150}
151