GitLab is used only for code review, issue tracking and project management. Canonical locations for source code are still https://gitweb.torproject.org/ https://git.torproject.org/ and git-rw.torproject.org.

Verified Commit e3135a66 authored by Philipp Winter's avatar Philipp Winter
Browse files

Make metrics more idiomatic to Prometheus.

Our metrics aren't implemented in the way Prometheus recommends.  This
patch makes use of labels and renames our metrics to change that.  For
example, instead of having two metrics called cache_hits and
cache_misses, we now have a single metric called cache_total and it
accepts a "type" label that can take on the values "hit" or "miss".

This patch fixes #10.
parent 76dfe653
......@@ -10,6 +10,7 @@ import (
"path"
"time"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/time/rate"
)
......@@ -99,14 +100,14 @@ func testBridgeLines(req *TestRequest) *TestResult {
for _, bridgeLine := range req.BridgeLines {
if entry := cache.IsCached(bridgeLine); entry != nil {
numCached++
metrics.CacheHits.Inc()
metrics.Cache.With(prometheus.Labels{"type": "hit"}).Inc()
result.Bridges[bridgeLine] = &BridgeTest{
Functional: entry.Error == "",
LastTested: entry.Time,
Error: entry.Error,
}
} else {
metrics.CacheMisses.Inc()
metrics.Cache.With(prometheus.Labels{"type": "miss"}).Inc()
remainingBridgeLines = append(remainingBridgeLines, bridgeLine)
}
}
......@@ -127,9 +128,9 @@ func testBridgeLines(req *TestRequest) *TestResult {
for bridgeLine, bridgeTest := range partialResult.Bridges {
cache.AddEntry(bridgeLine, errors.New(bridgeTest.Error), bridgeTest.LastTested)
if bridgeTest.Functional {
metrics.NumFunctionalBridges.Inc()
metrics.BridgeStatus.With(prometheus.Labels{"status": "functional"}).Inc()
} else {
metrics.NumDysfunctionalBridges.Inc()
metrics.BridgeStatus.With(prometheus.Labels{"status": "dysfunctional"}).Inc()
}
result.Bridges[bridgeLine] = bridgeTest
}
......@@ -160,7 +161,11 @@ func testBridgeLines(req *TestRequest) *TestResult {
func BridgeState(w http.ResponseWriter, r *http.Request) {
metrics.ApiNumRequests.Inc()
reqStatus := "invalid"
defer func() {
metrics.Requests.With(prometheus.Labels{"type": "api", "status": reqStatus}).Inc()
}()
b, err := ioutil.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
......@@ -181,8 +186,8 @@ func BridgeState(w http.ResponseWriter, r *http.Request) {
http.Error(w, "no bridge lines given", http.StatusBadRequest)
return
}
reqStatus = "valid"
metrics.ApiNumValidRequests.Inc()
if len(req.BridgeLines) > MaxBridgesPerReq {
log.Printf("Got %d bridges in request but we only allow <= %d.", len(req.BridgeLines), MaxBridgesPerReq)
http.Error(w, fmt.Sprintf("maximum of %d bridge lines allowed", MaxBridgesPerReq), http.StatusBadRequest)
......@@ -203,7 +208,11 @@ func BridgeState(w http.ResponseWriter, r *http.Request) {
func BridgeStateWeb(w http.ResponseWriter, r *http.Request) {
metrics.WebNumRequests.Inc()
reqStatus := "invalid"
defer func() {
metrics.Requests.With(prometheus.Labels{"type": "web", "status": reqStatus}).Inc()
}()
r.ParseForm()
// Rate-limit Web requests to prevent someone from abusing this service
// as a port scanner.
......@@ -216,8 +225,8 @@ func BridgeStateWeb(w http.ResponseWriter, r *http.Request) {
SendHtmlResponse(w, "No bridge line given.")
return
}
reqStatus = "valid"
metrics.WebNumValidRequests.Inc()
result := testBridgeLines(&TestRequest{BridgeLines: []string{bridgeLine}})
bridgeResult, exists := result.Bridges[bridgeLine]
if !exists {
......
......@@ -10,19 +10,14 @@ const (
)
type Metrics struct {
OrconnLaunched prometheus.Counter
CacheHits prometheus.Counter
CacheMisses prometheus.Counter
CacheSize prometheus.Gauge
PendingReqs prometheus.Gauge
FracFunctional prometheus.Gauge
ApiNumRequests prometheus.Counter
ApiNumValidRequests prometheus.Counter
WebNumRequests prometheus.Counter
WebNumValidRequests prometheus.Counter
NumFunctionalBridges prometheus.Counter
NumDysfunctionalBridges prometheus.Counter
TorTestTime prometheus.Histogram
OrconnLaunched prometheus.Counter
CacheSize prometheus.Gauge
PendingReqs prometheus.Gauge
FracFunctional prometheus.Gauge
TorTestTime prometheus.Histogram
Cache *prometheus.CounterVec
Requests *prometheus.CounterVec
BridgeStatus *prometheus.CounterVec
}
var metrics *Metrics
......@@ -50,59 +45,38 @@ func InitMetrics() {
Help: "The fraction of functional bridges currently in the cache",
})
metrics.CacheHits = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "cache_hits",
Help: "The number of requests that hit the cache",
})
metrics.CacheMisses = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "cache_misses",
Help: "The number of requests that missed the cache",
})
metrics.CacheSize = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: PrometheusNamespace,
Name: "cache_size",
Help: "The number of cached elements",
})
metrics.ApiNumRequests = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "api_num_requests",
Help: "The number of API requests",
})
metrics.ApiNumValidRequests = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "api_num_validrequests",
Help: "The number of valid API requests",
})
metrics.WebNumRequests = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "web_num_requests",
Help: "The number of Web requests",
})
metrics.WebNumValidRequests = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "web_num_valid_requests",
Help: "The number of valid Web requests",
})
metrics.NumFunctionalBridges = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "num_functional_bridges",
Help: "The number of functional bridges",
})
metrics.NumDysfunctionalBridges = promauto.NewCounter(prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "num_dysfunctional_bridges",
Help: "The number of dysfunctional bridges",
})
metrics.Cache = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "cache_total",
Help: "The number of cache hits and misses",
},
[]string{"type"},
)
metrics.Requests = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "requests_total",
Help: "The type and status of requests",
},
[]string{"type", "status"},
)
metrics.BridgeStatus = promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: PrometheusNamespace,
Name: "bridge_status_total",
Help: "The number of functional and dysfunctional bridges",
},
[]string{"status"},
)
buckets := []float64{}
TorTestTimeout.Seconds()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment