Skip to content
This repository has been archived by the owner on Dec 20, 2024. It is now read-only.

Commit

Permalink
add build_info metrics
Browse files Browse the repository at this point in the history
Signed-off-by: yeya24 <[email protected]>
  • Loading branch information
yeya24 committed Jul 18, 2019
1 parent 82ccf80 commit 09594c5
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 27 deletions.
5 changes: 4 additions & 1 deletion dfdaemon/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
"github.com/dragonflyoss/Dragonfly/dfdaemon/config"
"github.com/dragonflyoss/Dragonfly/dfdaemon/handler"
"github.com/dragonflyoss/Dragonfly/dfdaemon/proxy"
"github.com/sirupsen/logrus"
"github.com/dragonflyoss/Dragonfly/version"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)

// Server represents the dfdaemon server
Expand Down Expand Up @@ -104,6 +105,8 @@ func (s *Server) Start() error {
} else {
logrus.Infof("start dfdaemon http server on %s", s.server.Addr)
}
// register dfdaemon build information
version.NewBuildInfo("dfdaemon")
return s.server.ListenAndServe()
}

Expand Down
19 changes: 19 additions & 0 deletions docs/user_guide/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Prometheus Metrics

This doc contains all the metrics that Dragonfly components currently support. Now we only support metrics for Dfdaemon and SuperNode. And we will support dfget metrics in the future. For Dfdaemon and SuperNode, the metrics path is fixed to /metrics. The following metrics are exported.

## Supernode

- dragonfly_supernode_build_info{version, revision, goversion, arch, os} - build and version information of supernode
- dragonfly_supernode_http_requests_total{code, handler, method} - total number of http requests
- dragonfly_supernode_http_request_duration_seconds{code, handler, method} - http request latency in seconds
- dragonfly_supernode_http_request_size_bytes{code, handler, method} - http request size in bytes
- dragonfly_supernode_http_response_size_bytes{code, handler, method} - http response size in bytes

## Dfdaemon

- dragonfly_dfdaemon_build_info{version, revision, goversion, arch, os} - build and version information of dfdaemon

## Dfget

TODO
2 changes: 1 addition & 1 deletion docs/user_guide/monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Currently metrics become an important part of observability. As for monitoring Dragonfly, we recommend you to use Prometheus.

In Dragonfly project, there are two long-running process: supernode and dfdaemon. Both of these two components expose its metrics via `/metrics` endpoint, so Prometheus can get metrics from these two components. We will also support dfget metrics in the future. As for current metrics, you can check out this docs.
In Dragonfly project, there are two long-running processes: supernode and dfdaemon. Each of the components expose its metrics via `/metrics` endpoint, so Prometheus can get metrics from each component. We will also support dfget metrics in the future. As for current metrics, you can check out [metrics](metrics.md).

## How to set up Prometheus

Expand Down
4 changes: 2 additions & 2 deletions supernode/server/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ func newMetrics() *metrics {
prometheus.HistogramOpts{
Namespace: config.Namespace,
Subsystem: config.Subsystem,
Name: "http_request_size_bytes",
Help: "Histogram of request size for HTTP requests.",
Name: "http_request_size_bytes",
Help: "Histogram of request size for HTTP requests.",
Buckets: prometheus.ExponentialBuckets(100, 10, 8),
},
[]string{"code", "handler", "method"},
Expand Down
6 changes: 3 additions & 3 deletions supernode/server/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package server

import (
"encoding/json"
"github.com/gorilla/mux"
"io/ioutil"
"math/rand"
"net"
Expand All @@ -18,6 +17,7 @@ import (
"github.com/dragonflyoss/Dragonfly/version"

"github.com/go-check/check"
"github.com/gorilla/mux"
prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
)

Expand Down Expand Up @@ -122,13 +122,13 @@ func (rs *RouterTestSuite) TestHTTPMetrics(c *check.C) {

counter := m.requestCounter
c.Assert(1, check.Equals,
int(prom_testutil.ToFloat64(counter.WithLabelValues("/metrics", strconv.Itoa(http.StatusOK)))))
int(prom_testutil.ToFloat64(counter.WithLabelValues(strconv.Itoa(http.StatusOK), "/metrics", "get"))))

for i := 0; i < 5; i++ {
code, _, err := cutil.Get("http://"+rs.addr+"/_ping", 0)
c.Check(err, check.IsNil)
c.Assert(code, check.Equals, 200)
c.Assert(i+1, check.Equals,
int(prom_testutil.ToFloat64(counter.WithLabelValues("/_ping", strconv.Itoa(http.StatusOK)))))
int(prom_testutil.ToFloat64(counter.WithLabelValues(strconv.Itoa(http.StatusOK), "/_ping", "get"))))
}
}
7 changes: 5 additions & 2 deletions supernode/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import (
"github.com/dragonflyoss/Dragonfly/supernode/daemon/mgr/scheduler"
"github.com/dragonflyoss/Dragonfly/supernode/daemon/mgr/task"
"github.com/dragonflyoss/Dragonfly/supernode/store"
"github.com/dragonflyoss/Dragonfly/version"

"github.com/sirupsen/logrus"
)

