Files
VictoriaMetrics/lib/appmetrics/appmetrics.go
Max Kotliar 0a31eacb3d lib/{osinfo,appmetrics}: Move vm_os_info metric code to lib/appmetrics package (#10776)
Follow-up commit for
211fb08028

Address @f41gh7 review comments:
- Move code from `lib/osinfo` to `lib/appmetrics`.
- Make the logic private.
- Use metrics.WriteGaugeUint64 func.
- Remove registration logic from `app/xxx/main.go`.
- Remove `lib/osinfo` package.
2026-04-09 18:32:47 +03:00

91 lines
3.0 KiB
Go

package appmetrics
import (
"flag"
"fmt"
"io"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/memory"
"github.com/VictoriaMetrics/metrics"
)
var exposeMetadata = flag.Bool("metrics.exposeMetadata", false, "Whether to expose TYPE and HELP metadata at the /metrics page, which is exposed at -httpListenAddr . "+
"The metadata may be needed when the /metrics page is consumed by systems, which require this information. For example, Managed Prometheus in Google Cloud - "+
"https://cloud.google.com/stackdriver/docs/managed-prometheus/troubleshooting#missing-metric-type")
var exposeMetadataOnce sync.Once
func initExposeMetadata() {
metrics.ExposeMetadata(*exposeMetadata)
}
// WritePrometheusMetrics writes all the registered metrics to w in Prometheus exposition format.
func WritePrometheusMetrics(w io.Writer) {
exposeMetadataOnce.Do(initExposeMetadata)
currentTime := time.Now()
metricsCacheLock.Lock()
if currentTime.Sub(metricsCacheLastUpdateTime) > time.Second {
var bb bytesutil.ByteBuffer
writePrometheusMetrics(&bb)
writeOSMetrics(&bb)
metricsCache.Store(&bb)
metricsCacheLastUpdateTime = currentTime
}
metricsCacheLock.Unlock()
bb := metricsCache.Load()
_, _ = w.Write(bb.B)
}
var (
metricsCacheLock sync.Mutex
metricsCacheLastUpdateTime time.Time
metricsCache atomic.Pointer[bytesutil.ByteBuffer]
)
func writePrometheusMetrics(w io.Writer) {
metrics.WritePrometheus(w, true)
metrics.WriteFDMetrics(w)
metrics.WriteGaugeUint64(w, fmt.Sprintf("vm_app_version{version=%q, short_version=%q}", buildinfo.Version, buildinfo.ShortVersion()), 1)
metrics.WriteGaugeUint64(w, "vm_allowed_memory_bytes", uint64(memory.Allowed()))
metrics.WriteGaugeUint64(w, "vm_available_memory_bytes", uint64(memory.Allowed()+memory.Remaining()))
metrics.WriteGaugeUint64(w, "vm_available_cpu_cores", uint64(cgroup.AvailableCPUs()))
metrics.WriteGaugeUint64(w, "vm_gogc", uint64(cgroup.GetGOGC()))
// Export start time and uptime in seconds
metrics.WriteGaugeUint64(w, "vm_app_start_timestamp", uint64(startTime.Unix()))
metrics.WriteGaugeUint64(w, "vm_app_uptime_seconds", uint64(time.Since(startTime).Seconds()))
// Export flags as metrics.
isSetMap := make(map[string]bool)
flag.Visit(func(f *flag.Flag) {
isSetMap[f.Name] = true
})
metrics.WriteMetadataIfNeeded(w, "flag", "gauge")
flag.VisitAll(func(f *flag.Flag) {
lname := strings.ToLower(f.Name)
value := f.Value.String()
if flagutil.IsSecretFlag(lname) {
// Do not expose passwords and keys to prometheus.
value = "secret"
}
isSet := "false"
if isSetMap[f.Name] {
isSet = "true"
}
fmt.Fprintf(w, "flag{name=%q, value=%q, is_set=%q} 1\n", f.Name, value, isSet)
})
}
var startTime = time.Now()