Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 10, 22:30 UTC
| 1 | package caddy |
| 2 | |
| 3 | import ( |
| 4 | "net/http" |
| 5 | |
| 6 | "github.com/prometheus/client_golang/prometheus" |
| 7 | |
| 8 | "github.com/caddyserver/caddy/v2/internal/metrics" |
| 9 | ) |
| 10 | |
| 11 | // define and register the metrics used in this package. |
| 12 | func init() { |
| 13 | const ns, sub = "caddy", "admin" |
| 14 | adminMetrics.requestCount = prometheus.NewCounterVec(prometheus.CounterOpts{ |
| 15 | Namespace: ns, |
| 16 | Subsystem: sub, |
| 17 | Name: "http_requests_total", |
| 18 | Help: "Counter of requests made to the Admin API's HTTP endpoints.", |
| 19 | }, []string{"handler", "path", "code", "method"}) |
| 20 | adminMetrics.requestErrors = prometheus.NewCounterVec(prometheus.CounterOpts{ |
| 21 | Namespace: ns, |
| 22 | Subsystem: sub, |
| 23 | Name: "http_request_errors_total", |
| 24 | Help: "Number of requests resulting in middleware errors.", |
| 25 | }, []string{"handler", "path", "method"}) |
| 26 | globalMetrics.configSuccess = prometheus.NewGauge(prometheus.GaugeOpts{ |
| 27 | Name: "caddy_config_last_reload_successful", |
| 28 | Help: "Whether the last configuration reload attempt was successful.", |
| 29 | }) |
| 30 | globalMetrics.configSuccessTime = prometheus.NewGauge(prometheus.GaugeOpts{ |
| 31 | Name: "caddy_config_last_reload_success_timestamp_seconds", |
| 32 | Help: "Timestamp of the last successful configuration reload.", |
| 33 | }) |
| 34 | } |
| 35 | |
| 36 | // adminMetrics is a collection of metrics that can be tracked for the admin API. |
| 37 | var adminMetrics = struct { |
| 38 | requestCount *prometheus.CounterVec |
| 39 | requestErrors *prometheus.CounterVec |
| 40 | }{} |
| 41 | |
| 42 | // globalMetrics is a collection of metrics that can be tracked for Caddy global state |
| 43 | var globalMetrics = struct { |
| 44 | configSuccess prometheus.Gauge |
| 45 | configSuccessTime prometheus.Gauge |
| 46 | }{} |
| 47 | |
| 48 | // Similar to promhttp.InstrumentHandlerCounter, but upper-cases method names |
| 49 | // instead of lower-casing them. |
| 50 | // |
| 51 | // Unlike promhttp.InstrumentHandlerCounter, this assumes a "code" and "method" |
| 52 | // label is present, and will panic otherwise. |
| 53 | func instrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { |
| 54 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 55 | d := newDelegator(w) |
| 56 | next.ServeHTTP(d, r) |
| 57 | counter.With(prometheus.Labels{ |
| 58 | "code": metrics.SanitizeCode(d.status), |
| 59 | "method": metrics.SanitizeMethod(r.Method), |
| 60 | }).Inc() |
| 61 | }) |
| 62 | } |
| 63 | |
| 64 | func newDelegator(w http.ResponseWriter) *delegator { |
| 65 | return &delegator{ |
| 66 | ResponseWriter: w, |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | type delegator struct { |
| 71 | http.ResponseWriter |
| 72 | status int |
| 73 | } |
| 74 | |
| 75 | func (d *delegator) WriteHeader(code int) { |
| 76 | d.status = code |
| 77 | d.ResponseWriter.WriteHeader(code) |
| 78 | } |
| 79 | |
| 80 | // Unwrap returns the underlying ResponseWriter, necessary for |
| 81 | // http.ResponseController to work correctly. |
| 82 | func (d *delegator) Unwrap() http.ResponseWriter { |
| 83 | return d.ResponseWriter |
| 84 | } |