Skip to content

Commit 3d6f458

Browse files
committed
Move pg_process_idle to collectors
1 parent 7087fe1 commit 3d6f458

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

collector/pg_process_idle.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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+
14+
package collector
15+
16+
import (
17+
"context"
18+
"database/sql"
19+
20+
"github.com/go-kit/log"
21+
"github.com/prometheus/client_golang/prometheus"
22+
)
23+
24+
func init() {
25+
registerCollector("statements", defaultEnabled, NewPGProcessIdleCollector)
26+
}
27+
28+
type PGProcessIdleCollector struct {
29+
log log.Logger
30+
}
31+
32+
var processIdleSubsystem = "process_idle"
33+
34+
func NewPGProcessIdleCollector(config collectorConfig) (Collector, error) {
35+
return &PGProcessIdleCollector{log: config.logger}, nil
36+
}
37+
38+
var processIdle = map[string]*prometheus.Desc{
39+
"seconds": prometheus.NewDesc(
40+
prometheus.BuildFQName(namespace, processIdleSubsystem, "seconds"),
41+
"Idle time of server processes",
42+
[]string{"application_name"},
43+
prometheus.Labels{},
44+
),
45+
}
46+
47+
func (PGProcessIdleCollector) Update(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error {
48+
row := db.QueryRowContext(ctx,
49+
`WITH
50+
metrics AS (
51+
SELECT
52+
application_name,
53+
SUM(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - state_change))::bigint)::float AS process_idle_seconds_sum,
54+
COUNT(*) AS process_idle_seconds_count
55+
FROM pg_stat_activity
56+
WHERE state = 'idle'
57+
GROUP BY application_name
58+
),
59+
buckets AS (
60+
SELECT
61+
application_name,
62+
le,
63+
SUM(
64+
CASE WHEN EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - state_change)) <= le
65+
THEN 1
66+
ELSE 0
67+
END
68+
)::bigint AS bucket
69+
FROM
70+
pg_stat_activity,
71+
UNNEST(ARRAY[1, 2, 5, 15, 30, 60, 90, 120, 300]) AS le
72+
GROUP BY application_name, le
73+
ORDER BY application_name, le
74+
)
75+
SELECT
76+
application_name,
77+
process_idle_seconds_sum as seconds_sum,
78+
process_idle_seconds_count as seconds_count,
79+
ARRAY_AGG(le) AS seconds,
80+
ARRAY_AGG(bucket) AS seconds_bucket
81+
FROM metrics JOIN buckets USING (application_name)
82+
GROUP BY 1, 2, 3;`)
83+
84+
var applicationName string
85+
var secondsSum int64
86+
var secondsCount uint64
87+
var seconds []int64
88+
var secondsBucket []uint64
89+
90+
err := row.Scan(&applicationName, &secondsSum, &secondsCount, &seconds, &secondsBucket)
91+
92+
var buckets = make(map[float64]uint64, len(seconds))
93+
for i, second := range seconds {
94+
if i >= len(secondsBucket) {
95+
break
96+
}
97+
buckets[float64(second)] = secondsBucket[i]
98+
}
99+
if err != nil {
100+
return err
101+
}
102+
ch <- prometheus.MustNewConstHistogram(
103+
processIdle["seconds"],
104+
secondsCount, float64(secondsSum), buckets,
105+
applicationName,
106+
)
107+
return nil
108+
}

0 commit comments

Comments
 (0)