pangolin_exporter

Форк
0
/
pg_database.go 
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
15
package collector
16

17
import (
18
	"context"
19
	"database/sql"
20

21
	"github.com/go-kit/log"
22
	"github.com/prometheus/client_golang/prometheus"
23
)
24

25
const databaseSubsystem = "database"
26

27
func init() {
28
	registerCollector(databaseSubsystem, defaultEnabled, NewPGDatabaseCollector)
29
}
30

31
type PGDatabaseCollector struct {
32
	log               log.Logger
33
	excludedDatabases []string
34
}
35

36
func NewPGDatabaseCollector(config collectorConfig) (Collector, error) {
37
	exclude := config.excludeDatabases
38
	if exclude == nil {
39
		exclude = []string{}
40
	}
41
	return &PGDatabaseCollector{
42
		log:               config.logger,
43
		excludedDatabases: exclude,
44
	}, nil
45
}
46

47
var (
48
	pgDatabaseSizeDesc = prometheus.NewDesc(
49
		prometheus.BuildFQName(
50
			namespace,
51
			databaseSubsystem,
52
			"size_bytes",
53
		),
54
		"Disk space used by the database",
55
		[]string{"datname"}, nil,
56
	)
57
	pgDatabaseConnectionLimitsDesc = prometheus.NewDesc(
58
		prometheus.BuildFQName(
59
			namespace,
60
			databaseSubsystem,
61
			"connection_limit",
62
		),
63
		"Connection limit set for the database",
64
		[]string{"datname"}, nil,
65
	)
66

67
	pgDatabaseQuery     = "SELECT pg_database.datname, pg_database.datconnlimit FROM pg_database;"
68
	pgDatabaseSizeQuery = "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.
79
func (c PGDatabaseCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
80
	db := instance.getDB()
81
	// Query the list of databases
82
	rows, err := db.QueryContext(ctx,
83
		pgDatabaseQuery,
84
	)
85
	if err != nil {
86
		return err
87
	}
88
	defer rows.Close()
89

90
	var databases []string
91

92
	for rows.Next() {
93
		var datname sql.NullString
94
		var connLimit sql.NullInt64
95
		if err := rows.Scan(&datname, &connLimit); err != nil {
96
			return err
97
		}
98

99
		if !datname.Valid {
100
			continue
101
		}
102
		database := 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
106
		if sliceContains(c.excludedDatabases, database) {
107
			continue
108
		}
109

110
		databases = append(databases, database)
111

112
		connLimitMetric := 0.0
113
		if connLimit.Valid {
114
			connLimitMetric = float64(connLimit.Int64)
115
		}
116
		ch <- prometheus.MustNewConstMetric(
117
			pgDatabaseConnectionLimitsDesc,
118
			prometheus.GaugeValue, connLimitMetric, database,
119
		)
120
	}
121

122
	// Query the size of the databases
123
	for _, datname := range databases {
124
		var size sql.NullFloat64
125
		err = db.QueryRowContext(ctx, pgDatabaseSizeQuery, datname).Scan(&size)
126
		if err != nil {
127
			return err
128
		}
129

130
		sizeMetric := 0.0
131
		if size.Valid {
132
			sizeMetric = size.Float64
133
		}
134
		ch <- prometheus.MustNewConstMetric(
135
			pgDatabaseSizeDesc,
136
			prometheus.GaugeValue, sizeMetric, datname,
137
		)
138

139
	}
140
	return rows.Err()
141
}
142

143
func sliceContains(slice []string, s string) bool {
144
	for _, item := range slice {
145
		if item == s {
146
			return true
147
		}
148
	}
149
	return false
150
}
151

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.