mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 16:01:55 +03:00
Generated
+7
-1
@@ -100,9 +100,15 @@
|
|||||||
revision = "947dcec5ba9c011838740e680966fd7087a71d0d"
|
revision = "947dcec5ba9c011838740e680966fd7087a71d0d"
|
||||||
version = "v2.2.6"
|
version = "v2.2.6"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/alexcesaro/statsd.v2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "7fea3f0d2fab1ad973e641e51dba45443a311a90"
|
||||||
|
version = "v2.0.0"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "f828340a30ea13c563829f9a37d0ff62974d4578411c9be02e61125dbdf98692"
|
inputs-digest = "7fad0f62feb7737b064d85cc4333a1a3e9298faec2afd864b4404f515fc7f17c"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|||||||
@@ -52,3 +52,7 @@
|
|||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/beevik/ntp"
|
name = "github.com/beevik/ntp"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "gopkg.in/alexcesaro/statsd.v2"
|
||||||
|
version = "2.0.0"
|
||||||
|
|||||||
@@ -145,3 +145,33 @@ You will have this tool up and running on port 3128. Now curl
|
|||||||
port 3129 will show you some statistics if you are interested in.
|
port 3129 will show you some statistics if you are interested in.
|
||||||
|
|
||||||
Also, you can use [run-mtg.sh](https://github.com/9seconds/mtg/blob/master/run-mtg.sh) script
|
Also, you can use [run-mtg.sh](https://github.com/9seconds/mtg/blob/master/run-mtg.sh) script
|
||||||
|
|
||||||
|
|
||||||
|
# statsd integration
|
||||||
|
|
||||||
|
mtg provides an integration with statsd, you can enable it with command
|
||||||
|
line interface. To enable it, you have to provide IP address of statsd
|
||||||
|
service.
|
||||||
|
|
||||||
|
Out of the box, mtg supports 2 additional dialects: [InfluxDB](https://www.influxdata.com/blog/getting-started-with-sending-statsd-metrics-to-telegraf-influxdb/)
|
||||||
|
and [Datadog](https://docs.datadoghq.com/developers/dogstatsd/).
|
||||||
|
|
||||||
|
All metrics are gauges. Here is the list of metrics and their meaning:
|
||||||
|
|
||||||
|
| Metric name | Unit | Description |
|
||||||
|
|---------------------------------|---------|-----------------------------------------------------------|
|
||||||
|
| `connections.abridged.ipv4` | number | The number of active abridged IPv4 connections |
|
||||||
|
| `connections.abridged.ipv6` | number | The number of active abridged IPv6 connections |
|
||||||
|
| `connections.intermediate.ipv4` | number | The number of active intermediate IPv4 connections |
|
||||||
|
| `connections.intermediate.ipv6` | number | The number of active intermediate IPv6 connections |
|
||||||
|
| `connections.secure.ipv4` | number | The number of active secure intermediate IPv4 connections |
|
||||||
|
| `connections.secure.ipv6` | number | The number of active secure intermediate IPv6 connections |
|
||||||
|
| `crashes` | number | An amount of crashes in client handlers |
|
||||||
|
| `traffic.ingress` | bytes | Ingress traffic from the start of application (incoming) |
|
||||||
|
| `traffic.egress` | bytes | Egress traffic from the start of application (outgoing) |
|
||||||
|
| `speed.ingress` | bytes/s | Ingress bandwidth of the latest second (incoming traffic) |
|
||||||
|
| `speed.egress` | bytes/s | Egress bandwidth of the latest second (outgoing traffic) |
|
||||||
|
|
||||||
|
All metrics are prefixed with given prefix. Default prefix is `mtg`.
|
||||||
|
With such prefix metric name `traffic.ingress`, for example, would be
|
||||||
|
`mtg.traffic.ingress`.
|
||||||
|
|||||||
+43
-1
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
statsd "gopkg.in/alexcesaro/statsd.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Buffer sizes define internal socket buffer sizes.
|
// Buffer sizes define internal socket buffer sizes.
|
||||||
@@ -32,6 +33,14 @@ type Config struct {
|
|||||||
PublicIPv6 net.IP
|
PublicIPv6 net.IP
|
||||||
StatsIP net.IP
|
StatsIP net.IP
|
||||||
|
|
||||||
|
StatsD struct {
|
||||||
|
Addr net.Addr
|
||||||
|
Prefix string
|
||||||
|
Tags map[string]string
|
||||||
|
TagsFormat statsd.TagFormat
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
Secret []byte
|
Secret []byte
|
||||||
AdTag []byte
|
AdTag []byte
|
||||||
}
|
}
|
||||||
@@ -109,7 +118,9 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
|
|||||||
publicIPv4 net.IP, PublicIPv4Port uint16,
|
publicIPv4 net.IP, PublicIPv4Port uint16,
|
||||||
publicIPv6 net.IP, publicIPv6Port uint16,
|
publicIPv6 net.IP, publicIPv6Port uint16,
|
||||||
statsIP net.IP, statsPort uint16,
|
statsIP net.IP, statsPort uint16,
|
||||||
secret, adtag string) (*Config, error) {
|
secret, adtag string,
|
||||||
|
statsdIP string, statsdPort uint16, statsdNetwork string, statsdPrefix string,
|
||||||
|
statsdTagsFormat string, statsdTags map[string]string) (*Config, error) {
|
||||||
secureMode := false
|
secureMode := false
|
||||||
if strings.HasPrefix(secret, "dd") && len(secret) == 34 {
|
if strings.HasPrefix(secret, "dd") && len(secret) == 34 {
|
||||||
secureMode = true
|
secureMode = true
|
||||||
@@ -174,5 +185,36 @@ func NewConfig(debug, verbose bool, // nolint: gocyclo
|
|||||||
SecureMode: secureMode,
|
SecureMode: secureMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if statsdIP != "" {
|
||||||
|
conf.StatsD.Enabled = true
|
||||||
|
conf.StatsD.Prefix = statsdPrefix
|
||||||
|
conf.StatsD.Tags = statsdTags
|
||||||
|
|
||||||
|
var addr net.Addr
|
||||||
|
hostPort := net.JoinHostPort(statsdIP, strconv.Itoa(int(statsdPort)))
|
||||||
|
switch statsdNetwork {
|
||||||
|
case "tcp":
|
||||||
|
addr, err = net.ResolveTCPAddr("tcp", hostPort)
|
||||||
|
case "udp":
|
||||||
|
addr, err = net.ResolveUDPAddr("udp", hostPort)
|
||||||
|
default:
|
||||||
|
err = errors.Errorf("Unknown network %s", statsdNetwork)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Annotate(err, "Cannot resolve statsd address")
|
||||||
|
}
|
||||||
|
conf.StatsD.Addr = addr
|
||||||
|
|
||||||
|
switch statsdTagsFormat {
|
||||||
|
case "datadog":
|
||||||
|
conf.StatsD.TagsFormat = statsd.Datadog
|
||||||
|
case "influxdb":
|
||||||
|
conf.StatsD.TagsFormat = statsd.InfluxDB
|
||||||
|
case "":
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("Unknown tags format %s", statsdTagsFormat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ var (
|
|||||||
Envar("MTG_IPV6_PORT").
|
Envar("MTG_IPV6_PORT").
|
||||||
Uint16()
|
Uint16()
|
||||||
|
|
||||||
statsIP = app.Flag("stats-ip", "Which IP bind stats server to").
|
statsIP = app.Flag("stats-ip", "Which IP bind stats server to.").
|
||||||
Short('t').
|
Short('t').
|
||||||
Envar("MTG_STATS_IP").
|
Envar("MTG_STATS_IP").
|
||||||
Default("127.0.0.1").
|
Default("127.0.0.1").
|
||||||
@@ -72,6 +72,28 @@ var (
|
|||||||
Default("3129").
|
Default("3129").
|
||||||
Uint16()
|
Uint16()
|
||||||
|
|
||||||
|
statsdIP = app.Flag("statsd-ip", "Which IP should we use for working with statsd.").
|
||||||
|
Envar("MTG_STATSD_IP").
|
||||||
|
String()
|
||||||
|
statsdPort = app.Flag("statsd-port", "Which port should we use for working with statsd.").
|
||||||
|
Envar("MTG_STATSD_PORT").
|
||||||
|
Default("8125").
|
||||||
|
Uint16()
|
||||||
|
statsdNetwork = app.Flag("statsd-network", "Which network is used to work with statsd. Only 'tcp' and 'udp' are supported.").
|
||||||
|
Envar("MTG_STATSD_NETWORK").
|
||||||
|
Default("udp").
|
||||||
|
String()
|
||||||
|
statsdPrefix = app.Flag("statsd-prefix", "Which bucket prefix should we use for sending stats to statsd.").
|
||||||
|
Envar("MTG_STATSD_PREFIX").
|
||||||
|
Default("mtg").
|
||||||
|
String()
|
||||||
|
statsdTagsFormat = app.Flag("statsd-tags-format", "Which tag format should we use to send stats metrics. Valid options are 'datadog' and 'influxdb'.").
|
||||||
|
Envar("MTG_STATSD_TAGS_FORMAT").
|
||||||
|
String()
|
||||||
|
statsdTags = app.Flag("statsd-tags", "Tags to use for working with statsd (specified as 'key=value').").
|
||||||
|
Envar("MTG_STATSD_TAGS").
|
||||||
|
StringMap()
|
||||||
|
|
||||||
secret = app.Arg("secret", "Secret of this proxy.").Required().String()
|
secret = app.Arg("secret", "Secret of this proxy.").Required().String()
|
||||||
adtag = app.Arg("adtag", "ADTag of the proxy.").String()
|
adtag = app.Arg("adtag", "ADTag of the proxy.").String()
|
||||||
)
|
)
|
||||||
@@ -96,6 +118,8 @@ func main() {
|
|||||||
*publicIPv6, *publicIPv6Port,
|
*publicIPv6, *publicIPv6Port,
|
||||||
*statsIP, *statsPort,
|
*statsIP, *statsPort,
|
||||||
*secret, *adtag,
|
*secret, *adtag,
|
||||||
|
*statsdIP, *statsdPort, *statsdNetwork, *statsdPrefix,
|
||||||
|
*statsdTagsFormat, *statsdTags,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
usage(err.Error())
|
usage(err.Error())
|
||||||
@@ -134,7 +158,9 @@ func main() {
|
|||||||
zap.S().Infow("Use direct connection to Telegram")
|
zap.S().Infow("Use direct connection to Telegram")
|
||||||
}
|
}
|
||||||
|
|
||||||
go stats.Start(conf)
|
if err := stats.Start(conf); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
server := proxy.NewProxy(conf)
|
server := proxy.NewProxy(conf)
|
||||||
if err := server.Serve(); err != nil {
|
if err := server.Serve(); err != nil {
|
||||||
|
|||||||
+13
-1
@@ -14,7 +14,7 @@ import (
|
|||||||
var instance *stats
|
var instance *stats
|
||||||
|
|
||||||
// Start starts new statisitcs server.
|
// Start starts new statisitcs server.
|
||||||
func Start(conf *config.Config) {
|
func Start(conf *config.Config) error {
|
||||||
log := zap.S().Named("stats")
|
log := zap.S().Named("stats")
|
||||||
|
|
||||||
instance = &stats{
|
instance = &stats{
|
||||||
@@ -23,6 +23,14 @@ func Start(conf *config.Config) {
|
|||||||
mutex: &sync.RWMutex{},
|
mutex: &sync.RWMutex{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.StatsD.Enabled {
|
||||||
|
client, err := newStatsd(conf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go client.run()
|
||||||
|
}
|
||||||
|
|
||||||
go crashManager()
|
go crashManager()
|
||||||
go connectionManager()
|
go connectionManager()
|
||||||
go trafficManager()
|
go trafficManager()
|
||||||
@@ -51,7 +59,11 @@ func Start(conf *config.Config) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
go func() {
|
||||||
if err := http.ListenAndServe(conf.StatAddr(), nil); err != nil {
|
if err := http.ListenAndServe(conf.StatAddr(), nil); err != nil {
|
||||||
log.Fatalw("Stats server has been stopped", "error", err)
|
log.Fatalw("Stats server has been stopped", "error", err)
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package stats
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
statsd "gopkg.in/alexcesaro/statsd.v2"
|
||||||
|
|
||||||
|
"github.com/9seconds/mtg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
statsdConnectionsAbridgedV4 = "connections.abridged.ipv4"
|
||||||
|
statsdConnectionsAbridgedV6 = "connections.abridged.ipv6"
|
||||||
|
|
||||||
|
statsdConnectionsIntermediateV4 = "connections.intermediate.ipv4"
|
||||||
|
statsdConnectionsIntermediateV6 = "connections.intermediate.ipv6"
|
||||||
|
|
||||||
|
statsdConnectionsSecureV4 = "connections.secure.ipv4"
|
||||||
|
statsdConnectionsSecureV6 = "connections.secure.ipv6"
|
||||||
|
|
||||||
|
statsdTrafficIngress = "traffic.ingress"
|
||||||
|
statsdTrafficEgress = "traffic.egress"
|
||||||
|
|
||||||
|
statsdSpeedIngress = "speed.ingress"
|
||||||
|
statsdSpeedEgress = "speed.egress"
|
||||||
|
|
||||||
|
statsdCrashes = "crashes"
|
||||||
|
)
|
||||||
|
|
||||||
|
const statsdPollTime = time.Second
|
||||||
|
|
||||||
|
type statsdExporter struct {
|
||||||
|
client *statsd.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *statsdExporter) run() {
|
||||||
|
for range time.Tick(statsdPollTime) {
|
||||||
|
instance.mutex.Lock()
|
||||||
|
|
||||||
|
s.client.Gauge(statsdConnectionsAbridgedV4, instance.Connections.Abridged.IPv4)
|
||||||
|
s.client.Gauge(statsdConnectionsAbridgedV6, instance.Connections.Abridged.IPv6)
|
||||||
|
s.client.Gauge(statsdConnectionsIntermediateV4, instance.Connections.Intermediate.IPv4)
|
||||||
|
s.client.Gauge(statsdConnectionsIntermediateV6, instance.Connections.Intermediate.IPv6)
|
||||||
|
s.client.Gauge(statsdConnectionsSecureV4, instance.Connections.Secure.IPv4)
|
||||||
|
s.client.Gauge(statsdConnectionsSecureV6, instance.Connections.Secure.IPv6)
|
||||||
|
s.client.Gauge(statsdTrafficIngress, uint64(instance.Traffic.Ingress))
|
||||||
|
s.client.Gauge(statsdTrafficEgress, uint64(instance.Traffic.Egress))
|
||||||
|
s.client.Gauge(statsdSpeedIngress, uint64(instance.Speed.Ingress))
|
||||||
|
s.client.Gauge(statsdSpeedEgress, uint64(instance.Speed.Egress))
|
||||||
|
s.client.Gauge(statsdCrashes, instance.Crashes)
|
||||||
|
|
||||||
|
instance.mutex.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStatsd(conf *config.Config) (*statsdExporter, error) {
|
||||||
|
options := []statsd.Option{
|
||||||
|
statsd.Network(conf.StatsD.Addr.Network()),
|
||||||
|
statsd.Address(conf.StatsD.Addr.String()),
|
||||||
|
statsd.Prefix(conf.StatsD.Prefix),
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.StatsD.TagsFormat > 0 {
|
||||||
|
options = append(options, statsd.TagsFormat(conf.StatsD.TagsFormat))
|
||||||
|
tags := make([]string, len(conf.StatsD.Tags)*2)
|
||||||
|
for k, v := range conf.StatsD.Tags {
|
||||||
|
tags = append(tags, k, v)
|
||||||
|
}
|
||||||
|
options = append(options, statsd.Tags(tags...))
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := statsd.New(options...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Annotate(err, "Cannot create statsd client")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &statsdExporter{client: client}, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user