Skip to content

Commit 0808d01

Browse files
The system info metrics now use OpenCensus (#1114)
1 parent 418797a commit 0808d01

File tree

8 files changed

+73
-66
lines changed

8 files changed

+73
-66
lines changed
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Enhancement: System information metrics cleanup
2+
3+
The system information metrics are now based on OpenCensus instead of the Prometheus client library. Furthermore, its initialization was moved out of the Prometheus HTTP service to keep things clean.
4+
5+
https://github.com/cs3org/reva/pull/1114

cmd/revad/main.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ func main() {
5353
flag.Parse()
5454

5555
// initialize the global system information
56-
sysinfo.InitSystemInfo(&sysinfo.RevaVersion{Version: version, BuildDate: buildDate, GitCommit: gitCommit, GoVersion: goVersion})
56+
if err := sysinfo.InitSystemInfo(&sysinfo.RevaVersion{Version: version, BuildDate: buildDate, GitCommit: gitCommit, GoVersion: goVersion}); err != nil {
57+
fmt.Fprintf(os.Stderr, "error initializing system info: %s\n", err.Error())
58+
// This is not really a fatal error, so don't panic
59+
}
5760

5861
handleVersionFlag()
5962
handleSignalFlag()

go.mod

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ require (
3636
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03 // indirect
3737
github.com/pkg/xattr v0.4.1
3838
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
39-
github.com/prometheus/client_golang v1.7.1
4039
github.com/rs/cors v1.7.0
4140
github.com/rs/zerolog v1.19.0
4241
github.com/stretchr/testify v1.6.1

go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
906906
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
907907
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA=
908908
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
909+
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
909910
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
910911
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
911912
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

internal/http/services/prometheus/prometheus.go

+1-14
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ import (
2424
"contrib.go.opencensus.io/exporter/prometheus"
2525
"github.com/mitchellh/mapstructure"
2626
"github.com/pkg/errors"
27-
promclient "github.com/prometheus/client_golang/prometheus"
2827
"github.com/rs/zerolog"
2928
"go.opencensus.io/stats/view"
3029

3130
"github.com/cs3org/reva/pkg/rhttp/global"
32-
"github.com/cs3org/reva/pkg/sysinfo"
33-
3431
// Initializes goroutines which periodically update stats
3532
_ "github.com/cs3org/reva/pkg/metrics/reader/dummy"
3633
)
@@ -48,23 +45,15 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error)
4845

4946
conf.init()
5047

51-
registry := promclient.NewRegistry() // A Prometheus registry shared by OpenCensus and SysInfo
5248
pe, err := prometheus.NewExporter(prometheus.Options{
5349
Namespace: "revad",
54-
Registry: registry,
5550
})
5651
if err != nil {
5752
return nil, errors.Wrap(err, "prometheus: error creating exporter")
5853
}
5954

60-
// Initialize the SysInfo Prometheus exporter
61-
sysinfo, err := sysinfo.NewPrometheusExporter(registry)
62-
if err != nil {
63-
return nil, errors.Wrap(err, "prometheus: unable to create system info exporter")
64-
}
65-
6655
view.RegisterExporter(pe)
67-
return &svc{prefix: conf.Prefix, h: pe, sysinfo: sysinfo}, nil
56+
return &svc{prefix: conf.Prefix, h: pe}, nil
6857
}
6958

7059
type config struct {
@@ -80,8 +69,6 @@ func (c *config) init() {
8069
type svc struct {
8170
prefix string
8271
h http.Handler
83-
84-
sysinfo *sysinfo.PrometheusExporter
8572
}
8673

8774
func (s *svc) Prefix() string {

pkg/sysinfo/prometheus.go renamed to pkg/sysinfo/metrics.go

+42-39
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,59 @@
1919
package sysinfo
2020

2121
import (
22+
"context"
2223
"fmt"
2324
"reflect"
2425
"strings"
2526

26-
"github.com/prometheus/client_golang/prometheus"
27+
"github.com/pkg/errors"
28+
"go.opencensus.io/stats"
29+
"go.opencensus.io/stats/view"
30+
"go.opencensus.io/tag"
2731

2832
"github.com/cs3org/reva/pkg/utils"
2933
)
3034

31-
// PrometheusExporter exports system information via Prometheus.
32-
type PrometheusExporter struct {
33-
registry *prometheus.Registry
34-
sysInfoMetric prometheus.GaugeFunc
35-
}
35+
type sysInfoMetricsLabels = map[tag.Key]string
36+
37+
func registerSystemInfoMetrics() error {
38+
labels := getSystemInfoMetricsLabels("", SysInfo)
39+
40+
// Collect all labels and their values; the values are stored as mutators
41+
tagKeys := make([]tag.Key, 0, len(labels))
42+
mutators := make([]tag.Mutator, 0, len(labels))
43+
for key, value := range labels {
44+
tagKeys = append(tagKeys, key)
45+
mutators = append(mutators, tag.Insert(key, value))
46+
}
47+
48+
// Create the OpenCensus statistics and a corresponding view
49+
sysInfoStats := stats.Int64("sys_info", "A metric with a constant '1' value labeled by various system information elements", stats.UnitDimensionless)
50+
sysInfoView := &view.View{
51+
Name: sysInfoStats.Name(),
52+
Description: sysInfoStats.Description(),
53+
Measure: sysInfoStats,
54+
TagKeys: tagKeys,
55+
Aggregation: view.LastValue(),
56+
}
57+
58+
if err := view.Register(sysInfoView); err != nil {
59+
return errors.Wrap(err, "unable to register the system info metrics view")
60+
}
3661

37-
func (psysinfo *PrometheusExporter) init(registry *prometheus.Registry) error {
38-
// Create all necessary Prometheus objects
39-
psysinfo.registry = registry
40-
psysinfo.sysInfoMetric = prometheus.NewGaugeFunc(
41-
prometheus.GaugeOpts{
42-
Namespace: "revad",
43-
Name: "sys_info",
44-
Help: "A metric with a constant '1' value labeled by various system information elements",
45-
ConstLabels: psysinfo.getLabels("", SysInfo),
46-
},
47-
func() float64 { return 1 },
48-
)
49-
50-
if err := psysinfo.registry.Register(psysinfo.sysInfoMetric); err != nil {
51-
return fmt.Errorf("unable to register the system information metrics: %v", err)
62+
// Create a new context to serve the metrics
63+
if ctx, err := tag.New(context.Background(), mutators...); err == nil {
64+
// Just record a simple hardcoded '1' to expose the system info as a metric
65+
stats.Record(ctx, sysInfoStats.M(1))
66+
} else {
67+
return errors.Wrap(err, "unable to create a context for the system info metrics")
5268
}
5369

5470
return nil
5571
}
5672

57-
func (psysinfo *PrometheusExporter) getLabels(root string, i interface{}) prometheus.Labels {
58-
labels := prometheus.Labels{}
73+
func getSystemInfoMetricsLabels(root string, i interface{}) sysInfoMetricsLabels {
74+
labels := sysInfoMetricsLabels{}
5975

6076
// Iterate over each field of the given interface, recursively collecting the values as labels
6177
v := reflect.ValueOf(i).Elem()
@@ -77,27 +93,14 @@ func (psysinfo *PrometheusExporter) getLabels(root string, i interface{}) promet
7793
f := v.Field(i)
7894
if f.Kind() == reflect.Struct || (f.Kind() == reflect.Ptr && f.Elem().Kind() == reflect.Struct) {
7995
// Merge labels recursively
80-
for key, val := range psysinfo.getLabels(fieldName, f.Interface()) {
96+
for key, val := range getSystemInfoMetricsLabels(fieldName, f.Interface()) {
8197
labels[key] = val
8298
}
8399
} else { // Store the value of the field in the labels
84-
labels[fieldName] = fmt.Sprintf("%v", f)
100+
key := tag.MustNewKey(fieldName)
101+
labels[key] = fmt.Sprintf("%v", f)
85102
}
86103
}
87104

88105
return labels
89106
}
90-
91-
// NewPrometheusExporter creates a new Prometheus system information exporter.
92-
func NewPrometheusExporter(registry *prometheus.Registry) (*PrometheusExporter, error) {
93-
if registry == nil {
94-
return nil, fmt.Errorf("no registry provided")
95-
}
96-
97-
exporter := &PrometheusExporter{}
98-
if err := exporter.init(registry); err != nil {
99-
return nil, err
100-
}
101-
102-
return exporter, nil
103-
}

pkg/sysinfo/reva.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ package sysinfo
2121
// RevaVersion stores version information about Reva.
2222
type RevaVersion struct {
2323
Version string `json:"version"`
24-
BuildDate string `json:"build_date" sysinfo:"omitlabel"`
24+
BuildDate string `json:"build_date"`
2525
GitCommit string `json:"git_commit" sysinfo:"omitlabel"`
2626
GoVersion string `json:"go_version" sysinfo:"omitlabel"`
2727
}

pkg/sysinfo/sysinfo.go

+19-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"encoding/json"
2323
"fmt"
2424
"reflect"
25+
26+
"github.com/pkg/errors"
2527
)
2628

2729
// SystemInformation stores general information about Reva and the system it's running on.
@@ -44,16 +46,6 @@ func (sysInfo *SystemInformation) ToJSON() (string, error) {
4446
return string(data), nil
4547
}
4648

47-
// InitSystemInfo initializes the global system information object.
48-
func InitSystemInfo(revaVersion *RevaVersion) {
49-
SysInfo = &SystemInformation{
50-
Reva: revaVersion,
51-
}
52-
53-
// Replace any empty values in the system information by more meaningful ones
54-
replaceEmptyInfoValues(SysInfo)
55-
}
56-
5749
func replaceEmptyInfoValues(i interface{}) {
5850
// Iterate over each field of the given interface and search for "empty" values
5951
v := reflect.ValueOf(i).Elem()
@@ -71,3 +63,20 @@ func replaceEmptyInfoValues(i interface{}) {
7163
}
7264
}
7365
}
66+
67+
// InitSystemInfo initializes the global system information object and also registers the corresponding metrics.
68+
func InitSystemInfo(revaVersion *RevaVersion) error {
69+
SysInfo = &SystemInformation{
70+
Reva: revaVersion,
71+
}
72+
73+
// Replace any empty values in the system information by more meaningful ones
74+
replaceEmptyInfoValues(SysInfo)
75+
76+
// Register the system information metrics, as the necessary system info object has been filled out
77+
if err := registerSystemInfoMetrics(); err != nil {
78+
return errors.Wrap(err, "unable to register the system info metrics")
79+
}
80+
81+
return nil
82+
}

0 commit comments

Comments
 (0)