mirror of
https://github.com/itzg/mc-router.git
synced 2024-11-26 12:15:16 +01:00
Added influxdb as a metrics reporter/backend
This commit is contained in:
parent
7f50c512f5
commit
a12bbb88a3
43
README.md
43
README.md
@ -9,13 +9,42 @@ Routes Minecraft client connections to backend servers based upon the requested
|
||||
# Usage
|
||||
|
||||
```text
|
||||
Flags:
|
||||
--help Show context-sensitive help (also try --help-long
|
||||
and --help-man).
|
||||
--port=25565 The port bound to listen for Minecraft client
|
||||
connections
|
||||
--api-binding=API-BINDING The host:port bound for servicing API requests
|
||||
--mapping=MAPPING,MAPPING Where MAPPING is externalHostname=host:port
|
||||
-api-binding host:port
|
||||
The host:port bound for servicing API requests (env API_BINDING)
|
||||
-connection-rate-limit int
|
||||
Max number of connections to allow per second (env CONNECTION_RATE_LIMIT) (default 1)
|
||||
-cpu-profile string
|
||||
Enables CPU profiling and writes to given path (env CPU_PROFILE)
|
||||
-debug
|
||||
Enable debug logs (env DEBUG)
|
||||
-in-kube-cluster
|
||||
Use in-cluster kubernetes config (env IN_KUBE_CLUSTER)
|
||||
-kube-config string
|
||||
The path to a kubernetes configuration file (env KUBE_CONFIG)
|
||||
-kube-discovery
|
||||
Enables discovery of annotated kubernetes services (env KUBE_DISCOVERY)
|
||||
-mapping string
|
||||
Comma-separated mappings of externalHostname=host:port (env MAPPING)
|
||||
-metrics-backend string
|
||||
Backend to use for metrics exposure/publishing: discard,expvar,influxdb (env METRICS_BACKEND) (default "discard")
|
||||
-metrics-backend-config-influxdb-addr string
|
||||
(env METRICS_BACKEND_CONFIG_INFLUXDB_ADDR)
|
||||
-metrics-backend-config-influxdb-database string
|
||||
(env METRICS_BACKEND_CONFIG_INFLUXDB_DATABASE)
|
||||
-metrics-backend-config-influxdb-interval duration
|
||||
(env METRICS_BACKEND_CONFIG_INFLUXDB_INTERVAL) (default 1m0s)
|
||||
-metrics-backend-config-influxdb-password string
|
||||
(env METRICS_BACKEND_CONFIG_INFLUXDB_PASSWORD)
|
||||
-metrics-backend-config-influxdb-retention-policy string
|
||||
(env METRICS_BACKEND_CONFIG_INFLUXDB_RETENTION_POLICY)
|
||||
-metrics-backend-config-influxdb-tags value
|
||||
any extra tags to be included with all reported metrics (env METRICS_BACKEND_CONFIG_INFLUXDB_TAGS)
|
||||
-metrics-backend-config-influxdb-username string
|
||||
(env METRICS_BACKEND_CONFIG_INFLUXDB_USERNAME)
|
||||
-port port
|
||||
The port bound to listen for Minecraft client connections (env PORT) (default 25565)
|
||||
-version
|
||||
Output version and exit (env VERSION)
|
||||
```
|
||||
|
||||
# REST API
|
||||
|
@ -13,19 +13,34 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MetricsBackendConfig struct {
|
||||
Influxdb struct {
|
||||
Interval time.Duration `default:"1m"`
|
||||
Tags map[string]string `usage:"any extra tags to be included with all reported metrics"`
|
||||
Addr string
|
||||
Username string
|
||||
Password string
|
||||
Database string
|
||||
RetentionPolicy string
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Port int `default:"25565" usage:"The [port] bound to listen for Minecraft client connections"`
|
||||
Mapping string `usage:"Comma-separated mappings of externalHostname=host:port"`
|
||||
ApiBinding string `usage:"The [host:port] bound for servicing API requests"`
|
||||
Version bool `usage:"Output version and exit"`
|
||||
CpuProfile string `usage:"Enables CPU profiling and writes to given path"`
|
||||
Debug bool `usage:"Enable debug logs"`
|
||||
ConnectionRateLimit int `default:"1" usage:"Max number of connections to allow per second"`
|
||||
InKubeCluster bool `usage:"Use in-cluster kubernetes config"`
|
||||
KubeConfig string `usage:"The path to a kubernetes configuration file"`
|
||||
MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar"`
|
||||
Port int `default:"25565" usage:"The [port] bound to listen for Minecraft client connections"`
|
||||
Mapping string `usage:"Comma-separated mappings of externalHostname=host:port"`
|
||||
ApiBinding string `usage:"The [host:port] bound for servicing API requests"`
|
||||
Version bool `usage:"Output version and exit"`
|
||||
CpuProfile string `usage:"Enables CPU profiling and writes to given path"`
|
||||
Debug bool `usage:"Enable debug logs"`
|
||||
ConnectionRateLimit int `default:"1" usage:"Max number of connections to allow per second"`
|
||||
KubeDiscovery bool `usage:"Enables discovery of annotated kubernetes services"`
|
||||
InKubeCluster bool `usage:"Use in-cluster kubernetes config"`
|
||||
KubeConfig string `usage:"The path to a kubernetes configuration file"`
|
||||
MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar,influxdb"`
|
||||
MetricsBackendConfig MetricsBackendConfig
|
||||
}
|
||||
|
||||
var (
|
||||
@ -71,8 +86,9 @@ func main() {
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
metricsBuilder := NewMetricsBuilder(config.MetricsBackend)
|
||||
metricsBuilder := NewMetricsBuilder(config.MetricsBackend, &config.MetricsBackendConfig)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||
@ -98,22 +114,27 @@ func main() {
|
||||
if config.InKubeCluster {
|
||||
err = server.K8sWatcher.StartInCluster()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Warn("Unable to start k8s integration")
|
||||
logrus.WithError(err).Fatal("Unable to start k8s integration")
|
||||
} else {
|
||||
defer server.K8sWatcher.Stop()
|
||||
}
|
||||
} else if config.KubeConfig != "" {
|
||||
err := server.K8sWatcher.StartWithConfig(config.KubeConfig)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Warn("Unable to start k8s integration")
|
||||
logrus.WithError(err).Fatal("Unable to start k8s integration")
|
||||
} else {
|
||||
defer server.K8sWatcher.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
err = metricsBuilder.Start(ctx)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("Unable to start metrics reporter")
|
||||
}
|
||||
|
||||
// wait for process-stop signal
|
||||
<-c
|
||||
logrus.Info("Stopping")
|
||||
cancel()
|
||||
}
|
||||
|
||||
func parseMappings(val string) map[string]string {
|
||||
|
@ -1,31 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
kitlogrus "github.com/go-kit/kit/log/logrus"
|
||||
discardMetrics "github.com/go-kit/kit/metrics/discard"
|
||||
expvarMetrics "github.com/go-kit/kit/metrics/expvar"
|
||||
kitinflux "github.com/go-kit/kit/metrics/influx"
|
||||
influx "github.com/influxdata/influxdb1-client/v2"
|
||||
"github.com/itzg/mc-router/server"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MetricsBuilder interface {
|
||||
BuildConnectorMetrics() *server.ConnectorMetrics
|
||||
Start(ctx context.Context) error
|
||||
}
|
||||
|
||||
func NewMetricsBuilder(backend string) MetricsBuilder {
|
||||
switch backend {
|
||||
case "discard":
|
||||
return &discardMetricsBuilder{}
|
||||
func NewMetricsBuilder(backend string, config *MetricsBackendConfig) MetricsBuilder {
|
||||
switch strings.ToLower(backend) {
|
||||
case "expvar":
|
||||
return &expvarMetricsBuilder{}
|
||||
case "influxdb":
|
||||
return &influxMetricsBuilder{config: config}
|
||||
default:
|
||||
logrus.Fatalf("Unsupported metrics backend: %s", backend)
|
||||
return nil
|
||||
return &discardMetricsBuilder{}
|
||||
}
|
||||
}
|
||||
|
||||
type expvarMetricsBuilder struct {
|
||||
}
|
||||
|
||||
func (b expvarMetricsBuilder) Start(ctx context.Context) error {
|
||||
// nothing needed
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b expvarMetricsBuilder) BuildConnectorMetrics() *server.ConnectorMetrics {
|
||||
return &server.ConnectorMetrics{
|
||||
Errors: expvarMetrics.NewCounter("errors").With("subsystem", "connector"),
|
||||
@ -38,6 +51,11 @@ func (b expvarMetricsBuilder) BuildConnectorMetrics() *server.ConnectorMetrics {
|
||||
type discardMetricsBuilder struct {
|
||||
}
|
||||
|
||||
func (b discardMetricsBuilder) Start(ctx context.Context) error {
|
||||
// nothing needed
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b discardMetricsBuilder) BuildConnectorMetrics() *server.ConnectorMetrics {
|
||||
return &server.ConnectorMetrics{
|
||||
Errors: discardMetrics.NewCounter(),
|
||||
@ -46,3 +64,50 @@ func (b discardMetricsBuilder) BuildConnectorMetrics() *server.ConnectorMetrics
|
||||
ActiveConnections: discardMetrics.NewGauge(),
|
||||
}
|
||||
}
|
||||
|
||||
type influxMetricsBuilder struct {
|
||||
config *MetricsBackendConfig
|
||||
metrics *kitinflux.Influx
|
||||
}
|
||||
|
||||
func (b *influxMetricsBuilder) Start(ctx context.Context) error {
|
||||
influxConfig := &b.config.Influxdb
|
||||
if influxConfig.Addr == "" {
|
||||
return errors.New("influx addr is required")
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(influxConfig.Interval)
|
||||
client, err := influx.NewHTTPClient(influx.HTTPConfig{
|
||||
Addr: influxConfig.Addr,
|
||||
Username: influxConfig.Username,
|
||||
Password: influxConfig.Password,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create influx http client: %w", err)
|
||||
}
|
||||
|
||||
go b.metrics.WriteLoop(ctx, ticker.C, client)
|
||||
|
||||
logrus.WithField("addr", influxConfig.Addr).
|
||||
Debug("reporting metrics to influxdb")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *influxMetricsBuilder) BuildConnectorMetrics() *server.ConnectorMetrics {
|
||||
influxConfig := &b.config.Influxdb
|
||||
|
||||
metrics := kitinflux.New(influxConfig.Tags, influx.BatchPointsConfig{
|
||||
Database: influxConfig.Database,
|
||||
RetentionPolicy: influxConfig.RetentionPolicy,
|
||||
}, kitlogrus.NewLogrusLogger(logrus.StandardLogger()))
|
||||
|
||||
b.metrics = metrics
|
||||
|
||||
return &server.ConnectorMetrics{
|
||||
Errors: metrics.NewCounter("errors"),
|
||||
BytesTransmitted: metrics.NewCounter("transmitted_bytes"),
|
||||
Connections: metrics.NewCounter("connections"),
|
||||
ActiveConnections: metrics.NewGauge("connections_active"),
|
||||
}
|
||||
}
|
||||
|
5
go.mod
5
go.mod
@ -5,6 +5,8 @@ go 1.12
|
||||
require (
|
||||
github.com/VividCortex/gohistogram v1.0.0 // indirect
|
||||
github.com/go-kit/kit v0.9.0
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/gogo/protobuf v1.2.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
|
||||
github.com/golang/protobuf v1.3.1 // indirect
|
||||
@ -13,7 +15,8 @@ require (
|
||||
github.com/gorilla/mux v1.7.1
|
||||
github.com/hashicorp/golang-lru v0.5.1 // indirect
|
||||
github.com/imdario/mergo v0.3.7 // indirect
|
||||
github.com/itzg/go-flagsfiller v1.4.1
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
||||
github.com/itzg/go-flagsfiller v1.4.2
|
||||
github.com/json-iterator/go v1.1.6 // indirect
|
||||
github.com/juju/ratelimit v1.0.1
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
|
8
go.sum
8
go.sum
@ -6,6 +6,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
|
||||
@ -25,8 +29,12 @@ github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFE
|
||||
github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
|
||||
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/itzg/go-flagsfiller v1.4.1 h1:h/t5g+WkvsOR449bz1ngU8UGosKNm4Sr3iMNNgOqHfo=
|
||||
github.com/itzg/go-flagsfiller v1.4.1/go.mod h1:mfQgTahSs4OHn8PYev2Wwi1LJXUiYiGuZVCpBLxzbYs=
|
||||
github.com/itzg/go-flagsfiller v1.4.2 h1:aQRyQ9/ps111FZYGhzxgKYiOewE7zbAks7rxF49Qlm8=
|
||||
github.com/itzg/go-flagsfiller v1.4.2/go.mod h1:mfQgTahSs4OHn8PYev2Wwi1LJXUiYiGuZVCpBLxzbYs=
|
||||
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=
|
||||
|
9
test/mc-router-telegraf-backend/docker-compose.yml
Normal file
9
test/mc-router-telegraf-backend/docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
telegraf:
|
||||
image: telegraf:1.13
|
||||
ports:
|
||||
- 8186:8186
|
||||
volumes:
|
||||
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
|
8
test/mc-router-telegraf-backend/telegraf.conf
Normal file
8
test/mc-router-telegraf-backend/telegraf.conf
Normal file
@ -0,0 +1,8 @@
|
||||
[agent]
|
||||
interval = "10s"
|
||||
|
||||
[[inputs.influxdb_listener]]
|
||||
service_address = ":8186"
|
||||
|
||||
[[outputs.file]]
|
||||
files = ["stdout"]
|
Loading…
Reference in New Issue
Block a user