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
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

stats_json.go 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package stats
  2. import (
  3. "encoding/json"
  4. "net"
  5. "net/http"
  6. "strconv"
  7. "sync/atomic"
  8. "time"
  9. "go.uber.org/zap"
  10. "github.com/9seconds/mtg/conntypes"
  11. )
  12. type statsJSON struct {
  13. Connections statsJSONConnections `json:"connections"`
  14. Traffic statsJSONTraffic `json:"traffic"`
  15. Uptime statsJSONUptime `json:"uptime"`
  16. Crashes uint32 `json:"crashes"`
  17. AntiReplays uint32 `json:"anti_replay_detected"`
  18. }
  19. type statsBaseJSONConnections struct {
  20. All statsJSONConnectionType `json:"all"`
  21. Abridged statsJSONConnectionType `json:"abridged"`
  22. Intermediate statsJSONConnectionType `json:"intermediate"`
  23. Secured statsJSONConnectionType `json:"secured"`
  24. }
  25. type statsJSONConnections struct {
  26. statsBaseJSONConnections
  27. }
  28. type statsJSONConnectionType struct {
  29. IPv4 uint32 `json:"ipv4"`
  30. IPv6 uint32 `json:"ipv6"`
  31. }
  32. func (c statsJSONConnections) MarshalJSON() ([]byte, error) {
  33. c.All.IPv4 = c.Abridged.IPv4 + c.Intermediate.IPv4 + c.Secured.IPv4
  34. c.All.IPv6 = c.Abridged.IPv6 + c.Intermediate.IPv6 + c.Secured.IPv6
  35. return json.Marshal(c.statsBaseJSONConnections)
  36. }
  37. type statsJSONTraffic struct {
  38. Ingress uint64 `json:"ingress"`
  39. Egress uint64 `json:"egress"`
  40. }
  41. type statsJSONUptime time.Time
  42. func (s statsJSONUptime) MarshalJSON() ([]byte, error) {
  43. seconds := strconv.Itoa(int(time.Since(time.Time(s)).Seconds()))
  44. return []byte(seconds), nil
  45. }
  46. func (s *statsJSON) IngressTraffic(traffic int) {
  47. atomic.AddUint64(&s.Traffic.Ingress, uint64(traffic))
  48. }
  49. func (s *statsJSON) EgressTraffic(traffic int) {
  50. atomic.AddUint64(&s.Traffic.Egress, uint64(traffic))
  51. }
  52. func (s *statsJSON) ClientConnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) {
  53. s.changeConnections(connectionType, addr, 1)
  54. }
  55. func (s *statsJSON) ClientDisconnected(connectionType conntypes.ConnectionType, addr *net.TCPAddr) {
  56. s.changeConnections(connectionType, addr, ^uint32(0))
  57. }
  58. func (s *statsJSON) changeConnections(connectionType conntypes.ConnectionType, addr *net.TCPAddr, value uint32) {
  59. var connections *statsJSONConnectionType
  60. switch connectionType {
  61. case conntypes.ConnectionTypeAbridged:
  62. connections = &s.Connections.Abridged
  63. case conntypes.ConnectionTypeSecure:
  64. connections = &s.Connections.Secured
  65. default:
  66. connections = &s.Connections.Intermediate
  67. }
  68. if addr.IP.To4() != nil {
  69. atomic.AddUint32(&connections.IPv4, value)
  70. } else {
  71. atomic.AddUint32(&connections.IPv6, value)
  72. }
  73. }
  74. func (s *statsJSON) Crash() {
  75. atomic.AddUint32(&s.Crashes, 1)
  76. }
  77. func (s *statsJSON) AntiReplayDetected() {
  78. atomic.AddUint32(&s.AntiReplays, 1)
  79. }
  80. func newStatsJSON(mux *http.ServeMux) Stats {
  81. instance := &statsJSON{
  82. Uptime: statsJSONUptime(time.Now()),
  83. }
  84. logger := zap.S().Named("stats")
  85. mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
  86. w.Header().Set("Content-Type", "application/json")
  87. first, err := json.Marshal(instance)
  88. if err != nil {
  89. logger.Errorw("Cannot encode json", "error", err)
  90. http.Error(w, "Internal server error", http.StatusServiceUnavailable)
  91. return
  92. }
  93. interim := map[string]interface{}{}
  94. if err := json.Unmarshal(first, &interim); err != nil {
  95. panic(err)
  96. }
  97. encoder := json.NewEncoder(w)
  98. encoder.SetEscapeHTML(false)
  99. encoder.SetIndent("", " ")
  100. if err := encoder.Encode(interim); err != nil {
  101. logger.Errorw("Cannot encode json", "error", err)
  102. }
  103. })
  104. return instance
  105. }