mirror of
https://github.com/safing/portbase
synced 2025-09-04 03:29:59 +00:00
Add config options for metrics
This commit is contained in:
parent
4a05c26339
commit
aef3f26ad3
4 changed files with 89 additions and 16 deletions
|
@ -90,7 +90,7 @@ func writeMetricsTo(ctx context.Context, url string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create request
|
// Create request
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, buf)
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create request: %w", err)
|
return fmt.Errorf("failed to create request: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ func writeMetricsTo(ctx context.Context, url string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func metricsWriter(ctx context.Context) error {
|
func metricsWriter(ctx context.Context) error {
|
||||||
|
pushURL := pushOption()
|
||||||
ticker := time.NewTicker(10 * time.Second)
|
ticker := time.NewTicker(10 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
|
69
metrics/config.go
Normal file
69
metrics/config.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/safing/portbase/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configuration Keys
|
||||||
|
var (
|
||||||
|
CfgOptionInstanceKey = "core/metrics/instance"
|
||||||
|
instanceOption config.StringOption
|
||||||
|
cfgOptionInstanceOrder = 0
|
||||||
|
|
||||||
|
CfgOptionPushKey = "core/metrics/push"
|
||||||
|
pushOption config.StringOption
|
||||||
|
cfgOptionPushOrder = 0
|
||||||
|
|
||||||
|
pushFlag string
|
||||||
|
instanceFlag string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.StringVar(&pushFlag, "push-metrics", "", "Set default URL to push prometheus metrics to.")
|
||||||
|
flag.StringVar(&instanceFlag, "metrics-instance", "", "Set the default global instance label.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepConfig() error {
|
||||||
|
err := config.Register(&config.Option{
|
||||||
|
Name: "Metrics Instance Name",
|
||||||
|
Key: CfgOptionInstanceKey,
|
||||||
|
Description: "Define the prometheus instance label for exported metrics. Please note that changing the instance name will reset persisted metrics.",
|
||||||
|
OptType: config.OptTypeString,
|
||||||
|
ExpertiseLevel: config.ExpertiseLevelExpert,
|
||||||
|
ReleaseLevel: config.ReleaseLevelStable,
|
||||||
|
DefaultValue: instanceFlag,
|
||||||
|
RequiresRestart: true,
|
||||||
|
Annotations: config.Annotations{
|
||||||
|
config.DisplayOrderAnnotation: cfgOptionInstanceOrder,
|
||||||
|
config.CategoryAnnotation: "Metrics",
|
||||||
|
},
|
||||||
|
ValidationRegex: "^(" + prometheusBaseFormt + ")?$",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
instanceOption = config.Concurrent.GetAsString(CfgOptionInstanceKey, instanceFlag)
|
||||||
|
|
||||||
|
err = config.Register(&config.Option{
|
||||||
|
Name: "Push Metrics",
|
||||||
|
Key: CfgOptionPushKey,
|
||||||
|
Description: "Push metrics to this URL in the prometheus format.",
|
||||||
|
OptType: config.OptTypeString,
|
||||||
|
ExpertiseLevel: config.ExpertiseLevelExpert,
|
||||||
|
ReleaseLevel: config.ReleaseLevelStable,
|
||||||
|
DefaultValue: pushFlag,
|
||||||
|
RequiresRestart: true,
|
||||||
|
Annotations: config.Annotations{
|
||||||
|
config.DisplayOrderAnnotation: cfgOptionPushOrder,
|
||||||
|
config.CategoryAnnotation: "Metrics",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pushOption = config.Concurrent.GetAsString(CfgOptionPushKey, pushFlag)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -15,7 +15,8 @@ import (
|
||||||
|
|
||||||
// PrometheusFormatRequirement is required format defined by prometheus for
|
// PrometheusFormatRequirement is required format defined by prometheus for
|
||||||
// metric and label names.
|
// metric and label names.
|
||||||
const PrometheusFormatRequirement = "[a-zA-Z_][a-zA-Z0-9_]*"
|
const prometheusBaseFormt = "[a-zA-Z_][a-zA-Z0-9_]*"
|
||||||
|
const PrometheusFormatRequirement = "^" + prometheusBaseFormt + "$"
|
||||||
|
|
||||||
var prometheusFormat = regexp.MustCompile(PrometheusFormatRequirement)
|
var prometheusFormat = regexp.MustCompile(PrometheusFormatRequirement)
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ type Options struct {
|
||||||
|
|
||||||
func newMetricBase(id string, labels map[string]string, opts Options) (*metricBase, error) {
|
func newMetricBase(id string, labels map[string]string, opts Options) (*metricBase, error) {
|
||||||
// Check formats.
|
// Check formats.
|
||||||
if !prometheusFormat.MatchString(id) {
|
if !prometheusFormat.MatchString(strings.ReplaceAll(id, "/", "_")) {
|
||||||
return nil, fmt.Errorf("metric name %q must match %s", id, PrometheusFormatRequirement)
|
return nil, fmt.Errorf("metric name %q must match %s", id, PrometheusFormatRequirement)
|
||||||
}
|
}
|
||||||
for labelName := range labels {
|
for labelName := range labels {
|
||||||
|
@ -75,6 +76,11 @@ func newMetricBase(id string, labels map[string]string, opts Options) (*metricBa
|
||||||
opts.Permission = api.PermitUser
|
opts.Permission = api.PermitUser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that labels is a map.
|
||||||
|
if labels == nil {
|
||||||
|
labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
// Create metric base.
|
// Create metric base.
|
||||||
base := &metricBase{
|
base := &metricBase{
|
||||||
Identifier: id,
|
Identifier: id,
|
||||||
|
|
|
@ -2,7 +2,6 @@ package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -20,9 +19,6 @@ var (
|
||||||
metricNamespace string
|
metricNamespace string
|
||||||
globalLabels = make(map[string]string)
|
globalLabels = make(map[string]string)
|
||||||
|
|
||||||
pushURL string
|
|
||||||
metricInstance string
|
|
||||||
|
|
||||||
// ErrAlreadyStarted is returned when an operation is only valid before the
|
// ErrAlreadyStarted is returned when an operation is only valid before the
|
||||||
// first metric is registered, and is called after.
|
// first metric is registered, and is called after.
|
||||||
ErrAlreadyStarted = errors.New("can only be changed before first metric is registered")
|
ErrAlreadyStarted = errors.New("can only be changed before first metric is registered")
|
||||||
|
@ -36,29 +32,30 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.StringVar(&pushURL, "push-metrics", "", "URL to push prometheus metrics to")
|
|
||||||
flag.StringVar(&metricInstance, "metrics-instance", "", "Set the global instance label")
|
|
||||||
|
|
||||||
module = modules.Register("metrics", prep, start, stop, "database", "api")
|
module = modules.Register("metrics", prep, start, stop, "database", "api")
|
||||||
}
|
}
|
||||||
|
|
||||||
func prep() error {
|
func prep() error {
|
||||||
|
return prepConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() error {
|
||||||
// Add metric instance name as global variable if set.
|
// Add metric instance name as global variable if set.
|
||||||
if metricInstance != "" {
|
if instanceOption() != "" {
|
||||||
if err := AddGlobalLabel("instance", metricInstance); err != nil {
|
if err := AddGlobalLabel("instance", instanceOption()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return registerInfoMetric()
|
if err := registerInfoMetric(); err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func start() error {
|
|
||||||
if err := registerAPI(); err != nil {
|
if err := registerAPI(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pushURL != "" {
|
if pushOption() != "" {
|
||||||
module.StartServiceWorker("metric pusher", 0, metricsWriter)
|
module.StartServiceWorker("metric pusher", 0, metricsWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue