@@ -18,6 +18,7 @@ import (
1818 "database/sql"
1919 "fmt"
2020 "log/slog"
21+ "strings"
2122
2223 "github.com/alecthomas/kingpin/v2"
2324 "github.com/blang/semver/v4"
@@ -30,9 +31,11 @@ const (
3031)
3132
3233var (
33- includeQueryFlag * bool = nil
34- statementLengthFlag * uint = nil
35- statementLimitFlag * uint = nil
34+ includeQueryFlag * bool = nil
35+ statementLengthFlag * uint = nil
36+ statementLimitFlag * uint = nil
37+ excludedDatabasesFlag * string = nil
38+ excludedUsersFlag * string = nil
3639)
3740
3841func init () {
@@ -56,21 +59,53 @@ func init() {
5659 "Maximum number of statements to return." ).
5760 Default (defaultStatementLimit ).
5861 Uint ()
62+ excludedDatabasesFlag = kingpin .Flag (
63+ fmt .Sprint (collectorFlagPrefix , statStatementsSubsystem , ".exclude_databases" ),
64+ "Comma-separated list of database names to exclude. (default: none)" ).
65+ Default ("" ).
66+ String ()
67+ excludedUsersFlag = kingpin .Flag (
68+ fmt .Sprint (collectorFlagPrefix , statStatementsSubsystem , ".exclude_users" ),
69+ "Comma-separated list of user names to exclude. (default: none)" ).
70+ Default ("" ).
71+ String ()
5972}
6073
6174type PGStatStatementsCollector struct {
6275 log * slog.Logger
6376 includeQueryStatement bool
6477 statementLength uint
6578 statementLimit uint
79+ excludedDatabases []string
80+ excludedUsers []string
6681}
6782
6883func NewPGStatStatementsCollector (config collectorConfig ) (Collector , error ) {
84+ var excludedDatabases []string
85+ if * excludedDatabasesFlag != "" {
86+ for db := range strings .SplitSeq (* excludedDatabasesFlag , "," ) {
87+ if trimmed := strings .TrimSpace (db ); trimmed != "" {
88+ excludedDatabases = append (excludedDatabases , trimmed )
89+ }
90+ }
91+ }
92+
93+ var excludedUsers []string
94+ if * excludedUsersFlag != "" {
95+ for user := range strings .SplitSeq (* excludedUsersFlag , "," ) {
96+ if trimmed := strings .TrimSpace (user ); trimmed != "" {
97+ excludedUsers = append (excludedUsers , trimmed )
98+ }
99+ }
100+ }
101+
69102 return & PGStatStatementsCollector {
70103 log : config .logger ,
71104 includeQueryStatement : * includeQueryFlag ,
72105 statementLength : * statementLengthFlag ,
73106 statementLimit : * statementLimitFlag ,
107+ excludedDatabases : excludedDatabases ,
108+ excludedUsers : excludedUsers ,
74109 }, nil
75110}
76111
@@ -115,7 +150,9 @@ var (
115150)
116151
117152const (
118- pgStatStatementQuerySelect = `LEFT(pg_stat_statements.query, %d) as query,`
153+ pgStatStatementQuerySelect = `LEFT(pg_stat_statements.query, %d) as query,`
154+ pgStatStatementExcludeDatabases = `AND pg_database.datname NOT IN (%s) `
155+ pgStatStatementExcludeUsers = `AND pg_get_userbyid(userid) NOT IN (%s) `
119156
120157 pgStatStatementsQuery = `SELECT
121158 pg_get_userbyid(userid) as user,
@@ -136,6 +173,7 @@ const (
136173 WITHIN GROUP (ORDER BY total_time)
137174 FROM pg_stat_statements
138175 )
176+ %s
139177 ORDER BY seconds_total DESC
140178 LIMIT %s;`
141179
@@ -158,6 +196,7 @@ const (
158196 WITHIN GROUP (ORDER BY total_exec_time)
159197 FROM pg_stat_statements
160198 )
199+ %s
161200 ORDER BY seconds_total DESC
162201 LIMIT %s;`
163202
@@ -180,6 +219,7 @@ const (
180219 WITHIN GROUP (ORDER BY total_exec_time)
181220 FROM pg_stat_statements
182221 )
222+ %s
183223 ORDER BY seconds_total DESC
184224 LIMIT %s;`
185225)
@@ -198,11 +238,13 @@ func (c PGStatStatementsCollector) Update(ctx context.Context, instance *instanc
198238 if c .includeQueryStatement {
199239 querySelect = fmt .Sprintf (pgStatStatementQuerySelect , c .statementLength )
200240 }
241+ databaseFilter := c .buildExcludedDatabasesClause ()
242+ userFilter := c .buildExcludedUsersClause ()
201243 statementLimit := defaultStatementLimit
202244 if c .statementLimit > 0 {
203245 statementLimit = fmt .Sprintf ("%d" , c .statementLimit )
204246 }
205- query := fmt .Sprintf (queryTemplate , querySelect , statementLimit )
247+ query := fmt .Sprintf (queryTemplate , querySelect , databaseFilter + userFilter , statementLimit )
206248
207249 db := instance .getDB ()
208250 rows , err := db .QueryContext (ctx , query )
@@ -319,3 +361,28 @@ func (c PGStatStatementsCollector) Update(ctx context.Context, instance *instanc
319361 }
320362 return nil
321363}
364+
365+ func (c PGStatStatementsCollector ) buildExcludedDatabasesClause () string {
366+ if len (c .excludedDatabases ) == 0 {
367+ return ""
368+ }
369+
370+ databases := make ([]string , 0 , len (c .excludedDatabases ))
371+ for _ , db := range c .excludedDatabases {
372+ databases = append (databases , fmt .Sprintf ("'%s'" , strings .ReplaceAll (db , "'" , "''" )))
373+ }
374+
375+ return fmt .Sprintf (pgStatStatementExcludeDatabases , strings .Join (databases , ", " ))
376+ }
377+
378+ func (c PGStatStatementsCollector ) buildExcludedUsersClause () string {
379+ if len (c .excludedUsers ) == 0 {
380+ return ""
381+ }
382+
383+ users := make ([]string , 0 , len (c .excludedUsers ))
384+ for _ , user := range c .excludedUsers {
385+ users = append (users , fmt .Sprintf ("'%s'" , strings .ReplaceAll (user , "'" , "''" )))
386+ }
387+ return fmt .Sprintf (pgStatStatementExcludeUsers , strings .Join (users , ", " ))
388+ }
0 commit comments