mirror of
https://github.com/openfaas/faas.git
synced 2025-06-10 09:16:48 +00:00
- splits out notifiers and writes status for async handler Signed-off-by: Alex Ellis (VMware) <alexellis2@gmail.com>
92 lines
2.8 KiB
Go
92 lines
2.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/openfaas/faas/gateway/metrics"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
)
|
|
|
|
// HTTPNotifier notify about HTTP request/response
|
|
type HTTPNotifier interface {
|
|
Notify(method string, URL string, originalURL string, statusCode int, duration time.Duration)
|
|
}
|
|
|
|
// PrometheusServiceNotifier notifier for core service endpoints
|
|
type PrometheusServiceNotifier struct {
|
|
ServiceMetrics *metrics.ServiceMetricOptions
|
|
}
|
|
|
|
// Notify about service metrics
|
|
func (psn PrometheusServiceNotifier) Notify(method string, URL string, originalURL string, statusCode int, duration time.Duration) {
|
|
code := fmt.Sprintf("%d", statusCode)
|
|
path := urlToLabel(URL)
|
|
psn.ServiceMetrics.Counter.WithLabelValues(code, method, path).Inc()
|
|
psn.ServiceMetrics.Histogram.WithLabelValues(method, path, code).Observe(duration.Seconds())
|
|
}
|
|
|
|
var invalidChars = regexp.MustCompile(`[^a-zA-Z0-9]+`)
|
|
|
|
// converts a URL path to a string compatible with Prometheus label value.
|
|
func urlToLabel(path string) string {
|
|
result := invalidChars.ReplaceAllString(path, "_")
|
|
result = strings.ToLower(strings.Trim(result, "_"))
|
|
if result == "" {
|
|
result = "root"
|
|
}
|
|
return result
|
|
}
|
|
|
|
// PrometheusFunctionNotifier records metrics to Prometheus
|
|
type PrometheusFunctionNotifier struct {
|
|
Metrics *metrics.MetricOptions
|
|
}
|
|
|
|
// Notify records metrics in Prometheus
|
|
func (p PrometheusFunctionNotifier) Notify(method string, URL string, originalURL string, statusCode int, duration time.Duration) {
|
|
seconds := duration.Seconds()
|
|
serviceName := getServiceName(originalURL)
|
|
|
|
p.Metrics.GatewayFunctionsHistogram.
|
|
WithLabelValues(serviceName).
|
|
Observe(seconds)
|
|
|
|
code := strconv.Itoa(statusCode)
|
|
|
|
p.Metrics.GatewayFunctionInvocation.
|
|
With(prometheus.Labels{"function_name": serviceName, "code": code}).
|
|
Inc()
|
|
}
|
|
|
|
func getServiceName(urlValue string) string {
|
|
var serviceName string
|
|
forward := "/function/"
|
|
if strings.HasPrefix(urlValue, forward) {
|
|
// With a path like `/function/xyz/rest/of/path?q=a`, the service
|
|
// name we wish to locate is just the `xyz` portion. With a postive
|
|
// match on the regex below, it will return a three-element slice.
|
|
// The item at index `0` is the same as `urlValue`, at `1`
|
|
// will be the service name we need, and at `2` the rest of the path.
|
|
matcher := functionMatcher.Copy()
|
|
matches := matcher.FindStringSubmatch(urlValue)
|
|
if len(matches) == hasPathCount {
|
|
serviceName = matches[nameIndex]
|
|
}
|
|
}
|
|
return strings.Trim(serviceName, "/")
|
|
}
|
|
|
|
// LoggingNotifier notifies a log about a request
|
|
type LoggingNotifier struct {
|
|
}
|
|
|
|
// Notify a log about a request
|
|
func (LoggingNotifier) Notify(method string, URL string, originalURL string, statusCode int, duration time.Duration) {
|
|
log.Printf("Forwarded [%s] to %s - [%d] - %f seconds", method, originalURL, statusCode, duration.Seconds())
|
|
}
|