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  }