From ff4be53d942aff04b16ec67e1cd5ee7d12292627 Mon Sep 17 00:00:00 2001 From: 9seconds Date: Mon, 9 Jul 2018 09:14:11 +0300 Subject: [PATCH] Add base stats --- Gopkg.lock | 8 ++++- Gopkg.toml | 4 +++ main.go | 5 +++- stats/server.go | 39 +++++++++++++++++++++++++ stats/stats.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 stats/server.go create mode 100644 stats/stats.go diff --git a/Gopkg.lock b/Gopkg.lock index 88ad0e6..cb43617 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -22,6 +22,12 @@ revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" +[[projects]] + branch = "master" + name = "github.com/dustin/go-humanize" + packages = ["."] + revision = "02af3965c54e8cacf948b97fef38925c4120652c" + [[projects]] branch = "master" name = "github.com/juju/errors" @@ -80,6 +86,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "24afdd6b64331aeba47fed75918d04032e13e404612cac107bad1d68a5038b72" + inputs-digest = "312c9fb15085cbe9660443b15a07981990e1f70ec3ddfcce1b7e6cd5902307da" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index ed9feb4..ec43ce8 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -44,3 +44,7 @@ [[constraint]] name = "github.com/satori/go.uuid" version = "1.2.0" + +[[constraint]] + branch = "master" + name = "github.com/dustin/go-humanize" diff --git a/main.go b/main.go index c0ffba1..2e06549 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "github.com/9seconds/mtg/config" "github.com/9seconds/mtg/proxy" + "github.com/9seconds/mtg/stats" "github.com/juju/errors" ) @@ -115,13 +116,15 @@ func main() { zap.ReplaceGlobals(logger) defer logger.Sync() + printURLs(conf.GetURLs()) + if conf.UseMiddleProxy() { zap.S().Infow("Use middle proxy connection to Telegram") } else { zap.S().Infow("Use direct connection to Telegram") } - printURLs(conf.GetURLs()) + go stats.Start(conf) server := proxy.NewProxy(conf) if err := server.Serve(); err != nil { diff --git a/stats/server.go b/stats/server.go new file mode 100644 index 0000000..c3935d2 --- /dev/null +++ b/stats/server.go @@ -0,0 +1,39 @@ +package stats + +import ( + "encoding/json" + "net/http" + "sync" + "time" + + "github.com/9seconds/mtg/config" +) + +var instance *stats + +func Start(conf *config.Config) { + instance = &stats{ + URLs: conf.GetURLs(), + Uptime: uptime(time.Now()), + speedCurrent: &speed{}, + mutex: &sync.RWMutex{}, + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + + instance.mutex.Lock() + first, _ := json.Marshal(instance) + instance.mutex.Unlock() + + interm := map[string]interface{}{} + json.Unmarshal(first, &interm) + + encoder := json.NewEncoder(w) + encoder.SetEscapeHTML(false) + encoder.SetIndent("", " ") + encoder.Encode(interm) + }) + + http.ListenAndServe(conf.StatAddr(), nil) +} diff --git a/stats/stats.go b/stats/stats.go new file mode 100644 index 0000000..4754674 --- /dev/null +++ b/stats/stats.go @@ -0,0 +1,77 @@ +package stats + +import ( + "encoding/json" + "fmt" + "strconv" + "sync" + "time" + + humanize "github.com/dustin/go-humanize" + + "github.com/9seconds/mtg/config" +) + +type uptime time.Time + +func (u uptime) MarshalJSON() ([]byte, error) { + duration := time.Since(time.Time(u)) + value := map[string]string{ + "seconds": strconv.Itoa(int(duration.Seconds())), + "human": humanize.Time(time.Time(u)), + } + + return json.Marshal(value) +} + +type trafficValue uint64 + +func (t trafficValue) MarshalJSON() ([]byte, error) { + tv := uint64(t) + value := map[string]interface{}{ + "bytes": tv, + "human": humanize.Bytes(tv), + } + + return json.Marshal(value) +} + +type trafficSpeedValue uint64 + +func (t trafficSpeedValue) MarshalJSON() ([]byte, error) { + speed := uint64(t) + value := map[string]interface{}{ + "bytes/s": speed, + "human": fmt.Sprintf("%s/S", humanize.Bytes(speed)), + } + + return json.Marshal(value) +} + +type connections struct { + All uint32 `json:"all"` + Abridged uint32 `json:"abridged"` + Intermediate uint32 `json:"intermediate"` +} + +type traffic struct { + Ingress trafficValue `json:"ingress"` + Egress trafficValue `json:"egress"` +} + +type speed struct { + Ingress trafficSpeedValue `json:"ingress"` + Egress trafficSpeedValue `json:"egress"` +} + +type stats struct { + URLs config.IPURLs `json:"urls"` + ActiveConnections connections `json:"active_connections"` + AllConnections connections `json:"all_connections"` + Traffic traffic `json:"traffic"` + Speed speed `json:"speed"` + Uptime uptime `json:"uptime"` + + speedCurrent *speed + mutex *sync.RWMutex +}