pomerium/internal/metrics/middleware.go
2019-07-13 18:28:51 -07:00

151 lines
6 KiB
Go

package metrics // import "github.com/pomerium/pomerium/internal/metrics"
import (
"net/http"
"go.opencensus.io/plugin/ochttp"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/tripper"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
)
var (
httpSizeDistribution = view.Distribution(
1, 256, 512, 1024, 2048, 8192, 16384, 32768, 65536, 131072, 262144, 524288,
1048576, 2097152, 4194304, 8388608,
)
httpLatencyDistrubtion = view.Distribution(
1, 2, 5, 7, 10, 25, 500, 750,
100, 250, 500, 750,
1000, 2500, 5000, 7500,
10000, 25000, 50000, 75000,
100000,
)
// httpClientRequestCount = stats.Int64("http_client_requests_total", "Total HTTP Client Requests", "1")
// httpClientResponseSize = stats.Int64("http_client_response_size_bytes", "HTTP Client Response Size in bytes", "bytes")
// httpClientRequestDuration = stats.Int64("http_client_request_duration_ms", "HTTP Client Request duration in ms", "ms")
// HTTPServerRequestCountView is an OpenCensus View that tracks HTTP server requests by pomerium service, host, method and status
HTTPServerRequestCountView = &view.View{
Name: "http_server_requests_total",
Measure: ochttp.ServerLatency,
Description: "Total HTTP Requests",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, ochttp.StatusCode},
Aggregation: view.Count(),
}
// HTTPServerRequestDurationView is an OpenCensus view that tracks HTTP server request duration by pomerium service, host, method and status
HTTPServerRequestDurationView = &view.View{
Name: "http_server_request_duration_ms",
Measure: ochttp.ServerLatency,
Description: "HTTP Request duration in ms",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, ochttp.StatusCode},
Aggregation: httpLatencyDistrubtion,
}
// HTTPServerRequestSizeView is an OpenCensus view that tracks HTTP server request size by pomerium service, host and method
HTTPServerRequestSizeView = &view.View{
Name: "http_server_request_size_bytes",
Measure: ochttp.ServerRequestBytes,
Description: "HTTP Server Request Size in bytes",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod},
Aggregation: httpSizeDistribution,
}
// HTTPServerResponseSizeView is an OpenCensus view that tracks HTTP server response size by pomerium service, host, method and status
HTTPServerResponseSizeView = &view.View{
Name: "http_server_response_size_bytes",
Measure: ochttp.ServerResponseBytes,
Description: "HTTP Server Response Size in bytes",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, ochttp.StatusCode},
Aggregation: httpSizeDistribution,
}
// HTTPClientRequestCountView is an OpenCensus View that tracks HTTP client requests by pomerium service, destination, host, method and status
HTTPClientRequestCountView = &view.View{
Name: "http_client_requests_total",
Measure: ochttp.ClientRoundtripLatency,
Description: "Total HTTP Client Requests",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, ochttp.StatusCode, keyDestination},
Aggregation: view.Count(),
}
// HTTPClientRequestDurationView is an OpenCensus view that tracks HTTP client request duration by pomerium service, destination, host, method and status
HTTPClientRequestDurationView = &view.View{
Name: "http_client_request_duration_ms",
Measure: ochttp.ClientRoundtripLatency,
Description: "HTTP Client Request duration in ms",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, ochttp.StatusCode, keyDestination},
Aggregation: httpLatencyDistrubtion,
}
// HTTPClientResponseSizeView is an OpenCensus view that tracks HTTP client response size by pomerium service, destination, host, method and status
HTTPClientResponseSizeView = &view.View{
Name: "http_client_response_size_bytes",
Measure: ochttp.ClientReceivedBytes,
Description: "HTTP Client Response Size in bytes",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, ochttp.StatusCode, keyDestination},
Aggregation: httpSizeDistribution,
}
// HTTPClientRequestSizeView is an OpenCensus view that tracks HTTP client request size by pomerium service, destination, host and method
HTTPClientRequestSizeView = &view.View{
Name: "http_client_response_size_bytes",
Measure: ochttp.ClientSentBytes,
Description: "HTTP Client Response Size in bytes",
TagKeys: []tag.Key{keyService, keyHost, keyHTTPMethod, keyDestination},
Aggregation: httpSizeDistribution,
}
)
// HTTPMetricsHandler creates a metrics middleware for incoming HTTP requests
func HTTPMetricsHandler(service string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, tagErr := tag.New(
r.Context(),
tag.Insert(keyService, service),
tag.Insert(keyHost, r.Host),
tag.Insert(keyHTTPMethod, r.Method),
)
if tagErr != nil {
log.Warn().Err(tagErr).Str("context", "HTTPMetricsHandler").Msg("internal/metrics: Failed to create metrics context tag")
next.ServeHTTP(w, r)
return
}
ocHandler := ochttp.Handler{Handler: next}
ocHandler.ServeHTTP(w, r.WithContext(ctx))
})
}
}
// HTTPMetricsRoundTripper creates a metrics tracking tripper for outbound HTTP Requests
func HTTPMetricsRoundTripper(service string, destination string) func(next http.RoundTripper) http.RoundTripper {
return func(next http.RoundTripper) http.RoundTripper {
return tripper.RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
ctx, tagErr := tag.New(
r.Context(),
tag.Insert(keyService, service),
tag.Insert(keyHost, r.Host),
tag.Insert(keyHTTPMethod, r.Method),
tag.Insert(keyDestination, destination),
)
if tagErr != nil {
log.Warn().Err(tagErr).Str("context", "HTTPMetricsRoundTripper").Msg("internal/metrics: Failed to create context tag")
return next.RoundTrip(r)
}
ocTransport := ochttp.Transport{Base: next}
return ocTransport.RoundTrip(r.WithContext(ctx))
})
}
}