ソースを参照

Add support for prometheus

tags/0.15^2^2
9seconds 7年前
コミット
9346c11f37
7個のファイルの変更126行の追加2行の削除
  1. 5
    1
      config/config.go
  2. 9
    0
      go.mod
  3. 18
    0
      go.sum
  4. 7
    1
      main.go
  5. 5
    0
      stats/init.go
  6. 80
    0
      stats/prometheus.go
  7. 2
    0
      stats/server.go

+ 5
- 1
config/config.go ファイルの表示

@@ -38,6 +38,9 @@ type Config struct {
38 38
 		TagsFormat statsd.TagFormat
39 39
 		Enabled    bool
40 40
 	}
41
+	Prometheus struct {
42
+		Prefix string
43
+	}
41 44
 
42 45
 	Secret []byte
43 46
 	AdTag  []byte
@@ -116,7 +119,7 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
116 119
 	bindIP, publicIPv4, publicIPv6, statsIP net.IP,
117 120
 	bindPort, publicIPv4Port, publicIPv6Port, statsPort, statsdPort uint16,
118 121
 	statsdIP, statsdNetwork, statsdPrefix, statsdTagsFormat string,
119
-	statsdTags map[string]string,
122
+	statsdTags map[string]string, prometheusPrefix string,
120 123
 	secureOnly bool,
121 124
 	secret, adtag []byte) (*Config, error) {
122 125
 	secureMode := secureOnly
@@ -174,6 +177,7 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
174 177
 		ReadBufferSize:  int(readBufferSize),
175 178
 		WriteBufferSize: int(writeBufferSize),
176 179
 	}
180
+	conf.Prometheus.Prefix = prometheusPrefix
177 181
 
