mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-10 15:14:09 +00:00
app/victoria-metrics: add -selfScrapeInterval
flag for self-scraping /metrics
page
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/30 Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/180
This commit is contained in:
parent
2a0a0ed14d
commit
9df5b2d1c3
5 changed files with 110 additions and 4 deletions
|
@ -786,8 +786,11 @@ mkfs.ext4 ... -O 64bit,huge_file,extent -T huge
|
||||||
|
|
||||||
### Monitoring
|
### Monitoring
|
||||||
|
|
||||||
VictoriaMetrics exports internal metrics in Prometheus format on the `/metrics` page.
|
VictoriaMetrics exports internal metrics in Prometheus format at `/metrics` page.
|
||||||
Add this page to Prometheus' scrape config in order to collect VictoriaMetrics metrics.
|
These metrics may be collected either via Prometheus by adding the corresponding scrape config to it.
|
||||||
|
Alternatively they can be self-scraped by setting `-selfScrapeInterval` command-line flag to duration greater than 0.
|
||||||
|
For example, `-scrapeInterval=10s` would enable self-scraping of `/metrics` page with 10 seconds interval.
|
||||||
|
|
||||||
There are officials Grafana dashboards for [single-node VictoriaMetrics](https://grafana.com/dashboards/10229) and [clustered VictoriaMetrics](https://grafana.com/grafana/dashboards/11176).
|
There are officials Grafana dashboards for [single-node VictoriaMetrics](https://grafana.com/dashboards/10229) and [clustered VictoriaMetrics](https://grafana.com/grafana/dashboards/11176).
|
||||||
|
|
||||||
The most interesting metrics are:
|
The most interesting metrics are:
|
||||||
|
|
|
@ -26,6 +26,7 @@ func main() {
|
||||||
vmstorage.Init()
|
vmstorage.Init()
|
||||||
vmselect.Init()
|
vmselect.Init()
|
||||||
vminsert.Init()
|
vminsert.Init()
|
||||||
|
startSelfScraper()
|
||||||
|
|
||||||
go httpserver.Serve(*httpListenAddr, requestHandler)
|
go httpserver.Serve(*httpListenAddr, requestHandler)
|
||||||
logger.Infof("started VictoriaMetrics in %.3f seconds", time.Since(startTime).Seconds())
|
logger.Infof("started VictoriaMetrics in %.3f seconds", time.Since(startTime).Seconds())
|
||||||
|
@ -33,6 +34,8 @@ func main() {
|
||||||
sig := procutil.WaitForSigterm()
|
sig := procutil.WaitForSigterm()
|
||||||
logger.Infof("received signal %s", sig)
|
logger.Infof("received signal %s", sig)
|
||||||
|
|
||||||
|
stopSelfScraper()
|
||||||
|
|
||||||
logger.Infof("gracefully shutting down webservice at %q", *httpListenAddr)
|
logger.Infof("gracefully shutting down webservice at %q", *httpListenAddr)
|
||||||
startTime = time.Now()
|
startTime = time.Now()
|
||||||
if err := httpserver.Stop(*httpListenAddr); err != nil {
|
if err := httpserver.Stop(*httpListenAddr); err != nil {
|
||||||
|
|
99
app/victoria-metrics/self_scraper.go
Normal file
99
app/victoria-metrics/self_scraper.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmstorage"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompb"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/protoparser/prometheus"
|
||||||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
var selfScrapeInterval = flag.Duration("selfScrapeInterval", 0, "Interval for self-scraping own metrics at `/metrics` page")
|
||||||
|
|
||||||
|
var selfScraperStopCh chan struct{}
|
||||||
|
var selfScraperWG sync.WaitGroup
|
||||||
|
|
||||||
|
func startSelfScraper() {
|
||||||
|
selfScraperStopCh = make(chan struct{})
|
||||||
|
selfScraperWG.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer selfScraperWG.Done()
|
||||||
|
selfScraper(*selfScrapeInterval)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopSelfScraper() {
|
||||||
|
close(selfScraperStopCh)
|
||||||
|
selfScraperWG.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func selfScraper(scrapeInterval time.Duration) {
|
||||||
|
if scrapeInterval <= 0 {
|
||||||
|
// Self-scrape is disabled.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Infof("started self-scraping `/metrics` page with interval %.3f seconds", scrapeInterval.Seconds())
|
||||||
|
|
||||||
|
var bb bytesutil.ByteBuffer
|
||||||
|
var rows prometheus.Rows
|
||||||
|
var mrs []storage.MetricRow
|
||||||
|
var labels []prompb.Label
|
||||||
|
t := time.NewTicker(scrapeInterval)
|
||||||
|
var currentTimestamp int64
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-selfScraperStopCh:
|
||||||
|
t.Stop()
|
||||||
|
logger.Infof("stopped self-scraping `/metrics` page")
|
||||||
|
return
|
||||||
|
case currentTime := <-t.C:
|
||||||
|
currentTimestamp = currentTime.UnixNano() / 1e6
|
||||||
|
}
|
||||||
|
bb.Reset()
|
||||||
|
httpserver.WritePrometheusMetrics(&bb)
|
||||||
|
s := bytesutil.ToUnsafeString(bb.B)
|
||||||
|
rows.Reset()
|
||||||
|
rows.Unmarshal(s)
|
||||||
|
mrs = mrs[:0]
|
||||||
|
for i := range rows.Rows {
|
||||||
|
r := &rows.Rows[i]
|
||||||
|
labels = labels[:0]
|
||||||
|
labels = addLabel(labels, "", r.Metric)
|
||||||
|
labels = addLabel(labels, "job", "victoria-metrics")
|
||||||
|
labels = addLabel(labels, "instance", "self")
|
||||||
|
for j := range r.Tags {
|
||||||
|
t := &r.Tags[j]
|
||||||
|
labels = addLabel(labels, t.Key, t.Value)
|
||||||
|
}
|
||||||
|
if len(mrs) < cap(mrs) {
|
||||||
|
mrs = mrs[:len(mrs)+1]
|
||||||
|
} else {
|
||||||
|
mrs = append(mrs, storage.MetricRow{})
|
||||||
|
}
|
||||||
|
mr := &mrs[len(mrs)-1]
|
||||||
|
mr.MetricNameRaw = storage.MarshalMetricNameRaw(mr.MetricNameRaw[:0], labels)
|
||||||
|
mr.Timestamp = currentTimestamp
|
||||||
|
mr.Value = r.Value
|
||||||
|
}
|
||||||
|
logger.Infof("writing %d rows at timestamp %d", len(mrs), currentTimestamp)
|
||||||
|
vmstorage.AddRows(mrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addLabel(dst []prompb.Label, key, value string) []prompb.Label {
|
||||||
|
if len(dst) < cap(dst) {
|
||||||
|
dst = dst[:len(dst)+1]
|
||||||
|
} else {
|
||||||
|
dst = append(dst, prompb.Label{})
|
||||||
|
}
|
||||||
|
lb := &dst[len(dst)-1]
|
||||||
|
lb.Name = bytesutil.ToUnsafeBytes(key)
|
||||||
|
lb.Value = bytesutil.ToUnsafeBytes(value)
|
||||||
|
return dst
|
||||||
|
}
|
|
@ -181,7 +181,7 @@ func handlerWrapper(w http.ResponseWriter, r *http.Request, rh RequestHandler) {
|
||||||
}
|
}
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
writePrometheusMetrics(w)
|
WritePrometheusMetrics(w)
|
||||||
metricsHandlerDuration.UpdateDuration(startTime)
|
metricsHandlerDuration.UpdateDuration(startTime)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -12,7 +12,8 @@ import (
|
||||||
"github.com/VictoriaMetrics/metrics"
|
"github.com/VictoriaMetrics/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
func writePrometheusMetrics(w io.Writer) {
|
// WritePrometheusMetrics writes all the registered metrics to w in Prometheus exposition format.
|
||||||
|
func WritePrometheusMetrics(w io.Writer) {
|
||||||
metrics.WritePrometheus(w, true)
|
metrics.WritePrometheus(w, true)
|
||||||
|
|
||||||
fmt.Fprintf(w, "vm_app_version{version=%q} 1\n", buildinfo.Version)
|
fmt.Fprintf(w, "vm_app_version{version=%q} 1\n", buildinfo.Version)
|
||||||
|
|
Loading…
Reference in a new issue