Expose rate limit bucket tokens as metric (#502)

This commit is contained in:
Jasper
2026-01-04 04:43:46 +01:00
committed by GitHub
parent abdb3c8b6e
commit 9cc25e4127
4 changed files with 56 additions and 27 deletions
+3
View File
@@ -1,5 +1,7 @@
package server
import "time"
type WebhookConfig struct {
Url string `usage:"If set, a POST request that contains connection status notifications will be sent to this HTTP address"`
RequireUser bool `default:"false" usage:"Indicates if the webhook will only be called if a user is connecting rather than just server list/ping"`
@@ -41,6 +43,7 @@ type Config struct {
DockerApiVersion string `usage:"Instead of auto-negotiating, use specific Docker API version"`
MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar,influxdb,prometheus"`
MetricsBackendConfig MetricsBackendConfig
MetricsRateLimitPeriod time.Duration `default:"1s" usage:"The period at which the rate limit bucket's metrics are set: 0 to disable (default 1s)"`
UseProxyProtocol bool `default:"false" usage:"Send PROXY protocol to backend servers"`
ReceiveProxyProtocol bool `default:"false" usage:"Receive PROXY protocol from backend servers, by default trusts every proxy header that it receives, combine with -trusted-proxies to specify a list of trusted proxies"`
TrustedProxies []string `usage:"Comma delimited list of CIDR notation IP blocks to trust when receiving PROXY protocol"`
+19 -3
View File
@@ -111,13 +111,13 @@ func (c *Connector) UseClientFilter(filter *ClientFilter) {
c.clientFilter = filter
}
func (c *Connector) StartAcceptingConnections(listenAddress string, connRateLimit int) error {
func (c *Connector) StartAcceptingConnections(listenAddress string, connRateLimit int, metricsPeriod time.Duration) error {
ln, err := c.createListener(listenAddress)
if err != nil {
return err
}
go c.acceptConnections(ln, connRateLimit)
go c.acceptConnections(ln, connRateLimit, metricsPeriod)
return nil
}
@@ -201,11 +201,14 @@ func (c *Connector) AcceptConnection(conn net.Conn) {
go c.HandleConnection(conn)
}
func (c *Connector) acceptConnections(ln net.Listener, connRateLimit int) {
func (c *Connector) acceptConnections(ln net.Listener, connRateLimit int, metricsPeriod time.Duration) {
//noinspection GoUnhandledErrorResult
defer ln.Close()
bucket := ratelimit.NewBucketWithRate(float64(connRateLimit), int64(connRateLimit*2))
if metricsPeriod > 0 {
go c.bucketMetrics(bucket, metricsPeriod)
}
for {
select {
@@ -223,6 +226,19 @@ func (c *Connector) acceptConnections(ln net.Listener, connRateLimit int) {
}
}
func (c *Connector) bucketMetrics(bucket *ratelimit.Bucket, period time.Duration) {
ticker := time.NewTicker(period)
defer ticker.Stop()
for {
select {
case <-c.ctx.Done():
return
case <-ticker.C:
c.metrics.RateLimitAvailable.Set(float64(bucket.Available()))
}
}
}
func (c *Connector) HandleConnection(frontendConn net.Conn) {
c.metrics.ConnectionsFrontend.Add(1)
//noinspection GoUnhandledErrorResult
+9
View File
@@ -78,6 +78,7 @@ type ConnectorMetrics struct {
ServerActivePlayer metrics.Gauge
ServerLogins metrics.Counter
ServerActiveConnections metrics.Gauge
RateLimitAvailable metrics.Gauge
}
func (b expvarMetricsBuilder) BuildConnectorMetrics() *ConnectorMetrics {
@@ -91,6 +92,7 @@ func (b expvarMetricsBuilder) BuildConnectorMetrics() *ConnectorMetrics {
ServerActivePlayer: expvarMetrics.NewGauge("server_active_player"),
ServerLogins: expvarMetrics.NewCounter("server_logins"),
ServerActiveConnections: expvarMetrics.NewGauge("server_active_connections"),
RateLimitAvailable: expvarMetrics.NewGauge("rate_limit_available"),
}
}
@@ -112,6 +114,7 @@ func (b discardMetricsBuilder) BuildConnectorMetrics() *ConnectorMetrics {
ServerActivePlayer: discardMetrics.NewGauge(),
ServerLogins: discardMetrics.NewCounter(),
ServerActiveConnections: discardMetrics.NewGauge(),
RateLimitAvailable: discardMetrics.NewGauge(),
}
}
@@ -164,6 +167,7 @@ func (b *influxMetricsBuilder) BuildConnectorMetrics() *ConnectorMetrics {
ServerActivePlayer: metrics.NewGauge("mc_router_server_player_active"),
ServerLogins: metrics.NewCounter("mc_router_server_logins"),
ServerActiveConnections: metrics.NewGauge("mc_router_server_active_connections"),
RateLimitAvailable: metrics.NewGauge("mc_router_rate_limit_available"),
}
}
@@ -225,5 +229,10 @@ func (b prometheusMetricsBuilder) BuildConnectorMetrics() *ConnectorMetrics {
Name: "server_active_connections",
Help: "The number of active connections per server",
}, []string{"server_address"})),
RateLimitAvailable: prometheusMetrics.NewGauge(promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "mc_router",
Name: "rate_limit_available",
Help: "The number of available tokens in the rate limit bucket",
}, nil)),
}
}
+1
View File
@@ -202,6 +202,7 @@ func (s *Server) Run() {
err := s.connector.StartAcceptingConnections(
net.JoinHostPort("", strconv.Itoa(s.config.Port)),
s.config.ConnectionRateLimit,
s.config.MetricsRateLimitPeriod,
)
if err != nil {
logrus.WithError(err).Error("Could not start accepting connections")