178 182
 	if statsdIP != "" {
179 183
 		conf.StatsD.Enabled = true

+ 9
- 0
go.mod ファイルの表示

@@ -4,20 +4,29 @@ require (
4 4
 	github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
5 5
 	github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
6 6
 	github.com/beevik/ntp v0.2.0
7
+	github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
7 8
 	github.com/davecgh/go-spew v1.1.1 // indirect
8 9
 	github.com/dustin/go-humanize v1.0.0
9 10
 	github.com/gofrs/uuid v3.1.0+incompatible
11
+	github.com/gogo/protobuf v1.1.1 // indirect
12
+	github.com/golang/protobuf v1.2.0 // indirect
10 13
 	github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea
11 14
 	github.com/juju/loggo v0.0.0-20180524022052-584905176618 // indirect
12 15
 	github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 // indirect
13 16
 	github.com/kr/pretty v0.1.0 // indirect
17
+	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
14 18
 	github.com/pkg/errors v0.8.0 // indirect
15 19
 	github.com/pmezard/go-difflib v1.0.0 // indirect
20
+	github.com/prometheus/client_golang v0.9.0
21
+	github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
22
+	github.com/prometheus/common v0.0.0-20181015124227-bcb74de08d37 // indirect
23
+	github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect
16 24
 	github.com/stretchr/testify v1.2.2
17 25
 	go.uber.org/atomic v1.3.2 // indirect
18 26
 	go.uber.org/multierr v1.1.0 // indirect
19 27
 	go.uber.org/zap v1.9.1
20 28
 	golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect
29
+	golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
21 30
 	gopkg.in/alecthomas/kingpin.v2 v2.2.6
22 31
 	gopkg.in/alexcesaro/statsd.v2 v2.0.0
23 32
 	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect

+ 18
- 0
go.sum ファイルの表示

@@ -4,12 +4,18 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZq
4 4
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
5 5
 github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
6 6
 github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
7
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
8
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
7 9
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
8 10
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 11
 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
10 12
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
11 13
 github.com/gofrs/uuid v3.1.0+incompatible h1:q2rtkjaKT4YEr6E1kamy0Ha4RtepWlQBedyHx0uzKwA=
12 14
 github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
15
+github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
16
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
17
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
18
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
13 19
 github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea h1:g2k+8WR7cHch4g0tBDhfiEvAp7fXxTNBiD1oC1Oxj3E=
14 20
 github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
15 21
 github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8=
@@ -21,10 +27,20 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
21 27
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
22 28
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
23 29
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
30
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
31
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
24 32
 github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
25 33
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
26 34
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
27 35
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
36
+github.com/prometheus/client_golang v0.9.0 h1:tXuTFVHC03mW0D+Ua1Q2d1EAVqLTuggX50V0VLICCzY=
37
+github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
38
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
39
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
40
+github.com/prometheus/common v0.0.0-20181015124227-bcb74de08d37 h1:Y7YdJ9Xb3MoQOzAWXnDunAJYpvhVwZdTirNfGUgPKaA=
41
+github.com/prometheus/common v0.0.0-20181015124227-bcb74de08d37/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
42
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ=
43
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
28 44
 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
29 45
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
30 46
 go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
@@ -35,6 +51,8 @@ go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
35 51
 go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
36 52
 golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w=
37 53
 golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
54
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
55
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
38 56
 gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
39 57
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
40 58
 gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc=

+ 7
- 1
main.go ファイルの表示

@@ -110,6 +110,12 @@ var (
110 110
 		Envar("MTG_STATSD_TAGS").
111 111
 		StringMap()
112 112
 
113
+	prometheusPrefix = app.Flag("prometheus-prefix",
114
+		"Which namespace to use to send stats to Prometheus.").
115
+		Envar("MTG_PROMETHEUS_PREFIX").
116
+		Default("mtg").
117
+		String()
118
+
113 119
 	writeBufferSize = app.Flag("write-buffer",
114 120
 		"Write buffer size in bytes. You can think about it as a buffer from client to Telegram.").
115 121
 		Short('w').
@@ -151,7 +157,7 @@ func main() { // nolint: gocyclo
151 157
 		*bindIP, *publicIPv4, *publicIPv6, *statsIP,
152 158
 		*bindPort, *publicIPv4Port, *publicIPv6Port, *statsPort, *statsdPort,
153 159
 		*statsdIP, *statsdNetwork, *statsdPrefix, *statsdTagsFormat,
154
-		*statsdTags, *secureOnly,
160
+		*statsdTags, *prometheusPrefix, *secureOnly,
155 161
 		*secret, *adtag,
156 162
 	)
157 163
 	if err != nil {

+ 5
- 0
stats/init.go ファイルの表示

@@ -15,6 +15,11 @@ func Init(conf *config.Config) error {
15 15
 		}
16 16
 		go client.run()
17 17
 	}
18
+	prometheus, err := newPrometheus(conf)
19
+	if err != nil {
20
+		return errors.Annotate(err, "Cannot initialize prometheus client")
21
+	}
22
+	go prometheus.run()
18 23
 
19 24
 	go NewStats(conf).start()
20 25
 	go startServer(conf)

+ 80
- 0
stats/prometheus.go ファイルの表示

@@ -0,0 +1,80 @@
1
+package stats
2
+
3
+import (
4
+	"time"
5
+
6
+	"github.com/juju/errors"
7
+	"github.com/prometheus/client_golang/prometheus"
8
+
9
+	"github.com/9seconds/mtg/config"
10
+)
11
+
12
+const prometheusPollTime = time.Second
13
+
14
+type prometheusExporter struct {
15
+	connections *prometheus.GaugeVec
16
+	traffic     *prometheus.GaugeVec
17
+	speed       *prometheus.GaugeVec
18
+	crashes     prometheus.Gauge
19
+}
20
+
21
+func (p *prometheusExporter) run() {
22
+	for range time.Tick(prometheusPollTime) {
23
+		instance := GetStats()
24
+
25
+		p.connections.WithLabelValues("abridged", "v4").Set(float64(instance.Connections.Abridged.IPv4))
26
+		p.connections.WithLabelValues("abridged", "v6").Set(float64(instance.Connections.Abridged.IPv6))
27
+		p.connections.WithLabelValues("intermediate", "v4").Set(float64(instance.Connections.Intermediate.IPv4))
28
+		p.connections.WithLabelValues("intermediate", "v6").Set(float64(instance.Connections.Intermediate.IPv6))
29
+		p.connections.WithLabelValues("secure", "v4").Set(float64(instance.Connections.Secure.IPv4))
30
+		p.connections.WithLabelValues("secure", "v6").Set(float64(instance.Connections.Secure.IPv6))
31
+		p.traffic.WithLabelValues("ingress").Set(float64(instance.Traffic.ingress))
32
+		p.traffic.WithLabelValues("egress").Set(float64(instance.Traffic.egress))
33
+		p.speed.WithLabelValues("ingress").Set(float64(instance.Speed.ingress))
34
+		p.speed.WithLabelValues("egress").Set(float64(instance.Speed.egress))
35
+		p.crashes.Set(float64(instance.Crashes))
36
+	}
37
+}
38
+
39
+func newPrometheus(conf *config.Config) (*prometheusExporter, error) {
40
+	connections := prometheus.NewGaugeVec(prometheus.GaugeOpts{
41
+		Namespace: conf.Prometheus.Prefix,
42
+		Name:      "connections",
43
+		Help:      "Current number of connections to the proxy.",
44
+	}, []string{"type", "protocol"})
45
+	traffic := prometheus.NewGaugeVec(prometheus.GaugeOpts{
46
+		Namespace: conf.Prometheus.Prefix,
47
+		Name:      "traffic",
48
+		Help:      "Traffic passed through the proxy in bytes.",
49
+	}, []string{"direction"})
50
+	speed := prometheus.NewGaugeVec(prometheus.GaugeOpts{
51
+		Namespace: conf.Prometheus.Prefix,
52
+		Name:      "speed",
53
+		Help:      "Current throughput in bytes per second.",
54
+	}, []string{"direction"})
55
+	crashes := prometheus.NewGauge(prometheus.GaugeOpts{
56
+		Namespace: conf.Prometheus.Prefix,
57
+		Name:      "crashes",
58
+		Help:      "How many crashes happened.",
59
+	})
60
+
61
+	if err := prometheus.Register(connections); err != nil {
62
+		return nil, errors.Annotate(err, "Cannot register connections collector")
63
+	}
64
+	if err := prometheus.Register(traffic); err != nil {
65
+		return nil, errors.Annotate(err, "cannot register traffic collector")
66
+	}
67
+	if err := prometheus.Register(speed); err != nil {
68
+		return nil, errors.Annotate(err, "cannot register speed collector")
69
+	}
70
+	if err := prometheus.Register(crashes); err != nil {
71
+		return nil, errors.Annotate(err, "cannot register crashes collector")
72
+	}
73
+
74
+	return &prometheusExporter{
75
+		connections: connections,
76
+		traffic:     traffic,
77
+		speed:       speed,
78
+		crashes:     crashes,
79
+	}, nil
80
+}

+ 2
- 0
stats/server.go ファイルの表示

@@ -4,6 +4,7 @@ import (
4 4
 	"encoding/json"
5 5
 	"net/http"
6 6
 
7
+	"github.com/prometheus/client_golang/prometheus/promhttp"
7 8
 	"go.uber.org/zap"
8 9
 
9 10
 	"github.com/9seconds/mtg/config"
@@ -32,6 +33,7 @@ func startServer(conf *config.Config) {
32 33
 			log.Errorw("Cannot encode json", "error", err)
33 34
 		}
34 35
 	})
36
+	http.Handle("/prometheus/", promhttp.Handler())
35 37
 
36 38
 	if err := http.ListenAndServe(conf.StatAddr(), nil); err != nil {
37 39
 		log.Fatalw("Stats server has been stopped", "error", err)

読み込み中…
キャンセル
保存