blob: fdfb0c6070f972ccdcf7d22daae8feeab4d34f2b [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001// 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
15package v2http
16
17import (
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
30var (
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
57func init() {
58 prometheus.MustRegister(incomingEvents)
59 prometheus.MustRegister(failedEvents)
60 prometheus.MustRegister(successfulEventsHandlingTime)
61}
62
63func reportRequestReceived(request etcdserverpb.Request) {
64 incomingEvents.WithLabelValues(methodFromRequest(request)).Inc()
65}
66
67func 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
72func reportRequestFailed(request etcdserverpb.Request, err error) {
73 method := methodFromRequest(request)
74 failedEvents.WithLabelValues(method, strconv.Itoa(codeFromError(err))).Inc()
75}
76
77func methodFromRequest(request etcdserverpb.Request) string {
78 if request.Method == "GET" && request.Quorum {
79 return "QGET"
80 }
81 return request.Method
82}
83
84func 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}