pangolin_exporter
129 строк · 2.8 Кб
1// Copyright 2023 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
14package collector
15
16import (
17"context"
18"database/sql"
19
20"github.com/go-kit/log"
21"github.com/prometheus/client_golang/prometheus"
22)
23
24const locksSubsystem = "locks"
25
26func init() {
27registerCollector(locksSubsystem, defaultEnabled, NewPGLocksCollector)
28}
29
30type PGLocksCollector struct {
31log log.Logger
32}
33
34func NewPGLocksCollector(config collectorConfig) (Collector, error) {
35return &PGLocksCollector{
36log: config.logger,
37}, nil
38}
39
40var (
41pgLocksDesc = prometheus.NewDesc(
42prometheus.BuildFQName(
43namespace,
44locksSubsystem,
45"count",
46),
47"Number of locks",
48[]string{"datname", "mode"}, nil,
49)
50
51pgLocksQuery = `
52SELECT
53pg_database.datname as datname,
54tmp.mode as mode,
55COALESCE(count, 0) as count
56FROM
57(
58VALUES
59('accesssharelock'),
60('rowsharelock'),
61('rowexclusivelock'),
62('shareupdateexclusivelock'),
63('sharelock'),
64('sharerowexclusivelock'),
65('exclusivelock'),
66('accessexclusivelock'),
67('sireadlock')
68) AS tmp(mode)
69CROSS JOIN pg_database
70LEFT JOIN (
71SELECT
72database,
73lower(mode) AS mode,
74count(*) AS count
75FROM
76pg_locks
77WHERE
78database IS NOT NULL
79GROUP BY
80database,
81lower(mode)
82) AS tmp2 ON tmp.mode = tmp2.mode
83and pg_database.oid = tmp2.database
84ORDER BY
851
86`
87)
88
89// Update implements Collector and exposes database locks.
90// It is called by the Prometheus registry when collecting metrics.
91func (c PGLocksCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error {
92db := instance.getDB()
93// Query the list of databases
94rows, err := db.QueryContext(ctx,
95pgLocksQuery,
96)
97if err != nil {
98return err
99}
100defer rows.Close()
101
102var datname, mode sql.NullString
103var count sql.NullInt64
104
105for rows.Next() {
106if err := rows.Scan(&datname, &mode, &count); err != nil {
107return err
108}
109
110if !datname.Valid || !mode.Valid {
111continue
112}
113
114countMetric := 0.0
115if count.Valid {
116countMetric = float64(count.Int64)
117}
118
119ch <- prometheus.MustNewConstMetric(
120pgLocksDesc,
121prometheus.GaugeValue, countMetric,
122datname.String, mode.String,
123)
124}
125if err := rows.Err(); err != nil {
126return err
127}
128return nil
129}
130