Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package stats
  2. import (
  3. "fmt"
  4. "net"
  5. "strings"
  6. "time"
  7. "github.com/9seconds/mtg/v2/events"
  8. "github.com/9seconds/mtg/v2/mtglib"
  9. statsd "github.com/smira/go-statsd"
  10. )
  11. type statsdFakeLogger struct{}
  12. func (s statsdFakeLogger) Printf(msg string, args ...interface{}) {}
  13. type statsdStreamInfo struct {
  14. createdAt time.Time
  15. clientIP net.IP
  16. }
  17. func (s *statsdStreamInfo) ClientIPTag() statsd.Tag {
  18. if s.clientIP.To4() == nil {
  19. return statsd.StringTag(TagIPType, TagIPTypeIPv6)
  20. } else {
  21. return statsd.StringTag(TagIPType, TagIPTypeIPv4)
  22. }
  23. }
  24. type statsdProcessor struct {
  25. streams map[string]*statsdStreamInfo
  26. client *statsd.Client
  27. }
  28. func (s statsdProcessor) EventStart(evt mtglib.EventStart) {
  29. clientInfo := &statsdStreamInfo{
  30. createdAt: evt.CreatedAt,
  31. clientIP: evt.RemoteIP,
  32. }
  33. s.streams[evt.StreamID()] = clientInfo
  34. s.client.GaugeDelta(MetricActiveConnection, 1, clientInfo.ClientIPTag())
  35. }
  36. func (s statsdProcessor) EventFinish(evt mtglib.EventFinish) {
  37. clientInfo, ok := s.streams[evt.StreamID()]
  38. if !ok {
  39. return
  40. }
  41. defer delete(s.streams, evt.StreamID())
  42. duration := evt.CreatedAt.Sub(clientInfo.createdAt)
  43. s.client.GaugeDelta(MetricActiveConnection, -1, clientInfo.ClientIPTag())
  44. s.client.PrecisionTiming(MetricSessionDuration, duration)
  45. }
  46. func (s statsdProcessor) EventConcurrencyLimited(_ mtglib.EventConcurrencyLimited) {
  47. s.client.Incr(MetricConcurrencyLimited, 1)
  48. }
  49. func (s statsdProcessor) Shutdown() {
  50. now := time.Now()
  51. events := make([]mtglib.EventFinish, 0, len(s.streams))
  52. for k := range s.streams {
  53. events = append(events, mtglib.EventFinish{
  54. CreatedAt: now,
  55. ConnID: k,
  56. })
  57. }
  58. for i := range events {
  59. s.EventFinish(events[i])
  60. }
  61. }
  62. type StatsdFactory struct {
  63. client *statsd.Client
  64. }
  65. func (s StatsdFactory) Close() error {
  66. return s.client.Close()
  67. }
  68. func (s StatsdFactory) Make() events.Observer {
  69. return statsdProcessor{
  70. client: s.client,
  71. streams: make(map[string]*statsdStreamInfo),
  72. }
  73. }
  74. func NewStatsd(address, metricPrefix, tagFormat string) (StatsdFactory, error) {
  75. options := []statsd.Option{
  76. statsd.MetricPrefix(metricPrefix),
  77. statsd.Logger(statsdFakeLogger{}),
  78. }
  79. switch strings.ToLower(tagFormat) {
  80. case "datadog":
  81. options = append(options, statsd.TagStyle(statsd.TagFormatDatadog))
  82. case "influxdb":
  83. options = append(options, statsd.TagStyle(statsd.TagFormatInfluxDB))
  84. case "graphite":
  85. options = append(options, statsd.TagStyle(statsd.TagFormatGraphite))
  86. default:
  87. return StatsdFactory{}, fmt.Errorf("unknown tag format %s", tagFormat)
  88. }
  89. return StatsdFactory{
  90. client: statsd.NewClient(address, options...),
  91. }, nil
  92. }