Skip to content

Commit

Permalink
Merged the SysInfo Prometheus exporter into the existing Prometheus s…
Browse files Browse the repository at this point in the history
…ervice (cs3org#1071)
  • Loading branch information
Daniel-WWU-IT authored and glpatcern committed Aug 24, 2020
1 parent 3597b26 commit e8b21a4
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 43 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/sysinfo-prometheus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: System information included in Prometheus metrics

System information is now included in the main Prometheus metrics exposed at `/metrics`.

https://github.com/cs3org/reva/pull/1071
17 changes: 15 additions & 2 deletions internal/http/services/prometheus/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ import (
"net/http"

"contrib.go.opencensus.io/exporter/prometheus"
"github.com/cs3org/reva/pkg/rhttp/global"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
promclient "github.com/prometheus/client_golang/prometheus"
"github.com/rs/zerolog"
"go.opencensus.io/stats/view"

"github.com/cs3org/reva/pkg/rhttp/global"
"github.com/cs3org/reva/pkg/sysinfo"

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

conf.init()

registry := promclient.NewRegistry() // A Prometheus registry shared by OpenCensus and SysInfo
pe, err := prometheus.NewExporter(prometheus.Options{
Namespace: "revad",
Registry: registry,
})
if err != nil {
return nil, errors.Wrap(err, "prometheus: error creating exporter")
}

// Initialize the SysInfo Prometheus exporter
sysinfo, err := sysinfo.NewPrometheusExporter(registry)
if err != nil {
return nil, errors.Wrap(err, "prometheus: unable to create system info exporter")
}

view.RegisterExporter(pe)
return &svc{prefix: conf.Prefix, h: pe}, nil
return &svc{prefix: conf.Prefix, h: pe, sysinfo: sysinfo}, nil
}

type config struct {
Expand All @@ -69,6 +80,8 @@ func (c *config) init() {
type svc struct {
prefix string
h http.Handler

sysinfo *sysinfo.PrometheusExporter
}

func (s *svc) Prefix() string {
Expand Down
33 changes: 4 additions & 29 deletions internal/http/services/sysinfo/sysinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package sysinfo

import (
"net/http"
"strings"

"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
Expand All @@ -41,8 +40,6 @@ type config struct {

type svc struct {
conf *config

promHandler *prometheusSysInfoHandler
}

const (
Expand All @@ -67,24 +64,9 @@ func (s *svc) Unprotected() []string {
// Handler serves all HTTP requests.
func (s *svc) Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt := strings.ToLower(r.URL.Query().Get("format"))
if len(fmt) == 0 {
// No format was specified, so let Prometheus handle the request
s.promHandler.httpHandler.ServeHTTP(w, r)
} else {
// Otherwise, provide the system information in the requested format
data := ""
switch fmt {
case "json":
data = s.getJSONData()
default:
data = "Unsupported format"
}

log := appctx.GetLogger(r.Context())
if _, err := w.Write([]byte(data)); err != nil {
log.Err(err).Msg("error writing SysInfo response")
}
log := appctx.GetLogger(r.Context())
if _, err := w.Write([]byte(s.getJSONData())); err != nil {
log.Err(err).Msg("error writing SysInfo response")
}
})
}
Expand Down Expand Up @@ -120,16 +102,9 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error)
return nil, err
}

// Create the Prometheus system information handler
promHandler := &prometheusSysInfoHandler{}
if err := promHandler.init(); err != nil {
return nil, err
}

// Create the service
s := &svc{
conf: conf,
promHandler: promHandler,
conf: conf,
}
return s, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,46 +20,41 @@ package sysinfo

import (
"fmt"
"net/http"
"reflect"
"strings"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"

"github.com/cs3org/reva/pkg/sysinfo"
"github.com/cs3org/reva/pkg/utils"
)

type prometheusSysInfoHandler struct {
// PrometheusExporter exports system information via Prometheus.
type PrometheusExporter struct {
registry *prometheus.Registry
sysInfoMetric prometheus.GaugeFunc

httpHandler http.Handler
}

func (psysinfo *prometheusSysInfoHandler) init() error {
func (psysinfo *PrometheusExporter) init(registry *prometheus.Registry) error {
// Create all necessary Prometheus objects
psysinfo.registry = prometheus.NewRegistry()
psysinfo.registry = registry
psysinfo.sysInfoMetric = prometheus.NewGaugeFunc(
prometheus.GaugeOpts{
Namespace: "revad",
Name: "sys_info",
Help: "A metric with a constant '1' value labeled by various system information elements",
ConstLabels: psysinfo.getLabels("", sysinfo.SysInfo),
ConstLabels: psysinfo.getLabels("", SysInfo),
},
func() float64 { return 1 },
)
psysinfo.httpHandler = promhttp.HandlerFor(psysinfo.registry, promhttp.HandlerOpts{})

if err := psysinfo.registry.Register(psysinfo.sysInfoMetric); err != nil {
return fmt.Errorf("unable to register the system information metric: %v", err)
return fmt.Errorf("unable to register the system information metrics: %v", err)
}

return nil
}

func (psysinfo *prometheusSysInfoHandler) getLabels(root string, i interface{}) prometheus.Labels {
func (psysinfo *PrometheusExporter) getLabels(root string, i interface{}) prometheus.Labels {
labels := prometheus.Labels{}

// Iterate over each field of the given interface, recursively collecting the values as labels
Expand Down Expand Up @@ -92,3 +87,17 @@ func (psysinfo *prometheusSysInfoHandler) getLabels(root string, i interface{})

return labels
}

// NewPrometheusExporter creates a new Prometheus system information exporter.
func NewPrometheusExporter(registry *prometheus.Registry) (*PrometheusExporter, error) {
if registry == nil {
return nil, fmt.Errorf("no registry provided")
}

exporter := &PrometheusExporter{}
if err := exporter.init(registry); err != nil {
return nil, err
}

return exporter, nil
}

0 comments on commit e8b21a4

Please sign in to comment.