Skip to content

Commit e86c022

Browse files
rechtdjaglowski
authored andcommitted
Support excluding specific postgresql databases from stats collection (open-telemetry#29605)
**Description:** There are cases where all except a few databases should be collected, for example the `rdsadmin` database in Amazon RDS is not accessible to regular users. This PR adds an `exclude_databases` config setting to the psql collector where it's possible to specify a list of databases that should be excluded. **Testing:** Unit tests added **Documentation:** Readme updated with new config setting --------- Co-authored-by: Daniel Jaglowski <[email protected]>
1 parent 7edaeaf commit e86c022

File tree

8 files changed

+1094
-1
lines changed

8 files changed

+1094
-1
lines changed

.chloggen/postgresql-exclude.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: 'enhancement'
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: postgresqlreceiver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add config property for excluding specific databases from scraping
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [29605]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

receiver/postgresqlreceiver/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ The following settings are optional:
3939

4040
- `databases` (default = `[]`): The list of databases for which the receiver will attempt to collect statistics. If an empty list is provided, the receiver will attempt to collect statistics for all non-template databases.
4141

42+
- `exclude_databases` (default = `[]`): List of databases which will be excluded when collecting statistics.
43+
4244
The following settings are also optional and nested under `tls` to help configure client transport security
4345

4446
- `insecure` (default = `false`): Whether to enable client transport security for the postgresql connection.
@@ -70,7 +72,7 @@ receivers:
7072
key_file: /home/otel/mypostgreskey.key
7173
```
7274
73-
The full list of settings exposed for this receiver are documented [here](./config.go) with detailed sample configurations [here](./testdata/config.yaml). TLS config is documented further under the [opentelemetry collector's configtls package](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md).
75+
The full list of settings exposed for this receiver are documented [here](./config.go) with detailed sample configurations [here](./testdata/config.yaml). TLS config is documented further under the [opentelemetry collector's configtls package](https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/configtls/README.md).
7476
7577
## Metrics
7678

receiver/postgresqlreceiver/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type Config struct {
3131
Username string `mapstructure:"username"`
3232
Password configopaque.String `mapstructure:"password"`
3333
Databases []string `mapstructure:"databases"`
34+
ExcludeDatabases []string `mapstructure:"exclude_databases"`
3435
confignet.NetAddr `mapstructure:",squash"` // provides Endpoint and Transport
3536
configtls.TLSClientSetting `mapstructure:"tls,omitempty"` // provides SSL details
3637
metadata.MetricsBuilderConfig `mapstructure:",squash"`

receiver/postgresqlreceiver/config_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ func TestLoadConfig(t *testing.T) {
139139
expected.Username = "otel"
140140
expected.Password = "${env:POSTGRESQL_PASSWORD}"
141141
expected.Databases = []string{"otel"}
142+
expected.ExcludeDatabases = []string{"template0"}
142143
expected.CollectionInterval = 10 * time.Second
143144
expected.TLSClientSetting = configtls.TLSClientSetting{
144145
Insecure: false,

receiver/postgresqlreceiver/scraper.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type postgreSQLScraper struct {
2424
config *Config
2525
clientFactory postgreSQLClientFactory
2626
mb *metadata.MetricsBuilder
27+
excludes map[string]struct{}
2728
}
2829
type errsMux struct {
2930
sync.RWMutex
@@ -69,11 +70,16 @@ func newPostgreSQLScraper(
6970
config *Config,
7071
clientFactory postgreSQLClientFactory,
7172
) *postgreSQLScraper {
73+
excludes := make(map[string]struct{})
74+
for _, db := range config.ExcludeDatabases {
75+
excludes[db] = struct{}{}
76+
}
7277
return &postgreSQLScraper{
7378
logger: settings.Logger,
7479
config: config,
7580
clientFactory: clientFactory,
7681
mb: metadata.NewMetricsBuilder(config.MetricsBuilderConfig, settings),
82+
excludes: excludes,
7783
}
7884
}
7985

@@ -102,6 +108,13 @@ func (p *postgreSQLScraper) scrape(ctx context.Context) (pmetric.Metrics, error)
102108
}
103109
databases = dbList
104110
}
111+
var filteredDatabases []string
112+
for _, db := range databases {
113+
if _, ok := p.excludes[db]; !ok {
114+
filteredDatabases = append(filteredDatabases, db)
115+
}
116+
}
117+
databases = filteredDatabases
105118

106119
now := pcommon.NewTimestampFromTime(time.Now())
107120

receiver/postgresqlreceiver/scraper_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,27 @@ func TestScraperWithResourceAttributeFeatureGateSingle(t *testing.T) {
207207
pmetrictest.IgnoreMetricDataPointsOrder(), pmetrictest.IgnoreStartTimestamp(), pmetrictest.IgnoreTimestamp()))
208208
}
209209

210+
func TestScraperExcludeDatabase(t *testing.T) {
211+
factory := mockClientFactory{}
212+
factory.initMocks([]string{"otel", "telemetry"})
213+
214+
cfg := createDefaultConfig().(*Config)
215+
cfg.ExcludeDatabases = []string{"open"}
216+
217+
scraper := newPostgreSQLScraper(receivertest.NewNopCreateSettings(), cfg, &factory)
218+
219+
actualMetrics, err := scraper.scrape(context.Background())
220+
require.NoError(t, err)
221+
222+
expectedFile := filepath.Join("testdata", "scraper", "multiple", "exclude.yaml")
223+
224+
expectedMetrics, err := golden.ReadMetrics(expectedFile)
225+
require.NoError(t, err)
226+
227+
require.NoError(t, pmetrictest.CompareMetrics(expectedMetrics, actualMetrics, pmetrictest.IgnoreResourceMetricsOrder(),
228+
pmetrictest.IgnoreMetricDataPointsOrder(), pmetrictest.IgnoreStartTimestamp(), pmetrictest.IgnoreTimestamp()))
229+
}
230+
210231
type mockClientFactory struct{ mock.Mock }
211232
type mockClient struct{ mock.Mock }
212233

receiver/postgresqlreceiver/testdata/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ postgresql/all:
99
password: ${env:POSTGRESQL_PASSWORD}
1010
databases:
1111
- otel
12+
exclude_databases:
13+
- template0
1214
collection_interval: 10s
1315
tls:
1416
insecure: false

0 commit comments

Comments
 (0)