Skip to content

Commit f2e810a

Browse files
Fix last scraped caching for all metrics modes (#370)
* Fix last scraped caching for all metrics modes Signed-off-by: Anders Swanson <[email protected]>
1 parent d0a7588 commit f2e810a

File tree

7 files changed

+62
-34
lines changed

7 files changed

+62
-34
lines changed

collector/collector.go

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
168168
// otherwise do a normal scrape per request
169169
e.mu.Lock() // ensure no simultaneous scrapes
170170
defer e.mu.Unlock()
171-
e.scrape(ch, nil)
171+
now := time.Now()
172+
e.scrape(ch, &now)
172173
ch <- e.duration
173174
ch <- e.totalScrapes
174175
ch <- e.error
@@ -390,34 +391,6 @@ func hashFile(h hash.Hash, fn string) error {
390391
return nil
391392
}
392393

393-
func (e *Exporter) reloadMetrics() {
394-
// Truncate metricsToScrape
395-
e.metricsToScrape.Metric = []*Metric{}
396-
397-
// Load default metrics
398-
defaultMetrics := e.DefaultMetrics()
399-
e.metricsToScrape.Metric = defaultMetrics.Metric
400-
401-
// If custom metrics, load it
402-
if len(e.CustomMetricsFiles()) > 0 {
403-
for _, _customMetrics := range e.CustomMetricsFiles() {
404-
metrics := &Metrics{}
405-
406-
if err := loadMetricsConfig(_customMetrics, metrics); err != nil {
407-
e.logger.Error("failed to load custom metrics", "error", err)
408-
panic(errors.New("Error while loading " + _customMetrics))
409-
} else {
410-
e.logger.Info("Successfully loaded custom metrics from " + _customMetrics)
411-
}
412-
413-
e.metricsToScrape.Metric = append(e.metricsToScrape.Metric, metrics.Metric...)
414-
}
415-
} else {
416-
e.logger.Debug("No custom metrics defined.")
417-
}
418-
e.initCache()
419-
}
420-
421394
// ScrapeMetric is an interface method to call scrapeGenericValues using Metric struct values
422395
func (e *Exporter) ScrapeMetric(d *Database, ch chan<- prometheus.Metric, m *Metric) error {
423396
e.logger.Debug("Calling function ScrapeGenericValues()")

collector/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func LoadMetricsConfiguration(logger *slog.Logger, cfg *Config, path string, fla
200200
return m, yerr
201201
}
202202
} else {
203-
logger.Warn("Configuring default database from CLI parameters is deprecated. Use of the '--config.file' argument is preferred. See https://github.com/oracle/oracle-db-appdev-monitoring?tab=readme-ov-file#standalone-binary")
203+
logger.Warn("Configuring default database from CLI parameters is deprecated. Use of the '--config.file' argument is preferred. See https://oracle.github.io/oracle-db-appdev-monitoring/docs/getting-started/basics#standalone-binary")
204204
m.Databases = make(map[string]DatabaseConfig)
205205
m.Databases["default"] = m.defaultDatabase(cfg)
206206
}

collector/data_loader.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package collector
55

66
import (
7+
"errors"
78
"fmt"
89
"os"
910
"strings"
@@ -12,6 +13,34 @@ import (
1213
"gopkg.in/yaml.v2"
1314
)
1415

16+
func (e *Exporter) reloadMetrics() {
17+
// Truncate metricsToScrape
18+
e.metricsToScrape.Metric = []*Metric{}
19+
20+
// Load default metrics
21+
defaultMetrics := e.DefaultMetrics()
22+
e.metricsToScrape.Metric = defaultMetrics.Metric
23+
24+
// If custom metrics, load it
25+
if len(e.CustomMetricsFiles()) > 0 {
26+
for _, _customMetrics := range e.CustomMetricsFiles() {
27+
metrics := &Metrics{}
28+
29+
if err := loadMetricsConfig(_customMetrics, metrics); err != nil {
30+
e.logger.Error("failed to load custom metrics", "error", err)
31+
panic(errors.New("Error while loading " + _customMetrics))
32+
} else {
33+
e.logger.Info("Successfully loaded custom metrics from " + _customMetrics)
34+
}
35+
36+
e.metricsToScrape.Metric = append(e.metricsToScrape.Metric, metrics.Metric...)
37+
}
38+
} else {
39+
e.logger.Debug("No custom metrics defined.")
40+
}
41+
e.initCache()
42+
}
43+
1544
func loadYamlMetricsConfig(_metricsFileName string, metrics *Metrics) error {
1645
yamlBytes, err := os.ReadFile(_metricsFileName)
1746
if err != nil {

collector/metrics.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (e *Exporter) isScrapeMetric(tick *time.Time, metric *Metric, d *Database)
3434
// we should scrape the metric.
3535
interval < tick.Sub(*lastScraped)
3636
if shouldScrape {
37-
d.MetricsCache.SetLastScraped(metric, lastScraped)
37+
d.MetricsCache.SetLastScraped(metric, tick)
3838
}
3939
return shouldScrape
4040
}
@@ -78,6 +78,15 @@ func (e *Exporter) parseFloat(metric, metricHelp string, row map[string]string)
7878
return valueFloat, true
7979
}
8080

81+
func (m *Metric) ID() string {
82+
sb := strings.Builder{}
83+
sb.WriteString(m.Context)
84+
for desc := range m.MetricsDesc {
85+
sb.WriteString(desc)
86+
}
87+
return sb.String()
88+
}
89+
8190
func (m *Metric) GetLabels() []string {
8291
if len(m.FieldToAppend) == 0 {
8392
return m.Labels

site/docs/configuration/config-file.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
title: Exporter Config File
2+
title: Exporter Configuration
33
sidebar_position: 1
44
---
55

6-
# Exporter Config File
6+
# Exporter Configuration
77

88
The recommended way to configure the exporter is with the `--config.file` argument, specifying a YAML configuration file.
99

@@ -92,6 +92,20 @@ log:
9292
# configFile: /path/to/webconfigfile
9393
```
9494

95+
### Scrape on request vs. Scrape on interval
96+
97+
The metrics exporter has two scraping modes: scrape on request, and scrape on interval. By default, the metrics exporter scrapes metrics on request, when the `/metrics` endpoint is invoked.
98+
99+
To scrape metrics on a given interval, set the `metrics.scrapeInterval` property to a valid interval:
100+
101+
```yaml
102+
metrics:
103+
# Metrics will be scraped every 30s.
104+
scrapeInterval: 30s
105+
```
106+
107+
An individual metric may have its own scrape interval separate from the exporter's scrape interval. See the [metric schema](custom-metrics.md#metric-schema) for details on configuring per-metric scrape intervals.
108+
95109
### Config file in a container image
96110
97111
To add your custom config file to a container image, you can layer the base exporter image and include that config:

site/docs/configuration/custom-metrics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Metrics files must contain a series of `[[metric]]` definitions, in TOML, or the
3838
| request | Oracle database query to run for metrics scraping | String | Yes | |
3939
| ignorezeroresult | Whether or not an error will be printed if the request does not return any results | Boolean | No | false |
4040
| querytimeout | Oracle Database query timeout duration, e.g., 300ms, 0.5h | String duration | No | Value of query.timeout in seconds |
41-
| scrapeinterval | Custom metric scrape interval, used if scrape.interval is provided, otherwise metrics are always scraped on request. | String duration | No | |
41+
| scrapeinterval | Custom metric scrape interval. If the metric was already scraped during the specified interval, a cached value is provided. | String duration | No | |
4242
| databases | Array of databases the metric will be scraped from, using the database name from the exporter config file. If not present, the metric is scraped from all databases. If the databases array is empty (`databases = []`) the metric will not be scraped, effectively being disabled. | Array of Strings | No | |
4343

4444
### Example Metric Definition

site/docs/releases/changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ Our current priorities to support metrics for advanced database features and use
1515
- Standardize multi-arch builds and document supported database versions.
1616
- Metrics with an empty databases array (`databases = []`) are now considered disabled, and will not be scraped.
1717
- Increased the default query timeout for the `top_sql` metric to 10 seconds (previously 5 seconds).
18+
- Metrics using the `scrapeinterval` property will no longer be scraped on every request if they have a cached value. This only applies when the metrics exporter is configured to scrape metrics _on request_, rather than on a global interval.
1819
- Metrics using the `fieldtoappend` property now support labels. The `wait_time` and `activity` default metrics use the `fieldtoappend` property, and now properly display their labels.
1920
- Fix `wait_time` default metric to work with Oracle Database 19c.
21+
- Fix an issue where the exporter would unnecessarily scrape metrics with a custom scrape interval.
2022

2123
Thank you to the following people for their suggestions and contributions:
2224
- [@romankspb](https://github.com/romankspb)
2325
- [@muhammadabdullah-amjad](https://github.com/muhammadabdullah-amjad)
2426
- [@MansuyDavid](https://github.com/MansuyDavid)
2527
- [@borkoz](https://github.com/borkoz)
28+
- [@ristagg](https://github.com/ristagg)
2629

2730
### Version 2.0.4, September 8, 2025
2831

0 commit comments

Comments
 (0)