Skip to content

Commit a0ed627

Browse files
alebedev87claude
andcommitted
NE-2418: Add haproxy_max_connections metric
Add a new haproxy_max_connections gauge metric that exposes the process-wide maximum connections configured for HAProxy. The metric is extracted from the public frontend's "slim" field (field 6) in HAProxy's "show stat" CSV output. Since the router configures both global and defaults sections with the same ROUTER_MAX_CONNECTIONS value, the public frontend's session limit reflects the process-wide maxconn setting. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent d2db065 commit a0ed627

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

pkg/router/metrics/haproxy/haproxy.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ type Exporter struct {
136136
up, nextScrapeInterval prometheus.Gauge
137137
totalScrapes, csvParseFailures prometheus.Counter
138138
serverThresholdCurrent, serverThresholdLimit prometheus.Gauge
139+
maxConnections prometheus.Gauge
139140
frontendMetrics, backendMetrics, serverMetrics map[int]*prometheus.GaugeVec
140141

141142
// counterValues is added to the value specific haproxy frontend, backend, or server counter
@@ -218,6 +219,11 @@ func NewExporter(opts PrometheusOptions) (*Exporter, error) {
218219
Name: "exporter_csv_parse_failures",
219220
Help: "Number of errors while parsing CSV.",
220221
}),
222+
maxConnections: prometheus.NewGauge(prometheus.GaugeOpts{
223+
Namespace: namespace,
224+
Name: "max_connections",
225+
Help: "Maximum number of concurrent connections configured for the HAProxy process.",
226+
}),
221227
frontendMetrics: filterMetrics(opts.ExportedMetrics, metrics{
222228
4: newFrontendMetric("current_sessions", "Current number of active sessions.", nil),
223229
5: newFrontendMetric("max_sessions", "Maximum observed number of active sessions.", nil),
@@ -321,6 +327,7 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
321327
ch <- e.serverThresholdCurrent.Desc()
322328
ch <- e.serverThresholdLimit.Desc()
323329
ch <- e.csvParseFailures.Desc()
330+
ch <- e.maxConnections.Desc()
324331
}
325332

326333
// Collect fetches the stats from configured HAProxy location and delivers them
@@ -347,6 +354,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
347354
ch <- e.serverThresholdCurrent
348355
ch <- e.serverThresholdLimit
349356
ch <- e.csvParseFailures
357+
ch <- e.maxConnections
350358
e.collectMetrics(ch)
351359
}
352360

@@ -516,6 +524,19 @@ func (e *Exporter) parseRow(csvRow []string, updatedValues counterValuesByMetric
516524

517525
switch typ {
518526
case frontendType:
527+
// Extract maxconn from public frontend for the process-wide metric.
528+
// Field 6 corresponds to "slim" (session limit) column from HAProxy's "show stat" CSV output.
529+
// The router configures both global and defaults sections with the same ROUTER_MAX_CONNECTIONS value,
530+
// so the public frontend's limit (field 6/slim) reflects the process-wide maxconn setting.
531+
// NOTE: If the defaults maxconn is ever configured differently from global maxconn,
532+
// this approach will no longer accurately represent the process-wide limit.
533+
if pxname == "public" && len(csvRow) > 6 {
534+
if maxConnStr := csvRow[6]; maxConnStr != "" {
535+
if maxConn, err := strconv.ParseInt(maxConnStr, 10, 64); err == nil {
536+
e.maxConnections.Set(float64(maxConn))
537+
}
538+
}
539+
}
519540
e.exportAndRecordRow(e.frontendMetrics, metricID{proxyType: serverType, proxyName: pxname}, updatedValues, csvRow, pxname)
520541
case backendType:
521542
if mode, value, ok := knownBackendSegment(pxname); ok {

0 commit comments

Comments
 (0)