go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/api/v2http/metrics.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package v2http 16 17 import ( 18 "strconv" 19 "time" 20 21 "net/http" 22 23 etcdErr "github.com/coreos/etcd/error" 24 "github.com/coreos/etcd/etcdserver" 25 "github.com/coreos/etcd/etcdserver/api/v2http/httptypes" 26 "github.com/coreos/etcd/etcdserver/etcdserverpb" 27 "github.com/prometheus/client_golang/prometheus" 28 ) 29 30 var ( 31 incomingEvents = prometheus.NewCounterVec( 32 prometheus.CounterOpts{ 33 Namespace: "etcd", 34 Subsystem: "http", 35 Name: "received_total", 36 Help: "Counter of requests received into the system (successfully parsed and authd).", 37 }, []string{"method"}) 38 39 failedEvents = prometheus.NewCounterVec( 40 prometheus.CounterOpts{ 41 Namespace: "etcd", 42 Subsystem: "http", 43 Name: "failed_total", 44 Help: "Counter of handle failures of requests (non-watches), by method (GET/PUT etc.) and code (400, 500 etc.).", 45 }, []string{"method", "code"}) 46 47 successfulEventsHandlingTime = prometheus.NewHistogramVec( 48 prometheus.HistogramOpts{ 49 Namespace: "etcd", 50 Subsystem: "http", 51 Name: "successful_duration_seconds", 52 Help: "Bucketed histogram of processing time (s) of successfully handled requests (non-watches), by method (GET/PUT etc.).", 53 Buckets: prometheus.ExponentialBuckets(0.0005, 2, 13), 54 }, []string{"method"}) 55 ) 56 57 func init() { 58 prometheus.MustRegister(incomingEvents) 59 prometheus.MustRegister(failedEvents) 60 prometheus.MustRegister(successfulEventsHandlingTime) 61 } 62 63 func reportRequestReceived(request etcdserverpb.Request) { 64 incomingEvents.WithLabelValues(methodFromRequest(request)).Inc() 65 } 66 67 func reportRequestCompleted(request etcdserverpb.Request, response etcdserver.Response, startTime time.Time) { 68 method := methodFromRequest(request) 69 successfulEventsHandlingTime.WithLabelValues(method).Observe(time.Since(startTime).Seconds()) 70 } 71 72 func reportRequestFailed(request etcdserverpb.Request, err error) { 73 method := methodFromRequest(request) 74 failedEvents.WithLabelValues(method, strconv.Itoa(codeFromError(err))).Inc() 75 } 76 77 func methodFromRequest(request etcdserverpb.Request) string { 78 if request.Method == "GET" && request.Quorum { 79 return "QGET" 80 } 81 return request.Method 82 } 83 84 func codeFromError(err error) int { 85 if err == nil { 86 return http.StatusInternalServerError 87 } 88 switch e := err.(type) { 89 case *etcdErr.Error: 90 return (*etcdErr.Error)(e).StatusCode() 91 case *httptypes.HTTPError: 92 return (*httptypes.HTTPError)(e).Code 93 default: 94 return http.StatusInternalServerError 95 } 96 }