Add a flag to make per-host metrics optional

When serving many hosts from one nginx, the metrics may become too
numerous for Prometheus.  Add a flag to disable the host label, so
that metrics are totalled across all hosts.
This commit is contained in:
Bryan Boreham 2018-12-21 17:10:28 +00:00 committed by Bryan Boreham
parent 63b01370e4
commit f33a2090dd
6 changed files with 23 additions and 9 deletions

View file

@ -149,6 +149,8 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en
enableMetrics = flags.Bool("enable-metrics", true, enableMetrics = flags.Bool("enable-metrics", true,
`Enables the collection of NGINX metrics`) `Enables the collection of NGINX metrics`)
metricsPerHost = flags.Bool("metrics-per-host", true,
`Export metrics per-host`)
httpPort = flags.Int("http-port", 80, `Port to use for servicing HTTP traffic.`) httpPort = flags.Int("http-port", 80, `Port to use for servicing HTTP traffic.`)
httpsPort = flags.Int("https-port", 443, `Port to use for servicing HTTPS traffic.`) httpsPort = flags.Int("https-port", 443, `Port to use for servicing HTTPS traffic.`)
@ -227,6 +229,7 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en
ElectionID: *electionID, ElectionID: *electionID,
EnableProfiling: *profiling, EnableProfiling: *profiling,
EnableMetrics: *enableMetrics, EnableMetrics: *enableMetrics,
MetricsPerHost: *metricsPerHost,
EnableSSLPassthrough: *enableSSLPassthrough, EnableSSLPassthrough: *enableSSLPassthrough,
EnableSSLChainCompletion: *enableSSLChainCompletion, EnableSSLChainCompletion: *enableSSLChainCompletion,
ResyncPeriod: *resyncPeriod, ResyncPeriod: *resyncPeriod,

View file

@ -131,7 +131,7 @@ func main() {
mc := metric.NewDummyCollector() mc := metric.NewDummyCollector()
if conf.EnableMetrics { if conf.EnableMetrics {
mc, err = metric.NewCollector(conf.ListenPorts.Status, reg) mc, err = metric.NewCollector(conf.ListenPorts.Status, conf.MetricsPerHost, reg)
if err != nil { if err != nil {
klog.Fatalf("Error creating prometheus collector: %v", err) klog.Fatalf("Error creating prometheus collector: %v", err)
} }

View file

@ -88,6 +88,7 @@ type Configuration struct {
EnableProfiling bool EnableProfiling bool
EnableMetrics bool EnableMetrics bool
MetricsPerHost bool
EnableSSLChainCompletion bool EnableSSLChainCompletion bool

View file

@ -76,12 +76,12 @@ type SocketCollector struct {
metricMapping map[string]interface{} metricMapping map[string]interface{}
hosts sets.String hosts sets.String
metricsPerHost bool
} }
var ( var (
requestTags = []string{ requestTags = []string{
"host",
"status", "status",
"method", "method",
@ -95,7 +95,7 @@ var (
// NewSocketCollector creates a new SocketCollector instance using // NewSocketCollector creates a new SocketCollector instance using
// the ingress watch namespace and class used by the controller // the ingress watch namespace and class used by the controller
func NewSocketCollector(pod, namespace, class string) (*SocketCollector, error) { func NewSocketCollector(pod, namespace, class string, metricsPerHost bool) (*SocketCollector, error) {
socket := "/tmp/prometheus-nginx.socket" socket := "/tmp/prometheus-nginx.socket"
listener, err := net.Listen("unix", socket) listener, err := net.Listen("unix", socket)
if err != nil { if err != nil {
@ -113,9 +113,16 @@ func NewSocketCollector(pod, namespace, class string) (*SocketCollector, error)
"controller_pod": pod, "controller_pod": pod,
} }
requestTags := requestTags
if metricsPerHost {
requestTags = append(requestTags, "host")
}
sc := &SocketCollector{ sc := &SocketCollector{
listener: listener, listener: listener,
metricsPerHost: metricsPerHost,
responseTime: prometheus.NewHistogramVec( responseTime: prometheus.NewHistogramVec(
prometheus.HistogramOpts{ prometheus.HistogramOpts{
Name: "response_duration_seconds", Name: "response_duration_seconds",
@ -219,8 +226,8 @@ func (sc *SocketCollector) handleMessage(msg []byte) {
continue continue
} }
// Note these must match the order in requestTags at the top
requestLabels := prometheus.Labels{ requestLabels := prometheus.Labels{
"host": stats.Host,
"status": stats.Status, "status": stats.Status,
"method": stats.Method, "method": stats.Method,
"path": stats.Path, "path": stats.Path,
@ -228,6 +235,9 @@ func (sc *SocketCollector) handleMessage(msg []byte) {
"ingress": stats.Ingress, "ingress": stats.Ingress,
"service": stats.Service, "service": stats.Service,
} }
if sc.metricsPerHost {
requestLabels["host"] = stats.Host
}
collectorLabels := prometheus.Labels{ collectorLabels := prometheus.Labels{
"namespace": stats.Namespace, "namespace": stats.Namespace,

View file

@ -288,7 +288,7 @@ func TestCollector(t *testing.T) {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
registry := prometheus.NewPedanticRegistry() registry := prometheus.NewPedanticRegistry()
sc, err := NewSocketCollector("pod", "default", "ingress") sc, err := NewSocketCollector("pod", "default", "ingress", true)
if err != nil { if err != nil {
t.Errorf("%v: unexpected error creating new SocketCollector: %v", c.name, err) t.Errorf("%v: unexpected error creating new SocketCollector: %v", c.name, err)
} }

View file

@ -59,7 +59,7 @@ type collector struct {
} }
// NewCollector creates a new metric collector the for ingress controller // NewCollector creates a new metric collector the for ingress controller
func NewCollector(statusPort int, registry *prometheus.Registry) (Collector, error) { func NewCollector(statusPort int, metricsPerHost bool, registry *prometheus.Registry) (Collector, error) {
podNamespace := os.Getenv("POD_NAMESPACE") podNamespace := os.Getenv("POD_NAMESPACE")
if podNamespace == "" { if podNamespace == "" {
podNamespace = "default" podNamespace = "default"
@ -77,7 +77,7 @@ func NewCollector(statusPort int, registry *prometheus.Registry) (Collector, err
return nil, err return nil, err
} }
s, err := collectors.NewSocketCollector(podName, podNamespace, class.IngressClass) s, err := collectors.NewSocketCollector(podName, podNamespace, class.IngressClass, metricsPerHost)
if err != nil { if err != nil {
return nil, err return nil, err
} }