mirror of
https://github.com/safing/portbase
synced 2025-04-18 00:19:09 +00:00
Export metrics with values and also export values only
This commit is contained in:
parent
a34de1ce8e
commit
f2208faf8c
5 changed files with 137 additions and 13 deletions
|
@ -3,7 +3,6 @@ package metrics
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -17,20 +16,41 @@ import (
|
|||
func registerAPI() error {
|
||||
api.RegisterHandler("/metrics", &metricsAPI{})
|
||||
|
||||
return api.RegisterEndpoint(api.Endpoint{
|
||||
Path: "metrics/list",
|
||||
Read: api.PermitAnyone,
|
||||
MimeType: api.MimeTypeJSON,
|
||||
BelongsTo: module,
|
||||
DataFunc: func(*api.Request) ([]byte, error) {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
return json.Marshal(registry)
|
||||
},
|
||||
if err := api.RegisterEndpoint(api.Endpoint{
|
||||
Name: "Export Registered Metrics",
|
||||
Description: "List all registered metrics with their metadata.",
|
||||
})
|
||||
Path: "metrics/list",
|
||||
Read: api.Dynamic,
|
||||
BelongsTo: module,
|
||||
StructFunc: func(ar *api.Request) (any, error) {
|
||||
return ExportMetrics(ar.AuthToken.Read), nil
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := api.RegisterEndpoint(api.Endpoint{
|
||||
Name: "Export Metric Values",
|
||||
Description: "List all exportable metric values.",
|
||||
Path: "metrics/values",
|
||||
Read: api.Dynamic,
|
||||
Parameters: []api.Parameter{{
|
||||
Method: http.MethodGet,
|
||||
Field: "internal-only",
|
||||
Description: "Specify to only return metrics with an alternative internal ID.",
|
||||
}},
|
||||
BelongsTo: module,
|
||||
StructFunc: func(ar *api.Request) (any, error) {
|
||||
return ExportValues(
|
||||
ar.AuthToken.Read,
|
||||
ar.Request.URL.Query().Has("internal-only"),
|
||||
), nil
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type metricsAPI struct{}
|
||||
|
|
|
@ -42,3 +42,8 @@ func NewCounter(id string, labels map[string]string, opts *Options) (*Counter, e
|
|||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// CurrentValue returns the current counter value.
|
||||
func (c *Counter) CurrentValue() uint64 {
|
||||
return c.Get()
|
||||
}
|
||||
|
|
|
@ -50,6 +50,11 @@ func NewFetchingCounter(id string, labels map[string]string, fn func() uint64, o
|
|||
return m, nil
|
||||
}
|
||||
|
||||
// CurrentValue returns the current counter value.
|
||||
func (fc *FetchingCounter) CurrentValue() uint64 {
|
||||
return fc.fetchCnt()
|
||||
}
|
||||
|
||||
// WritePrometheus writes the metric in the prometheus format to the given writer.
|
||||
func (fc *FetchingCounter) WritePrometheus(w io.Writer) {
|
||||
fc.counter.Set(fc.fetchCnt())
|
||||
|
|
89
metrics/metric_export.go
Normal file
89
metrics/metric_export.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/safing/portbase/api"
|
||||
)
|
||||
|
||||
// UIntMetric is an interface for special functions of uint metrics.
|
||||
type UIntMetric interface {
|
||||
CurrentValue() uint64
|
||||
}
|
||||
|
||||
// FloatMetric is an interface for special functions of float metrics.
|
||||
type FloatMetric interface {
|
||||
CurrentValue() float64
|
||||
}
|
||||
|
||||
// MetricExport is used to export a metric and its current value.
|
||||
type MetricExport struct {
|
||||
Metric
|
||||
CurrentValue any
|
||||
}
|
||||
|
||||
// ExportMetrics exports all registered metrics.
|
||||
func ExportMetrics(requestPermission api.Permission) []*MetricExport {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
export := make([]*MetricExport, 0, len(registry))
|
||||
for _, metric := range registry {
|
||||
// Check permission.
|
||||
if requestPermission < metric.Opts().Permission {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add metric with current value.
|
||||
export = append(export, &MetricExport{
|
||||
Metric: metric,
|
||||
CurrentValue: getCurrentValue(metric),
|
||||
})
|
||||
}
|
||||
|
||||
return export
|
||||
}
|
||||
|
||||
// ExportValues exports the values of all supported metrics.
|
||||
func ExportValues(requestPermission api.Permission, internalOnly bool) map[string]any {
|
||||
registryLock.RLock()
|
||||
defer registryLock.RUnlock()
|
||||
|
||||
export := make(map[string]any, len(registry))
|
||||
for _, metric := range registry {
|
||||
// Check permission.
|
||||
if requestPermission < metric.Opts().Permission {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get Value.
|
||||
v := getCurrentValue(metric)
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get ID.
|
||||
var id string
|
||||
switch {
|
||||
case metric.Opts().InternalID != "":
|
||||
id = metric.Opts().InternalID
|
||||
case internalOnly:
|
||||
continue
|
||||
default:
|
||||
id = metric.LabeledID()
|
||||
}
|
||||
|
||||
// Add to export
|
||||
export[id] = v
|
||||
}
|
||||
|
||||
return export
|
||||
}
|
||||
|
||||
func getCurrentValue(metric Metric) any {
|
||||
if m, ok := metric.(UIntMetric); ok {
|
||||
return m.CurrentValue()
|
||||
}
|
||||
if m, ok := metric.(FloatMetric); ok {
|
||||
return m.CurrentValue()
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -39,3 +39,8 @@ func NewGauge(id string, labels map[string]string, fn func() float64, opts *Opti
|
|||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// CurrentValue returns the current gauge value.
|
||||
func (g *Gauge) CurrentValue() float64 {
|
||||
return g.Get()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue