@@ -13,7 +13,8 @@ import (
1313 "github.com/cloudflare/cfssl/log"
1414 "github.com/cloudflare/cfssl/signer"
1515 "github.com/cloudflare/cfssl/whitelist"
16- metrics "github.com/cloudflare/go-metrics"
16+ "github.com/prometheus/client_golang/prometheus"
17+ "github.com/prometheus/client_golang/prometheus/promauto"
1718)
1819
1920// A SignatureResponse contains only a certificate, as there is no other
@@ -25,56 +26,36 @@ type SignatureResponse struct {
2526type filter func (string , * signer.SignRequest ) bool
2627
2728var filters = map [string ][]filter {}
29+ var (
30+ requests = promauto .NewCounterVec (
31+ prometheus.CounterOpts {
32+ Name : "requests_total" ,
33+ Help : "How many requests for each operation type and signer were succesfully processed." ,
34+ },
35+ []string {"operation" , "signer" },
36+ )
37+ erroredRequests = promauto .NewCounterVec (
38+ prometheus.CounterOpts {
39+ Name : "requests_errored_total" ,
40+ Help : "How many requests for each operation type resulted in an error." ,
41+ },
42+ []string {"operation" , "signer" },
43+ )
44+ badInputs = promauto .NewCounterVec (
45+ prometheus.CounterOpts {
46+ Name : "bad_inputs_total" ,
47+ Help : "How many times the input was malformed or not allowed." ,
48+ },
49+ []string {"operation" },
50+ )
51+ )
2852
29- type signerStats struct {
30- Counter metrics.Counter
31- Rate metrics.Meter
32- }
33-
34- var stats struct {
35- Registry metrics.Registry
36- Requests map [string ]signerStats
37- TotalRequestRate metrics.Meter
38- ErrorPercent metrics.GaugeFloat64
39- ErrorRate metrics.Meter
40- }
41-
42- func initStats () {
43- stats .Registry = metrics .NewRegistry ()
44-
45- stats .Requests = map [string ]signerStats {}
46-
47- // signers is defined in ca.go
48- for k := range signers {
49- stats .Requests [k ] = signerStats {
50- Counter : metrics .NewRegisteredCounter ("requests:" + k , stats .Registry ),
51- Rate : metrics .NewRegisteredMeter ("request-rate:" + k , stats .Registry ),
52- }
53- }
54-
55- stats .TotalRequestRate = metrics .NewRegisteredMeter ("total-request-rate" , stats .Registry )
56- stats .ErrorPercent = metrics .NewRegisteredGaugeFloat64 ("error-percent" , stats .Registry )
57- stats .ErrorRate = metrics .NewRegisteredMeter ("error-rate" , stats .Registry )
58- }
59-
60- // incError increments the error count and updates the error percentage.
61- func incErrors () {
62- stats .ErrorRate .Mark (1 )
63- eCtr := float64 (stats .ErrorRate .Count ())
64- rCtr := float64 (stats .TotalRequestRate .Count ())
65- stats .ErrorPercent .Update (eCtr / rCtr * 100 )
66- }
67-
68- // incRequests increments the request count and updates the error percentage.
69- func incRequests () {
70- stats .TotalRequestRate .Mark (1 )
71- eCtr := float64 (stats .ErrorRate .Count ())
72- rCtr := float64 (stats .TotalRequestRate .Count ())
73- stats .ErrorPercent .Update (eCtr / rCtr * 100 )
74- }
53+ const (
54+ signOperation = "sign"
55+ )
7556
7657func fail (w http.ResponseWriter , req * http.Request , status , code int , msg , ad string ) {
77- incErrors ()
58+ badInputs . WithLabelValues ( signOperation ). Inc ()
7859
7960 if ad != "" {
8061 ad = " (" + ad + ")"
@@ -95,8 +76,6 @@ func fail(w http.ResponseWriter, req *http.Request, status, code int, msg, ad st
9576}
9677
9778func dispatchRequest (w http.ResponseWriter , req * http.Request ) {
98- incRequests ()
99-
10079 if req .Method != "POST" {
10180 fail (w , req , http .StatusMethodNotAllowed , 1 , "only POST is permitted" , "" )
10281 return
@@ -146,10 +125,7 @@ func dispatchRequest(w http.ResponseWriter, req *http.Request) {
146125 fail (w , req , http .StatusBadRequest , 1 , "bad request" , "request is for non-existent label " + sigRequest .Label )
147126 return
148127 }
149-
150- stats .Requests [sigRequest .Label ].Counter .Inc (1 )
151- stats .Requests [sigRequest .Label ].Rate .Mark (1 )
152-
128+ requests .WithLabelValues (signOperation , sigRequest .Label ).Inc ()
153129 // Sanity checks to ensure that we have a valid policy. This
154130 // should have been checked in NewAuthSignHandler.
155131 policy := s .Policy ()
@@ -195,12 +171,14 @@ func dispatchRequest(w http.ResponseWriter, req *http.Request) {
195171
196172 cert , err := s .Sign (sigRequest )
197173 if err != nil {
174+ erroredRequests .WithLabelValues (signOperation , sigRequest .Label ).Inc ()
198175 fail (w , req , http .StatusBadRequest , 1 , "bad request" , "signature failed: " + err .Error ())
199176 return
200177 }
201178
202179 x509Cert , err := helpers .ParseCertificatePEM (cert )
203180 if err != nil {
181+ erroredRequests .WithLabelValues (signOperation , sigRequest .Label ).Inc ()
204182 fail (w , req , http .StatusInternalServerError , 1 , "bad certificate" , err .Error ())
205183 }
206184
@@ -219,22 +197,3 @@ func metricsDisallowed(w http.ResponseWriter, req *http.Request) {
219197 log .Warning ("attempt to access metrics endpoint from external address " , req .RemoteAddr )
220198 http .NotFound (w , req )
221199}
222-
223- func dumpMetrics (w http.ResponseWriter , req * http.Request ) {
224- log .Info ("whitelisted requested for metrics endpoint" )
225- var statsOut = struct {
226- Metrics metrics.Registry `json:"metrics"`
227- Signers []string `json:"signers"`
228- }{stats .Registry , make ([]string , 0 , len (signers ))}
229-
230- for signer := range signers {
231- statsOut .Signers = append (statsOut .Signers , signer )
232- }
233-
234- out , err := json .Marshal (statsOut )
235- if err != nil {
236- log .Errorf ("failed to dump metrics: %v" , err )
237- }
238-
239- w .Write (out )
240- }
0 commit comments