2022-07-21 18:49:52 +02:00
package appmetrics
2019-05-22 23:16:55 +02:00
import (
"flag"
"fmt"
"io"
2020-11-03 13:10:42 +01:00
"regexp"
2019-05-22 23:16:55 +02:00
"strings"
2021-02-16 13:54:34 +01:00
"sync"
"sync/atomic"
2019-05-22 23:16:55 +02:00
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/buildinfo"
2021-02-16 13:54:34 +01:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
2021-03-10 11:01:18 +01:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/cgroup"
2020-09-16 21:34:01 +02:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil"
2019-05-22 23:16:55 +02:00
"github.com/VictoriaMetrics/VictoriaMetrics/lib/memory"
"github.com/VictoriaMetrics/metrics"
)
2023-12-19 02:19:42 +01:00
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 )
}
2021-09-21 22:07:56 +02:00
var versionRe = regexp . MustCompile ( ` v\d+\.\d+\.\d+(?:-enterprise)?(?:-cluster)? ` )
2020-11-03 13:10:42 +01:00
2020-08-07 09:56:50 +02:00
// WritePrometheusMetrics writes all the registered metrics to w in Prometheus exposition format.
func WritePrometheusMetrics ( w io . Writer ) {
2023-12-19 02:19:42 +01:00
exposeMetadataOnce . Do ( initExposeMetadata )
2021-02-16 13:54:34 +01:00
currentTime := time . Now ( )
metricsCacheLock . Lock ( )
if currentTime . Sub ( metricsCacheLastUpdateTime ) > time . Second {
var bb bytesutil . ByteBuffer
writePrometheusMetrics ( & bb )
metricsCache . Store ( & bb )
metricsCacheLastUpdateTime = currentTime
}
metricsCacheLock . Unlock ( )
2023-07-20 02:37:49 +02:00
bb := metricsCache . Load ( )
2021-02-16 21:05:00 +01:00
_ , _ = w . Write ( bb . B )
2021-02-16 13:54:34 +01:00
}
var (
metricsCacheLock sync . Mutex
metricsCacheLastUpdateTime time . Time
2023-07-20 02:37:49 +02:00
metricsCache atomic . Pointer [ bytesutil . ByteBuffer ]
2021-02-16 13:54:34 +01:00
)
func writePrometheusMetrics ( w io . Writer ) {
2019-05-22 23:16:55 +02:00
metrics . WritePrometheus ( w , true )
2021-02-04 15:33:07 +01:00
metrics . WriteFDMetrics ( w )
2019-05-22 23:16:55 +02:00
2023-12-19 02:19:42 +01:00
metrics . WriteGaugeUint64 ( w , fmt . Sprintf ( "vm_app_version{version=%q, short_version=%q}" , buildinfo . Version , versionRe . FindString ( buildinfo . Version ) ) , 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 ( ) ) )
2019-05-22 23:16:55 +02:00
// Export start time and uptime in seconds
2023-12-19 02:19:42 +01:00
metrics . WriteGaugeUint64 ( w , "vm_app_start_timestamp" , uint64 ( startTime . Unix ( ) ) )
metrics . WriteGaugeUint64 ( w , "vm_app_uptime_seconds" , uint64 ( time . Since ( startTime ) . Seconds ( ) ) )
2019-05-22 23:16:55 +02:00
// Export flags as metrics.
2021-07-13 14:07:59 +02:00
isSetMap := make ( map [ string ] bool )
flag . Visit ( func ( f * flag . Flag ) {
isSetMap [ f . Name ] = true
} )
2023-12-19 02:19:42 +01:00
metrics . WriteMetadataIfNeeded ( w , "flag" , "gauge" )
2019-05-22 23:16:55 +02:00
flag . VisitAll ( func ( f * flag . Flag ) {
lname := strings . ToLower ( f . Name )
value := f . Value . String ( )
2020-09-16 21:34:01 +02:00
if flagutil . IsSecretFlag ( lname ) {
2019-05-22 23:16:55 +02:00
// Do not expose passwords and keys to prometheus.
value = "secret"
}
2021-07-13 14:07:59 +02:00
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 )
2019-05-22 23:16:55 +02:00
} )
}
var startTime = time . Now ( )