| 
									
										
										
										
											2020-09-17 14:01:20 -04:00
										 |  |  | package caddy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-09-22 22:10:34 -04:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-24 08:35:51 -05:00
										 |  |  | 	"github.com/caddyserver/caddy/v2/internal/metrics" | 
					
						
							| 
									
										
										
										
											2020-09-17 14:01:20 -04:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2021-06-04 00:19:16 -04:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus/collectors" | 
					
						
							| 
									
										
										
										
											2020-09-17 14:01:20 -04:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus/promauto" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // define and register the metrics used in this package. | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2021-06-04 00:19:16 -04:00
										 |  |  | 	prometheus.MustRegister(collectors.NewBuildInfoCollector()) | 
					
						
							| 
									
										
										
										
											2020-09-17 14:01:20 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	const ns, sub = "caddy", "admin" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	adminMetrics.requestCount = promauto.NewCounterVec(prometheus.CounterOpts{ | 
					
						
							|  |  |  | 		Namespace: ns, | 
					
						
							|  |  |  | 		Subsystem: sub, | 
					
						
							|  |  |  | 		Name:      "http_requests_total", | 
					
						
							|  |  |  | 		Help:      "Counter of requests made to the Admin API's HTTP endpoints.", | 
					
						
							|  |  |  | 	}, []string{"handler", "path", "code", "method"}) | 
					
						
							|  |  |  | 	adminMetrics.requestErrors = promauto.NewCounterVec(prometheus.CounterOpts{ | 
					
						
							|  |  |  | 		Namespace: ns, | 
					
						
							|  |  |  | 		Subsystem: sub, | 
					
						
							|  |  |  | 		Name:      "http_request_errors_total", | 
					
						
							|  |  |  | 		Help:      "Number of requests resulting in middleware errors.", | 
					
						
							|  |  |  | 	}, []string{"handler", "path", "method"}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // adminMetrics is a collection of metrics that can be tracked for the admin API. | 
					
						
							|  |  |  | var adminMetrics = struct { | 
					
						
							|  |  |  | 	requestCount  *prometheus.CounterVec | 
					
						
							|  |  |  | 	requestErrors *prometheus.CounterVec | 
					
						
							|  |  |  | }{} | 
					
						
							| 
									
										
										
										
											2020-09-22 22:10:34 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Similar to promhttp.InstrumentHandlerCounter, but upper-cases method names | 
					
						
							|  |  |  | // instead of lower-casing them. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Unlike promhttp.InstrumentHandlerCounter, this assumes a "code" and "method" | 
					
						
							|  |  |  | // label is present, and will panic otherwise. | 
					
						
							|  |  |  | func instrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler) http.HandlerFunc { | 
					
						
							|  |  |  | 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 
					
						
							|  |  |  | 		d := newDelegator(w) | 
					
						
							|  |  |  | 		next.ServeHTTP(d, r) | 
					
						
							|  |  |  | 		counter.With(prometheus.Labels{ | 
					
						
							| 
									
										
										
										
											2022-01-24 08:35:51 -05:00
										 |  |  | 			"code":   metrics.SanitizeCode(d.status), | 
					
						
							|  |  |  | 			"method": metrics.SanitizeMethod(r.Method), | 
					
						
							| 
									
										
										
										
											2020-09-22 22:10:34 -04:00
										 |  |  | 		}).Inc() | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newDelegator(w http.ResponseWriter) *delegator { | 
					
						
							|  |  |  | 	return &delegator{ | 
					
						
							|  |  |  | 		ResponseWriter: w, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type delegator struct { | 
					
						
							|  |  |  | 	http.ResponseWriter | 
					
						
							|  |  |  | 	status int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *delegator) WriteHeader(code int) { | 
					
						
							|  |  |  | 	d.status = code | 
					
						
							|  |  |  | 	d.ResponseWriter.WriteHeader(code) | 
					
						
							|  |  |  | } |