// Server is server instance.
// Server is supernode server struct.
type Server struct {
Config *config.Config
PeerMgr mgr.PeerMgr
Expand Down Expand Up @@ -78,7 +79,7 @@ func New(cfg *config.Config) (*Server, error) {
}, nil
}

// Start runs
// Start runs supernode server.
func (s *Server) Start() error {
router := initRoute(s)

Expand All @@ -90,6 +91,8 @@ func (s *Server) Start() error {
return err
}

// register supernode build information
version.NewBuildInfo("supernode")
server := &http.Server{
Handler: router,
ReadTimeout: time.Minute * 10,
Expand Down
23 changes: 11 additions & 12 deletions test/api_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,21 @@ func (s *APIMetricsSuite) TestHttpMetrics(c *check.C) {
CheckRespStatus(c, resp, 200)

// Get httpRequest counter value equals 1.
pingTimes, found := GetMetricValue(c, fmt.Sprintf(requestCounter, 200, "/_ping", "get"))
c.Assert(found, check.Equals, true)
c.Assert(pingTimes, check.Equals, float64(1))
CheckMetric(c, fmt.Sprintf(requestCounter, 200, "/_ping", "get"), 1)

// Get httpResponse size sum value equals 2.
responseBytes, found := GetMetricValue(c, fmt.Sprintf(responseSizeSum, 200, "/_ping", "get"))
c.Assert(found, check.Equals, true)
c.Assert(responseBytes, check.Equals, float64(2))
CheckMetric(c, fmt.Sprintf(responseSizeSum, 200, "/_ping", "get"), 2)

// Get httpResponse size count value equals 1.
responseCount, found := GetMetricValue(c, fmt.Sprintf(responseSizeCount, 200, "/_ping", "get"))
c.Assert(found, check.Equals, true)
c.Assert(responseCount, check.Equals, float64(1))
CheckMetric(c, fmt.Sprintf(responseSizeCount, 200, "/_ping", "get"), 1)

// Get httpRequest size count value equals 1.
requestCount, found := GetMetricValue(c, fmt.Sprintf(requestSizeCount, 200, "/_ping", "get"))
c.Assert(found, check.Equals, true)
c.Assert(requestCount, check.Equals, float64(1))
CheckMetric(c, fmt.Sprintf(requestSizeCount, 200, "/_ping", "get"), 1)
}

// TestBuildInfoMetrics tests build info metric.
func (s *APIMetricsSuite) TestBuildInfoMetrics(c *check.C) {
supernodeBuildInfo := `dragonfly_supernode_build_info{`
// Ensure build_info metric exists.
CheckMetric(c, supernodeBuildInfo, 1)
}
14 changes: 8 additions & 6 deletions test/util_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ func CheckRespStatus(c *check.C, resp *http.Response, status int) {
}
}

// GetMetricValue get the specific metrics from /metrics endpoint,
// if cannot find this metrics, return not found.
func GetMetricValue(c *check.C, key string) (float64, bool) {
// CheckMetric find the specific metric from /metrics endpoint and it will compare the metric
// value with expected value.
func CheckMetric(c *check.C, metric string, value float64) {
var val float64
resp, err := request.Get("/metrics")
c.Assert(err, check.IsNil)
Expand All @@ -31,12 +31,14 @@ func GetMetricValue(c *check.C, key string) (float64, bool) {
c.Assert(err, check.IsNil)
lines := strings.Split(string(data), "\n")
for _, line := range lines {
if strings.Contains(line, key) {
if strings.Contains(line, metric) {
val, err = strconv.ParseFloat(strings.Split(line, " ")[1], 64)
c.Assert(err, check.IsNil)
return val, true
c.Assert(val, check.Equals, value)
return
}
}

return val, false
// Cannot find expected metric and fail the test.
c.FailNow()
}
20 changes: 20 additions & 0 deletions version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import (
"strings"
"text/template"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"

"github.com/dragonflyoss/Dragonfly/apis/types"
)

Expand Down Expand Up @@ -104,6 +107,23 @@ func Print(program string) string {
return strings.TrimSpace(buf.String())
}

// NewBuildInfo register a collector which exports metrics about version and build information.
func NewBuildInfo(program string) {
buildInfo := promauto.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: "dragonfly",
Subsystem: program,
Name: "build_info",
Help: fmt.Sprintf(
"A metric with a constant '1' value labeled by version, revision, os, arch and goversion from which %s was built.",
program,
),
},
[]string{"version", "revision", "os", "arch", "goversion"},
)
buildInfo.WithLabelValues(version, revision, os, arch, goVersion).Set(1)
}

// Handler returns build information
func Handler(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(DFVersion)
Expand Down

0 comments on commit 09594c5

Please sign in to comment.