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.

Commit 21b28c65 authored by Philipp Winter's avatar Philipp Winter
Browse files

Merge branch 'issue/10' into 'master'

Make metrics more idiomatic to Prometheus.

Closes #10

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