Skip to content

Commit 4cb9abe

Browse files
committed
added service stats
1 parent 6360ba3 commit 4cb9abe

38 files changed

+1415
-650
lines changed

appicon.png

-105 KB
Loading

config/config.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ type Tunnel struct {
103103
Keepalive bool `yaml:",omitempty"`
104104
TTL int `yaml:"ttl,omitempty"`
105105

106+
Stats ServiceStats
106107
Favorite bool
107108
Closed bool
108109
CreatedAt time.Time
@@ -137,3 +138,15 @@ func (c *Config) Write() error {
137138

138139
return os.WriteFile(filepath.Join(configDir, configFile), buf.Bytes(), 0644)
139140
}
141+
142+
type ServiceStats struct {
143+
Time time.Time
144+
TotalConns uint64
145+
RequestRate float64
146+
CurrentConns uint64
147+
TotalErrs uint64
148+
InputBytes uint64
149+
InputRateBytes uint64
150+
OutputBytes uint64
151+
OutputRateBytes uint64
152+
}

go.mod

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,63 @@ module github.com/go-gost/gost.plus
33
go 1.22.0
44

55
require (
6-
gioui.org v0.5.0
7-
gioui.org/x v0.5.0
6+
gioui.org v0.6.0
7+
gioui.org/x v0.6.1
8+
github.com/go-gost/core v0.0.0-20240309124515-fea73cf68235
9+
github.com/go-gost/x v0.0.0-20240131151842-25dcf536c6f5
10+
github.com/google/uuid v1.6.0
811
golang.org/x/exp/shiny v0.0.0-20240103183307-be819d1f06fc
9-
gopkg.in/natefinch/lumberjack.v2 v2.2.1
1012
gopkg.in/yaml.v3 v3.0.1
1113
)
1214

1315
require (
1416
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect
1517
gioui.org/shader v1.0.8 // indirect
16-
github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 // indirect
18+
github.com/beorn7/perks v1.0.1 // indirect
19+
github.com/cespare/xxhash/v2 v2.2.0 // indirect
20+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
21+
github.com/fsnotify/fsnotify v1.7.0 // indirect
22+
github.com/go-gost/gosocks5 v0.4.0 // indirect
23+
github.com/go-gost/plugin v0.0.0-20240103125338-9c84e29cb81a // indirect
24+
github.com/go-gost/relay v0.5.0 // indirect
25+
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 // indirect
26+
github.com/go-redis/redis/v8 v8.11.5 // indirect
27+
github.com/go-text/typesetting v0.1.1 // indirect
28+
github.com/gobwas/glob v0.2.3 // indirect
29+
github.com/golang/protobuf v1.5.3 // indirect
30+
github.com/gorilla/websocket v1.5.1 // indirect
31+
github.com/hashicorp/hcl v1.0.0 // indirect
32+
github.com/magiconair/properties v1.8.7 // indirect
33+
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
34+
github.com/mitchellh/mapstructure v1.5.0 // indirect
35+
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
36+
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
37+
github.com/pires/go-proxyproto v0.7.0 // indirect
38+
github.com/prometheus/client_golang v1.17.0 // indirect
39+
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
40+
github.com/prometheus/common v0.44.0 // indirect
41+
github.com/prometheus/procfs v0.11.1 // indirect
42+
github.com/rs/xid v1.3.0 // indirect
43+
github.com/sagikazarmark/locafero v0.4.0 // indirect
44+
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
45+
github.com/sirupsen/logrus v1.8.1 // indirect
46+
github.com/sourcegraph/conc v0.3.0 // indirect
47+
github.com/spf13/afero v1.11.0 // indirect
48+
github.com/spf13/cast v1.6.0 // indirect
49+
github.com/spf13/pflag v1.0.5 // indirect
50+
github.com/spf13/viper v1.18.2 // indirect
51+
github.com/subosito/gotenv v1.6.0 // indirect
52+
github.com/xtaci/smux v1.5.24 // indirect
53+
github.com/yl2chen/cidranger v1.0.2 // indirect
54+
go.uber.org/multierr v1.11.0 // indirect
1755
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
1856
golang.org/x/image v0.14.0 // indirect
57+
golang.org/x/net v0.19.0 // indirect
1958
golang.org/x/sys v0.18.0 // indirect
2059
golang.org/x/text v0.14.0 // indirect
60+
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
61+
google.golang.org/grpc v1.59.0 // indirect
62+
google.golang.org/protobuf v1.31.0 // indirect
63+
gopkg.in/ini.v1 v1.67.0 // indirect
64+
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
2165
)

go.sum

Lines changed: 144 additions & 9 deletions
Large diffs are not rendered by default.

main.go

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package main
22

33
import (
4+
"context"
45
_ "net"
56
"os"
7+
"time"
68

79
"gioui.org/app"
810
_ "gioui.org/app/permission/storage"
9-
"gioui.org/io/key"
1011
"gioui.org/op"
1112
"github.com/go-gost/core/logger"
1213
"github.com/go-gost/gost.plus/config"
14+
"github.com/go-gost/gost.plus/runner"
15+
"github.com/go-gost/gost.plus/runner/task"
1316
"github.com/go-gost/gost.plus/tunnel"
1417
"github.com/go-gost/gost.plus/tunnel/entrypoint"
1518
"github.com/go-gost/gost.plus/ui"
@@ -20,11 +23,10 @@ func main() {
2023
Init()
2124

2225
go func() {
23-
w := app.NewWindow(
24-
app.Title("GOST+"),
25-
app.MinSize(800, 600),
26-
)
27-
err := run(w)
26+
var w app.Window
27+
w.Option(app.Title("GOST+"))
28+
w.Option(app.MinSize(800, 600))
29+
err := run(&w)
2830
if err != nil {
2931
logger.Default().Fatal(err)
3032
}
@@ -34,20 +36,26 @@ func main() {
3436
}
3537

3638
func run(w *app.Window) error {
39+
go func() {
40+
for e := range runner.Event() {
41+
if e.TaskID == runner.TaskUpdateStats {
42+
w.Invalidate()
43+
}
44+
}
45+
}()
46+
3747
ui := ui.NewUI()
3848
var ops op.Ops
3949
for {
40-
switch e := w.NextEvent().(type) {
50+
switch e := w.Event().(type) {
4151
case app.DestroyEvent:
52+
tunnel.SaveConfig()
53+
entrypoint.SaveConfig()
4254
return e.Err
4355
case app.FrameEvent:
4456
gtx := app.NewContext(&ops, e)
4557
ui.Layout(gtx)
4658
e.Frame(gtx.Ops)
47-
case key.Event:
48-
if e.Name == key.NameBack {
49-
return nil
50-
}
5159
}
5260
}
5361
}
@@ -56,4 +64,10 @@ func Init() {
5664
config.Init()
5765
tunnel.LoadConfig()
5866
entrypoint.LoadConfig()
67+
68+
runner.Exec(context.Background(), task.UpdateStats(),
69+
runner.WithAync(true),
70+
runner.WithInterval(time.Second),
71+
runner.WithCancel(true),
72+
)
5973
}

runner/runner.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package runner
2+
3+
import (
4+
"context"
5+
"sync"
6+
"time"
7+
8+
"github.com/go-gost/core/logger"
9+
)
10+
11+
var (
12+
runner = NewRunner()
13+
)
14+
15+
type TaskEvent struct {
16+
TaskID TaskID
17+
Err error
18+
}
19+
20+
type taskState struct {
21+
task Task
22+
cancel context.CancelFunc
23+
}
24+
25+
type Options struct {
26+
Async bool
27+
Interval time.Duration
28+
Cancel bool
29+
}
30+
31+
type Option func(opts *Options)
32+
33+
func WithAync(aync bool) Option {
34+
return func(opts *Options) {
35+
opts.Async = aync
36+
}
37+
}
38+
39+
func WithInterval(interval time.Duration) Option {
40+
return func(opts *Options) {
41+
opts.Interval = interval
42+
}
43+
}
44+
45+
func WithCancel(cancel bool) Option {
46+
return func(opts *Options) {
47+
opts.Cancel = cancel
48+
}
49+
}
50+
51+
func Event() <-chan *TaskEvent {
52+
return runner.Event()
53+
}
54+
55+
func Exec(ctx context.Context, task Task, opts ...Option) error {
56+
return runner.Exec(ctx, task, opts...)
57+
}
58+
59+
func Cancel(id TaskID) {
60+
runner.Cancel(id)
61+
}
62+
63+
type Runner struct {
64+
events chan *TaskEvent
65+
states map[TaskID]taskState
66+
mu sync.RWMutex
67+
}
68+
69+
func NewRunner() *Runner {
70+
return &Runner{
71+
events: make(chan *TaskEvent, 16),
72+
states: make(map[TaskID]taskState),
73+
}
74+
}
75+
76+
func (r *Runner) Event() <-chan *TaskEvent {
77+
return r.events
78+
}
79+
80+
func (r *Runner) Exec(ctx context.Context, task Task, opts ...Option) error {
81+
if task == nil || task.ID() == "" {
82+
return nil
83+
}
84+
85+
var options Options
86+
for _, opt := range opts {
87+
opt(&options)
88+
}
89+
90+
if options.Cancel {
91+
r.Cancel(task.ID())
92+
}
93+
94+
ctx, cancel := context.WithCancel(ctx)
95+
r.setState(taskState{
96+
task: task,
97+
cancel: cancel,
98+
})
99+
100+
log := logger.Default().WithFields(map[string]any{
101+
"kind": "runner",
102+
"async": options.Async,
103+
})
104+
log.Debugf("task %s started", task.ID())
105+
106+
if !options.Async {
107+
t := time.Now()
108+
err := task.Run(ctx)
109+
110+
log.WithFields(map[string]any{
111+
"duration": time.Since(t),
112+
}).Debugf("task %s done: %v", task.ID(), err)
113+
114+
select {
115+
case r.events <- &TaskEvent{
116+
TaskID: task.ID(),
117+
Err: err,
118+
}:
119+
default:
120+
}
121+
122+
return err
123+
}
124+
125+
go func() {
126+
defer cancel()
127+
128+
t := time.Now()
129+
defer func() {
130+
log.WithFields(map[string]any{
131+
"duration": time.Since(t),
132+
}).Debugf("task %s done", task.ID())
133+
}()
134+
135+
run := func() {
136+
select {
137+
case r.events <- &TaskEvent{
138+
TaskID: task.ID(),
139+
Err: task.Run(ctx),
140+
}:
141+
default:
142+
}
143+
}
144+
145+
run()
146+
147+
interval := options.Interval
148+
if interval <= 0 {
149+
return
150+
}
151+
152+
ticker := time.NewTicker(interval)
153+
defer ticker.Stop()
154+
155+
for {
156+
select {
157+
case <-ticker.C:
158+
run()
159+
case <-ctx.Done():
160+
return
161+
}
162+
}
163+
}()
164+
165+
return nil
166+
}
167+
168+
func (r *Runner) Cancel(id TaskID) {
169+
r.delState(id)
170+
}
171+
172+
func (r *Runner) setState(state taskState) {
173+
if state.task == nil {
174+
return
175+
}
176+
177+
r.mu.Lock()
178+
defer r.mu.Unlock()
179+
180+
r.states[state.task.ID()] = state
181+
}
182+
183+
func (r *Runner) delState(id TaskID) {
184+
r.mu.Lock()
185+
defer r.mu.Unlock()
186+
187+
state := r.states[id]
188+
if state.cancel != nil {
189+
state.cancel()
190+
}
191+
192+
delete(r.states, id)
193+
}

runner/task.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package runner
2+
3+
import (
4+
"context"
5+
)
6+
7+
type TaskID string
8+
9+
const (
10+
TaskUpdateStats TaskID = "service.stats.update"
11+
)
12+
13+
type Task interface {
14+
ID() TaskID
15+
Run(ctx context.Context) error
16+
}

0 commit comments

Comments
 (0)