9seconds 7 лет назад
Родитель
Сommit
ff4be53d94
5 измененных файлов: 131 добавлений и 2 удалений
  1. 7
    1
      Gopkg.lock
  2. 4
    0
      Gopkg.toml
  3. 4
    1
      main.go
  4. 39
    0
      stats/server.go
  5. 77
    0
      stats/stats.go

+ 7
- 1
Gopkg.lock Просмотреть файл

22
   revision = "346938d642f2ec3594ed81d874461961cd0faa76"
22
   revision = "346938d642f2ec3594ed81d874461961cd0faa76"
23
   version = "v1.1.0"
23
   version = "v1.1.0"
24
 
24
 
25
+[[projects]]
26
+  branch = "master"
27
+  name = "github.com/dustin/go-humanize"
28
+  packages = ["."]
29
+  revision = "02af3965c54e8cacf948b97fef38925c4120652c"
30
+
25
 [[projects]]
31
 [[projects]]
26
   branch = "master"
32
   branch = "master"
27
   name = "github.com/juju/errors"
33
   name = "github.com/juju/errors"
80
 [solve-meta]
86
 [solve-meta]
81
   analyzer-name = "dep"
87
   analyzer-name = "dep"
82
   analyzer-version = 1
88
   analyzer-version = 1
83
-  inputs-digest = "24afdd6b64331aeba47fed75918d04032e13e404612cac107bad1d68a5038b72"
89
+  inputs-digest = "312c9fb15085cbe9660443b15a07981990e1f70ec3ddfcce1b7e6cd5902307da"
84
   solver-name = "gps-cdcl"
90
   solver-name = "gps-cdcl"
85
   solver-version = 1
91
   solver-version = 1

+ 4
- 0
Gopkg.toml Просмотреть файл

44
 [[constraint]]
44
 [[constraint]]
45
   name = "github.com/satori/go.uuid"
45
   name = "github.com/satori/go.uuid"
46
   version = "1.2.0"
46
   version = "1.2.0"
47
+
48
+[[constraint]]
49
+  branch = "master"
50
+  name = "github.com/dustin/go-humanize"

+ 4
- 1
main.go Просмотреть файл

16
 
16
 
17
 	"github.com/9seconds/mtg/config"
17
 	"github.com/9seconds/mtg/config"
18
 	"github.com/9seconds/mtg/proxy"
18
 	"github.com/9seconds/mtg/proxy"
19
+	"github.com/9seconds/mtg/stats"
19
 	"github.com/juju/errors"
20
 	"github.com/juju/errors"
20
 )
21
 )
21
 
22
 
115
 	zap.ReplaceGlobals(logger)
116
 	zap.ReplaceGlobals(logger)
116
 	defer logger.Sync()
117
 	defer logger.Sync()
117
 
118
 
119
+	printURLs(conf.GetURLs())
120
+
118
 	if conf.UseMiddleProxy() {
121
 	if conf.UseMiddleProxy() {
119
 		zap.S().Infow("Use middle proxy connection to Telegram")
122
 		zap.S().Infow("Use middle proxy connection to Telegram")
120
 	} else {
123
 	} else {
121
 		zap.S().Infow("Use direct connection to Telegram")
124
 		zap.S().Infow("Use direct connection to Telegram")
122
 	}
125
 	}
123
 
126
 
124
-	printURLs(conf.GetURLs())
127
+	go stats.Start(conf)
125
 
128
 
126
 	server := proxy.NewProxy(conf)
129
 	server := proxy.NewProxy(conf)
127
 	if err := server.Serve(); err != nil {
130
 	if err := server.Serve(); err != nil {

+ 39
- 0
stats/server.go Просмотреть файл

1
+package stats
2
+
3
+import (
4
+	"encoding/json"
5
+	"net/http"
6
+	"sync"
7
+	"time"
8
+
9
+	"github.com/9seconds/mtg/config"
10
+)
11
+
12
+var instance *stats
13
+
14
+func Start(conf *config.Config) {
15
+	instance = &stats{
16
+		URLs:         conf.GetURLs(),
17
+		Uptime:       uptime(time.Now()),
18
+		speedCurrent: &speed{},
19
+		mutex:        &sync.RWMutex{},
20
+	}
21
+
22
+	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
23
+		w.Header().Set("Content-Type", "application/json")
24
+
25
+		instance.mutex.Lock()
26
+		first, _ := json.Marshal(instance)
27
+		instance.mutex.Unlock()
28
+
29
+		interm := map[string]interface{}{}
30
+		json.Unmarshal(first, &interm)
31
+
32
+		encoder := json.NewEncoder(w)
33
+		encoder.SetEscapeHTML(false)
34
+		encoder.SetIndent("", "  ")
35
+		encoder.Encode(interm)
36
+	})
37
+
38
+	http.ListenAndServe(conf.StatAddr(), nil)
39
+}

+ 77
- 0
stats/stats.go Просмотреть файл

1
+package stats
2
+
3
+import (
4
+	"encoding/json"
5
+	"fmt"
6
+	"strconv"
7
+	"sync"
8
+	"time"
9
+
10
+	humanize "github.com/dustin/go-humanize"
11
+
12
+	"github.com/9seconds/mtg/config"
13
+)
14
+
15
+type uptime time.Time
16
+
17
+func (u uptime) MarshalJSON() ([]byte, error) {
18
+	duration := time.Since(time.Time(u))
19
+	value := map[string]string{
20
+		"seconds": strconv.Itoa(int(duration.Seconds())),
21
+		"human":   humanize.Time(time.Time(u)),
22
+	}
23
+
24
+	return json.Marshal(value)
25
+}
26
+
27
+type trafficValue uint64
28
+
29
+func (t trafficValue) MarshalJSON() ([]byte, error) {
30
+	tv := uint64(t)
31
+	value := map[string]interface{}{
32
+		"bytes": tv,
33
+		"human": humanize.Bytes(tv),
34
+	}
35
+
36
+	return json.Marshal(value)
37
+}
38
+
39
+type trafficSpeedValue uint64
40
+
41
+func (t trafficSpeedValue) MarshalJSON() ([]byte, error) {
42
+	speed := uint64(t)
43
+	value := map[string]interface{}{
44
+		"bytes/s": speed,
45
+		"human":   fmt.Sprintf("%s/S", humanize.Bytes(speed)),
46
+	}
47
+
48
+	return json.Marshal(value)
49
+}
50
+
51
+type connections struct {
52
+	All          uint32 `json:"all"`
53
+	Abridged     uint32 `json:"abridged"`
54
+	Intermediate uint32 `json:"intermediate"`
55
+}
56
+
57
+type traffic struct {
58
+	Ingress trafficValue `json:"ingress"`
59
+	Egress  trafficValue `json:"egress"`
60
+}
61
+
62
+type speed struct {
63
+	Ingress trafficSpeedValue `json:"ingress"`
64
+	Egress  trafficSpeedValue `json:"egress"`
65
+}
66
+
67
+type stats struct {
68
+	URLs              config.IPURLs `json:"urls"`
69
+	ActiveConnections connections   `json:"active_connections"`
70
+	AllConnections    connections   `json:"all_connections"`
71
+	Traffic           traffic       `json:"traffic"`
72
+	Speed             speed         `json:"speed"`
73
+	Uptime            uptime        `json:"uptime"`
74
+
75
+	speedCurrent *speed
76
+	mutex        *sync.RWMutex
77
+}

Загрузка…
Отмена
Сохранить