add traffic reset for stats
This commit is contained in:
@@ -31,6 +31,7 @@ import (
|
|||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
"github.com/go-gost/x/metadata"
|
"github.com/go-gost/x/metadata"
|
||||||
mdutil "github.com/go-gost/x/metadata/util"
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
xservice "github.com/go-gost/x/service"
|
xservice "github.com/go-gost/x/service"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
@@ -101,8 +102,8 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|||||||
ifce := cfg.Interface
|
ifce := cfg.Interface
|
||||||
var preUp, preDown, postUp, postDown []string
|
var preUp, preDown, postUp, postDown []string
|
||||||
var ignoreChain bool
|
var ignoreChain bool
|
||||||
var pStats *stats.Stats
|
var pStats stats.Stats
|
||||||
var observePeriod time.Duration
|
var observerPeriod time.Duration
|
||||||
var netnsIn, netnsOut string
|
var netnsIn, netnsOut string
|
||||||
var dialTimeout time.Duration
|
var dialTimeout time.Duration
|
||||||
if cfg.Metadata != nil {
|
if cfg.Metadata != nil {
|
||||||
@@ -123,9 +124,10 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|||||||
ignoreChain = mdutil.GetBool(md, parsing.MDKeyIgnoreChain)
|
ignoreChain = mdutil.GetBool(md, parsing.MDKeyIgnoreChain)
|
||||||
|
|
||||||
if mdutil.GetBool(md, parsing.MDKeyEnableStats) {
|
if mdutil.GetBool(md, parsing.MDKeyEnableStats) {
|
||||||
pStats = &stats.Stats{}
|
pStats = xstats.NewStats(mdutil.GetBool(md, "observer.resetTraffic"))
|
||||||
}
|
}
|
||||||
observePeriod = mdutil.GetDuration(md, "observePeriod")
|
observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period")
|
||||||
|
|
||||||
netnsIn = mdutil.GetString(md, "netns")
|
netnsIn = mdutil.GetString(md, "netns")
|
||||||
netnsOut = mdutil.GetString(md, "netns.out")
|
netnsOut = mdutil.GetString(md, "netns.out")
|
||||||
dialTimeout = mdutil.GetDuration(md, "dialTimeout")
|
dialTimeout = mdutil.GetDuration(md, "dialTimeout")
|
||||||
@@ -318,7 +320,7 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|||||||
xservice.RecordersOption(recorders...),
|
xservice.RecordersOption(recorders...),
|
||||||
xservice.StatsOption(pStats),
|
xservice.StatsOption(pStats),
|
||||||
xservice.ObserverOption(registry.ObserverRegistry().Get(cfg.Observer)),
|
xservice.ObserverOption(registry.ObserverRegistry().Get(cfg.Observer)),
|
||||||
xservice.ObservePeriodOption(observePeriod),
|
xservice.ObserverPeriodOption(observerPeriod),
|
||||||
xservice.LoggerOption(serviceLogger),
|
xservice.LoggerOption(serviceLogger),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func (d *http3Dialer) Dial(ctx context.Context, addr string, opts ...dialer.Dial
|
|||||||
Host: host,
|
Host: host,
|
||||||
Client: &http.Client{
|
Client: &http.Client{
|
||||||
// Timeout: 60 * time.Second,
|
// Timeout: 60 * time.Second,
|
||||||
Transport: &http3.RoundTripper{
|
Transport: &http3.Transport{
|
||||||
TLSClientConfig: d.options.TLSConfig,
|
TLSClientConfig: d.options.TLSConfig,
|
||||||
Dial: func(ctx context.Context, adr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
Dial: func(ctx context.Context, adr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||||
// d.options.Logger.Infof("dial: %s/%s, %s", addr, network, host)
|
// d.options.Logger.Infof("dial: %s/%s, %s", addr, network, host)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ require (
|
|||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
||||||
github.com/gin-contrib/cors v1.7.2
|
github.com/gin-contrib/cors v1.7.2
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/go-gost/core v0.1.11
|
github.com/go-gost/core v0.2.0
|
||||||
github.com/go-gost/gosocks4 v0.0.1
|
github.com/go-gost/gosocks4 v0.0.1
|
||||||
github.com/go-gost/gosocks5 v0.4.2
|
github.com/go-gost/gosocks5 v0.4.2
|
||||||
github.com/go-gost/plugin v0.1.1
|
github.com/go-gost/plugin v0.1.1
|
||||||
@@ -45,7 +45,7 @@ require (
|
|||||||
github.com/zalando/go-keyring v0.2.4
|
github.com/zalando/go-keyring v0.2.4
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.31.0
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884
|
golang.org/x/exp v0.0.0-20241210194714-1829a127f884
|
||||||
golang.org/x/net v0.32.0
|
golang.org/x/net v0.33.0
|
||||||
golang.org/x/sys v0.28.0
|
golang.org/x/sys v0.28.0
|
||||||
golang.org/x/text v0.21.0
|
golang.org/x/text v0.21.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.5.0
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
|||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-gost/core v0.1.11 h1:7zmRx0stWrClUJM/IT/ltRQJC9wUc8f6TAj1fbBiSPs=
|
github.com/go-gost/core v0.2.0 h1:hZf94DAv93iwKXXzGXBmspE5bExYcBJeLl6inL9mG6Y=
|
||||||
github.com/go-gost/core v0.1.11/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
|
github.com/go-gost/core v0.2.0/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
|
||||||
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
||||||
github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
|
github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
|
||||||
github.com/go-gost/gosocks5 v0.4.2 h1:IianxHTkACPqCwiOAT3MHoMdSUl+SEPSRu1ikawC1Pc=
|
github.com/go-gost/gosocks5 v0.4.2 h1:IianxHTkACPqCwiOAT3MHoMdSUl+SEPSRu1ikawC1Pc=
|
||||||
@@ -305,8 +305,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
xhop "github.com/go-gost/x/hop"
|
xhop "github.com/go-gost/x/hop"
|
||||||
resolver_util "github.com/go-gost/x/internal/util/resolver"
|
resolver_util "github.com/go-gost/x/internal/util/resolver"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -163,7 +164,7 @@ func (h *dnsHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
|
|||||||
|
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/go-gost/x/internal/util/sniffing"
|
"github.com/go-gost/x/internal/util/sniffing"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -114,7 +115,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
|||||||
}
|
}
|
||||||
ro.Network = network
|
ro.Network = network
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
mdutil "github.com/go-gost/x/metadata/util"
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -116,7 +117,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
|||||||
}
|
}
|
||||||
ro.Network = network
|
ro.Network = network
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
+21
-6
@@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/go-gost/core/limiter/traffic"
|
"github.com/go-gost/core/limiter/traffic"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
"github.com/go-gost/core/recorder"
|
"github.com/go-gost/core/recorder"
|
||||||
xbypass "github.com/go-gost/x/bypass"
|
xbypass "github.com/go-gost/x/bypass"
|
||||||
@@ -41,6 +42,7 @@ import (
|
|||||||
ws_util "github.com/go-gost/x/internal/util/ws"
|
ws_util "github.com/go-gost/x/internal/util/ws"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -83,7 +85,7 @@ func (h *httpHandler) Init(md md.Metadata) error {
|
|||||||
h.cancel = cancel
|
h.cancel = cancel
|
||||||
|
|
||||||
if h.options.Observer != nil {
|
if h.options.Observer != nil {
|
||||||
h.stats = stats_util.NewHandlerStats(h.options.Service)
|
h.stats = stats_util.NewHandlerStats(h.options.Service, h.md.observerResetTraffic)
|
||||||
go h.observeStats(ctx)
|
go h.observeStats(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -420,7 +422,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpHandler) handleProxy(ctx context.Context, conn net.Conn, req *http.Request, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
func (h *httpHandler) handleProxy(ctx context.Context, conn net.Conn, req *http.Request, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
ro.Time = time.Time{}
|
ro.Time = time.Time{}
|
||||||
@@ -452,7 +454,7 @@ func (h *httpHandler) handleProxy(ctx context.Context, conn net.Conn, req *http.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats *stats.Stats, log logger.Logger) (close bool, err error) {
|
func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats stats.Stats, log logger.Logger) (close bool, err error) {
|
||||||
close = true
|
close = true
|
||||||
|
|
||||||
ro2 := &xrecorder.HandlerRecorderObject{}
|
ro2 := &xrecorder.HandlerRecorderObject{}
|
||||||
@@ -949,13 +951,26 @@ func (h *httpHandler) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(h.md.observePeriod)
|
var events []observer.Event
|
||||||
|
|
||||||
|
ticker := time.NewTicker(h.md.observerPeriod)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
h.options.Observer.Observe(ctx, h.stats.Events())
|
if len(events) > 0 {
|
||||||
|
if err := h.options.Observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := h.stats.Events()
|
||||||
|
if err := h.options.Observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ type metadata struct {
|
|||||||
hash string
|
hash string
|
||||||
authBasicRealm string
|
authBasicRealm string
|
||||||
proxyAgent string
|
proxyAgent string
|
||||||
observePeriod time.Duration
|
|
||||||
limiterRefreshInterval time.Duration
|
limiterRefreshInterval time.Duration
|
||||||
|
|
||||||
|
observerPeriod time.Duration
|
||||||
|
observerResetTraffic bool
|
||||||
|
|
||||||
sniffing bool
|
sniffing bool
|
||||||
sniffingTimeout time.Duration
|
sniffingTimeout time.Duration
|
||||||
sniffingWebsocket bool
|
sniffingWebsocket bool
|
||||||
@@ -73,14 +75,16 @@ func (h *httpHandler) parseMetadata(md mdata.Metadata) error {
|
|||||||
h.md.hash = mdutil.GetString(md, "hash")
|
h.md.hash = mdutil.GetString(md, "hash")
|
||||||
h.md.authBasicRealm = mdutil.GetString(md, "authBasicRealm")
|
h.md.authBasicRealm = mdutil.GetString(md, "authBasicRealm")
|
||||||
|
|
||||||
h.md.observePeriod = mdutil.GetDuration(md, "observePeriod", "observer.observePeriod")
|
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
|
||||||
if h.md.observePeriod == 0 {
|
if h.md.observerPeriod == 0 {
|
||||||
h.md.observePeriod = 5 * time.Second
|
h.md.observerPeriod = 5 * time.Second
|
||||||
}
|
}
|
||||||
if h.md.observePeriod < time.Second {
|
if h.md.observerPeriod < time.Second {
|
||||||
h.md.observePeriod = time.Second
|
h.md.observerPeriod = time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.md.observerResetTraffic = mdutil.GetBool(md, "observer.resetTraffic")
|
||||||
|
|
||||||
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
||||||
if h.md.limiterRefreshInterval == 0 {
|
if h.md.limiterRefreshInterval == 0 {
|
||||||
h.md.limiterRefreshInterval = 30 * time.Second
|
h.md.limiterRefreshInterval = 30 * time.Second
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/go-gost/core/limiter/traffic"
|
"github.com/go-gost/core/limiter/traffic"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
"github.com/go-gost/core/recorder"
|
"github.com/go-gost/core/recorder"
|
||||||
xbypass "github.com/go-gost/x/bypass"
|
xbypass "github.com/go-gost/x/bypass"
|
||||||
@@ -72,7 +73,7 @@ func (h *http2Handler) Init(md md.Metadata) error {
|
|||||||
h.cancel = cancel
|
h.cancel = cancel
|
||||||
|
|
||||||
if h.options.Observer != nil {
|
if h.options.Observer != nil {
|
||||||
h.stats = stats_util.NewHandlerStats(h.options.Service)
|
h.stats = stats_util.NewHandlerStats(h.options.Service, h.md.observerResetTraffic)
|
||||||
go h.observeStats(ctx)
|
go h.observeStats(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,13 +484,26 @@ func (h *http2Handler) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(h.md.observePeriod)
|
var events []observer.Event
|
||||||
|
|
||||||
|
ticker := time.NewTicker(h.md.observerPeriod)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
h.options.Observer.Observe(ctx, h.stats.Events())
|
if len(events) > 0 {
|
||||||
|
if err := h.options.Observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := h.stats.Events()
|
||||||
|
if err := h.options.Observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ type metadata struct {
|
|||||||
header http.Header
|
header http.Header
|
||||||
hash string
|
hash string
|
||||||
authBasicRealm string
|
authBasicRealm string
|
||||||
observePeriod time.Duration
|
observerPeriod time.Duration
|
||||||
|
observerResetTraffic bool
|
||||||
limiterRefreshInterval time.Duration
|
limiterRefreshInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,13 +44,14 @@ func (h *http2Handler) parseMetadata(md mdata.Metadata) error {
|
|||||||
h.md.hash = mdutil.GetString(md, "hash")
|
h.md.hash = mdutil.GetString(md, "hash")
|
||||||
h.md.authBasicRealm = mdutil.GetString(md, "authBasicRealm")
|
h.md.authBasicRealm = mdutil.GetString(md, "authBasicRealm")
|
||||||
|
|
||||||
h.md.observePeriod = mdutil.GetDuration(md, "observePeriod", "observer.observePeriod")
|
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
|
||||||
if h.md.observePeriod == 0 {
|
if h.md.observerPeriod == 0 {
|
||||||
h.md.observePeriod = 5 * time.Second
|
h.md.observerPeriod = 5 * time.Second
|
||||||
}
|
}
|
||||||
if h.md.observePeriod < time.Second {
|
if h.md.observerPeriod < time.Second {
|
||||||
h.md.observePeriod = time.Second
|
h.md.observerPeriod = time.Second
|
||||||
}
|
}
|
||||||
|
h.md.observerResetTraffic = mdutil.GetBool(md, "observer.resetTraffic")
|
||||||
|
|
||||||
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
||||||
if h.md.limiterRefreshInterval == 0 {
|
if h.md.limiterRefreshInterval == 0 {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
xbypass "github.com/go-gost/x/bypass"
|
xbypass "github.com/go-gost/x/bypass"
|
||||||
ctxvalue "github.com/go-gost/x/ctx"
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
"github.com/go-gost/x/internal/util/sniffing"
|
"github.com/go-gost/x/internal/util/sniffing"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
@@ -90,7 +91,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
ctxvalue "github.com/go-gost/x/ctx"
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -78,7 +79,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
|||||||
|
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/go-gost/core/hop"
|
"github.com/go-gost/core/hop"
|
||||||
"github.com/go-gost/core/limiter/traffic"
|
"github.com/go-gost/core/limiter/traffic"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
"github.com/go-gost/core/recorder"
|
"github.com/go-gost/core/recorder"
|
||||||
"github.com/go-gost/relay"
|
"github.com/go-gost/relay"
|
||||||
@@ -19,6 +20,7 @@ import (
|
|||||||
stats_util "github.com/go-gost/x/internal/util/stats"
|
stats_util "github.com/go-gost/x/internal/util/stats"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -65,7 +67,7 @@ func (h *relayHandler) Init(md md.Metadata) (err error) {
|
|||||||
h.cancel = cancel
|
h.cancel = cancel
|
||||||
|
|
||||||
if h.options.Observer != nil {
|
if h.options.Observer != nil {
|
||||||
h.stats = stats_util.NewHandlerStats(h.options.Service)
|
h.stats = stats_util.NewHandlerStats(h.options.Service, h.md.observerResetTraffic)
|
||||||
go h.observeStats(ctx)
|
go h.observeStats(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +124,7 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle
|
|||||||
|
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -253,13 +255,26 @@ func (h *relayHandler) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(h.md.observePeriod)
|
var events []observer.Event
|
||||||
|
|
||||||
|
ticker := time.NewTicker(h.md.observerPeriod)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
h.options.Observer.Observe(ctx, h.stats.Events())
|
if len(events) > 0 {
|
||||||
|
if err := h.options.Observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := h.stats.Events()
|
||||||
|
if err := h.options.Observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,11 @@ type metadata struct {
|
|||||||
noDelay bool
|
noDelay bool
|
||||||
hash string
|
hash string
|
||||||
muxCfg *mux.Config
|
muxCfg *mux.Config
|
||||||
observePeriod time.Duration
|
|
||||||
limiterRefreshInterval time.Duration
|
limiterRefreshInterval time.Duration
|
||||||
|
|
||||||
|
observerPeriod time.Duration
|
||||||
|
observerResetTraffic bool
|
||||||
|
|
||||||
sniffing bool
|
sniffing bool
|
||||||
sniffingTimeout time.Duration
|
sniffingTimeout time.Duration
|
||||||
sniffingWebsocket bool
|
sniffingWebsocket bool
|
||||||
@@ -62,14 +64,16 @@ func (h *relayHandler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
MaxStreamBuffer: mdutil.GetInt(md, "mux.maxStreamBuffer"),
|
MaxStreamBuffer: mdutil.GetInt(md, "mux.maxStreamBuffer"),
|
||||||
}
|
}
|
||||||
|
|
||||||
h.md.observePeriod = mdutil.GetDuration(md, "observePeriod", "observer.observePeriod")
|
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
|
||||||
if h.md.observePeriod == 0 {
|
if h.md.observerPeriod == 0 {
|
||||||
h.md.observePeriod = 5 * time.Second
|
h.md.observerPeriod = 5 * time.Second
|
||||||
}
|
}
|
||||||
if h.md.observePeriod < time.Second {
|
if h.md.observerPeriod < time.Second {
|
||||||
h.md.observePeriod = time.Second
|
h.md.observerPeriod = time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.md.observerResetTraffic = mdutil.GetBool(md, "observer.resetTraffic")
|
||||||
|
|
||||||
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
||||||
if h.md.limiterRefreshInterval == 0 {
|
if h.md.limiterRefreshInterval == 0 {
|
||||||
h.md.limiterRefreshInterval = 30 * time.Second
|
h.md.limiterRefreshInterval = 30 * time.Second
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/go-gost/x/internal/util/sniffing"
|
"github.com/go-gost/x/internal/util/sniffing"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -96,7 +97,7 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/go-gost/core/limiter/traffic"
|
"github.com/go-gost/core/limiter/traffic"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
"github.com/go-gost/core/recorder"
|
"github.com/go-gost/core/recorder"
|
||||||
"github.com/go-gost/gosocks4"
|
"github.com/go-gost/gosocks4"
|
||||||
@@ -25,6 +26,7 @@ import (
|
|||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -70,7 +72,7 @@ func (h *socks4Handler) Init(md md.Metadata) (err error) {
|
|||||||
h.cancel = cancel
|
h.cancel = cancel
|
||||||
|
|
||||||
if h.options.Observer != nil {
|
if h.options.Observer != nil {
|
||||||
h.stats = stats_util.NewHandlerStats(h.options.Service)
|
h.stats = stats_util.NewHandlerStats(h.options.Service, h.md.observerResetTraffic)
|
||||||
go h.observeStats(ctx)
|
go h.observeStats(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +124,7 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -338,13 +340,26 @@ func (h *socks4Handler) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(h.md.observePeriod)
|
var events []observer.Event
|
||||||
|
|
||||||
|
ticker := time.NewTicker(h.md.observerPeriod)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
h.options.Observer.Observe(ctx, h.stats.Events())
|
if len(events) > 0 {
|
||||||
|
if err := h.options.Observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := h.stats.Events()
|
||||||
|
if err := h.options.Observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,11 @@ import (
|
|||||||
type metadata struct {
|
type metadata struct {
|
||||||
readTimeout time.Duration
|
readTimeout time.Duration
|
||||||
hash string
|
hash string
|
||||||
observePeriod time.Duration
|
|
||||||
limiterRefreshInterval time.Duration
|
limiterRefreshInterval time.Duration
|
||||||
|
|
||||||
|
observerPeriod time.Duration
|
||||||
|
observerResetTraffic bool
|
||||||
|
|
||||||
sniffing bool
|
sniffing bool
|
||||||
sniffingTimeout time.Duration
|
sniffingTimeout time.Duration
|
||||||
sniffingWebsocket bool
|
sniffingWebsocket bool
|
||||||
@@ -37,14 +39,16 @@ func (h *socks4Handler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
|
|
||||||
h.md.hash = mdutil.GetString(md, "hash")
|
h.md.hash = mdutil.GetString(md, "hash")
|
||||||
|
|
||||||
h.md.observePeriod = mdutil.GetDuration(md, "observePeriod", "observer.observePeriod")
|
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
|
||||||
if h.md.observePeriod == 0 {
|
if h.md.observerPeriod == 0 {
|
||||||
h.md.observePeriod = 5 * time.Second
|
h.md.observerPeriod = 5 * time.Second
|
||||||
}
|
}
|
||||||
if h.md.observePeriod < time.Second {
|
if h.md.observerPeriod < time.Second {
|
||||||
h.md.observePeriod = time.Second
|
h.md.observerPeriod = time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h.md.observerResetTraffic = mdutil.GetBool(md, "observer.resetTraffic")
|
||||||
|
|
||||||
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
||||||
if h.md.limiterRefreshInterval == 0 {
|
if h.md.limiterRefreshInterval == 0 {
|
||||||
h.md.limiterRefreshInterval = 30 * time.Second
|
h.md.limiterRefreshInterval = 30 * time.Second
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/go-gost/core/handler"
|
"github.com/go-gost/core/handler"
|
||||||
"github.com/go-gost/core/limiter/traffic"
|
"github.com/go-gost/core/limiter/traffic"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
"github.com/go-gost/core/recorder"
|
"github.com/go-gost/core/recorder"
|
||||||
"github.com/go-gost/gosocks5"
|
"github.com/go-gost/gosocks5"
|
||||||
@@ -18,6 +19,7 @@ import (
|
|||||||
stats_util "github.com/go-gost/x/internal/util/stats"
|
stats_util "github.com/go-gost/x/internal/util/stats"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -70,7 +72,7 @@ func (h *socks5Handler) Init(md md.Metadata) (err error) {
|
|||||||
h.cancel = cancel
|
h.cancel = cancel
|
||||||
|
|
||||||
if h.options.Observer != nil {
|
if h.options.Observer != nil {
|
||||||
h.stats = stats_util.NewHandlerStats(h.options.Service)
|
h.stats = stats_util.NewHandlerStats(h.options.Service, h.md.observerResetTraffic)
|
||||||
go h.observeStats(ctx)
|
go h.observeStats(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +124,7 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -216,13 +218,26 @@ func (h *socks5Handler) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(h.md.observePeriod)
|
var events []observer.Event
|
||||||
|
|
||||||
|
ticker := time.NewTicker(h.md.observerPeriod)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
h.options.Observer.Observe(ctx, h.stats.Events())
|
if len(events) > 0 {
|
||||||
|
if err := h.options.Observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := h.stats.Events()
|
||||||
|
if err := h.options.Observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ type metadata struct {
|
|||||||
compatibilityMode bool
|
compatibilityMode bool
|
||||||
hash string
|
hash string
|
||||||
muxCfg *mux.Config
|
muxCfg *mux.Config
|
||||||
observePeriod time.Duration
|
|
||||||
limiterRefreshInterval time.Duration
|
limiterRefreshInterval time.Duration
|
||||||
|
|
||||||
|
observerPeriod time.Duration
|
||||||
|
observerResetTraffic bool
|
||||||
|
|
||||||
sniffing bool
|
sniffing bool
|
||||||
sniffingTimeout time.Duration
|
sniffingTimeout time.Duration
|
||||||
sniffingWebsocket bool
|
sniffingWebsocket bool
|
||||||
@@ -66,13 +68,14 @@ func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
MaxStreamBuffer: mdutil.GetInt(md, "mux.maxStreamBuffer"),
|
MaxStreamBuffer: mdutil.GetInt(md, "mux.maxStreamBuffer"),
|
||||||
}
|
}
|
||||||
|
|
||||||
h.md.observePeriod = mdutil.GetDuration(md, "observePeriod", "observer.observePeriod")
|
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
|
||||||
if h.md.observePeriod == 0 {
|
if h.md.observerPeriod == 0 {
|
||||||
h.md.observePeriod = 5 * time.Second
|
h.md.observerPeriod = 5 * time.Second
|
||||||
}
|
}
|
||||||
if h.md.observePeriod < time.Second {
|
if h.md.observerPeriod < time.Second {
|
||||||
h.md.observePeriod = time.Second
|
h.md.observerPeriod = time.Second
|
||||||
}
|
}
|
||||||
|
h.md.observerResetTraffic = mdutil.GetBool(md, "observer.resetTraffic")
|
||||||
|
|
||||||
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
||||||
if h.md.limiterRefreshInterval == 0 {
|
if h.md.limiterRefreshInterval == 0 {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/go-gost/x/internal/util/ss"
|
"github.com/go-gost/x/internal/util/ss"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -106,7 +107,7 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.H
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
sshd_util "github.com/go-gost/x/internal/util/sshd"
|
sshd_util "github.com/go-gost/x/internal/util/sshd"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
rate_limiter "github.com/go-gost/x/limiter/rate"
|
rate_limiter "github.com/go-gost/x/limiter/rate"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -98,7 +99,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func (h *tunnelHandler) handleBind(ctx context.Context, conn net.Conn, network,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var stats *stats.Stats
|
var stats stats.Stats
|
||||||
if h.stats != nil {
|
if h.stats != nil {
|
||||||
stats = h.stats.Stats(tunnelID.String())
|
stats = h.stats.Stats(tunnelID.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import (
|
|||||||
ws_util "github.com/go-gost/x/internal/util/ws"
|
ws_util "github.com/go-gost/x/internal/util/ws"
|
||||||
climiter "github.com/go-gost/x/limiter/conn/wrapper"
|
climiter "github.com/go-gost/x/limiter/conn/wrapper"
|
||||||
metrics "github.com/go-gost/x/metrics/wrapper"
|
metrics "github.com/go-gost/x/metrics/wrapper"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"golang.org/x/net/http/httpguts"
|
"golang.org/x/net/http/httpguts"
|
||||||
@@ -86,7 +87,7 @@ func (ep *entrypoint) Handle(ctx context.Context, conn net.Conn) (err error) {
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -195,7 +196,7 @@ func (ep *entrypoint) dial(ctx context.Context, network, addr string) (conn net.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ep *entrypoint) handleHTTP(ctx context.Context, conn net.Conn, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
func (ep *entrypoint) handleHTTP(ctx context.Context, conn net.Conn, ro *xrecorder.HandlerRecorderObject, log logger.Logger) (err error) {
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
br := bufio.NewReader(conn)
|
br := bufio.NewReader(conn)
|
||||||
@@ -250,7 +251,7 @@ func (ep *entrypoint) handleHTTP(ctx context.Context, conn net.Conn, ro *xrecord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ep *entrypoint) httpRoundTrip(ctx context.Context, rw io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats *stats.Stats, log logger.Logger) (err error) {
|
func (ep *entrypoint) httpRoundTrip(ctx context.Context, rw io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats stats.Stats, log logger.Logger) (err error) {
|
||||||
ro2 := &xrecorder.HandlerRecorderObject{}
|
ro2 := &xrecorder.HandlerRecorderObject{}
|
||||||
*ro2 = *ro
|
*ro2 = *ro
|
||||||
ro = ro2
|
ro = ro2
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/go-gost/core/listener"
|
"github.com/go-gost/core/listener"
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/service"
|
"github.com/go-gost/core/service"
|
||||||
"github.com/go-gost/relay"
|
"github.com/go-gost/relay"
|
||||||
ctxvalue "github.com/go-gost/x/ctx"
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
@@ -116,7 +117,7 @@ func (h *tunnelHandler) Init(md md.Metadata) (err error) {
|
|||||||
h.cancel = cancel
|
h.cancel = cancel
|
||||||
|
|
||||||
if h.options.Observer != nil {
|
if h.options.Observer != nil {
|
||||||
h.stats = stats_util.NewHandlerStats(h.options.Service)
|
h.stats = stats_util.NewHandlerStats(h.options.Service, h.md.observerResetTraffic)
|
||||||
go h.observeStats(ctx)
|
go h.observeStats(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,13 +322,26 @@ func (h *tunnelHandler) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(h.md.observePeriod)
|
var events []observer.Event
|
||||||
|
|
||||||
|
ticker := time.NewTicker(h.md.observerPeriod)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
h.options.Observer.Observe(ctx, h.stats.Events())
|
if len(events) > 0 {
|
||||||
|
if err := h.options.Observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := h.stats.Events()
|
||||||
|
if err := h.options.Observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ type metadata struct {
|
|||||||
ingress ingress.Ingress
|
ingress ingress.Ingress
|
||||||
sd sd.SD
|
sd sd.SD
|
||||||
muxCfg *mux.Config
|
muxCfg *mux.Config
|
||||||
observePeriod time.Duration
|
|
||||||
limiterRefreshInterval time.Duration
|
limiterRefreshInterval time.Duration
|
||||||
|
|
||||||
|
observerPeriod time.Duration
|
||||||
|
observerResetTraffic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tunnelHandler) parseMetadata(md mdata.Metadata) (err error) {
|
func (h *tunnelHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
@@ -105,13 +107,14 @@ func (h *tunnelHandler) parseMetadata(md mdata.Metadata) (err error) {
|
|||||||
h.md.muxCfg.MaxStreamBuffer = 1048576
|
h.md.muxCfg.MaxStreamBuffer = 1048576
|
||||||
}
|
}
|
||||||
|
|
||||||
h.md.observePeriod = mdutil.GetDuration(md, "observePeriod", "observer.observePeriod")
|
h.md.observerPeriod = mdutil.GetDuration(md, "observePeriod", "observer.period", "observer.observePeriod")
|
||||||
if h.md.observePeriod == 0 {
|
if h.md.observerPeriod == 0 {
|
||||||
h.md.observePeriod = 5 * time.Second
|
h.md.observerPeriod = 5 * time.Second
|
||||||
}
|
}
|
||||||
if h.md.observePeriod < time.Second {
|
if h.md.observerPeriod < time.Second {
|
||||||
h.md.observePeriod = time.Second
|
h.md.observerPeriod = time.Second
|
||||||
}
|
}
|
||||||
|
h.md.observerResetTraffic = mdutil.GetBool(md, "observer.resetTraffic")
|
||||||
|
|
||||||
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
h.md.limiterRefreshInterval = mdutil.GetDuration(md, "limiter.refreshInterval")
|
||||||
if h.md.limiterRefreshInterval == 0 {
|
if h.md.limiterRefreshInterval == 0 {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const (
|
|||||||
type ConnectorOptions struct {
|
type ConnectorOptions struct {
|
||||||
service string
|
service string
|
||||||
sd sd.SD
|
sd sd.SD
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
limiter traffic.TrafficLimiter
|
limiter traffic.TrafficLimiter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
"github.com/go-gost/x/internal/util/sniffing"
|
"github.com/go-gost/x/internal/util/sniffing"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
@@ -95,7 +96,7 @@ func (h *unixHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
|
|||||||
})
|
})
|
||||||
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/go-gost/x/internal/util/sniffing"
|
"github.com/go-gost/x/internal/util/sniffing"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
ws_util "github.com/go-gost/x/internal/util/ws"
|
ws_util "github.com/go-gost/x/internal/util/ws"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"golang.org/x/net/http/httpguts"
|
"golang.org/x/net/http/httpguts"
|
||||||
@@ -123,7 +124,7 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO
|
|||||||
opt(&ho)
|
opt(&ho)
|
||||||
}
|
}
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
br := bufio.NewReader(conn)
|
br := bufio.NewReader(conn)
|
||||||
@@ -349,7 +350,7 @@ func (h *Sniffer) serveH2(ctx context.Context, conn net.Conn, ho *HandleOptions)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, node *chain.Node, req *http.Request, pStats *stats.Stats, ho *HandleOptions) (close bool, err error) {
|
func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, node *chain.Node, req *http.Request, pStats stats.Stats, ho *HandleOptions) (close bool, err error) {
|
||||||
close = true
|
close = true
|
||||||
|
|
||||||
log := ho.Log
|
log := ho.Log
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
xhttp "github.com/go-gost/x/internal/net/http"
|
xhttp "github.com/go-gost/x/internal/net/http"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
ws_util "github.com/go-gost/x/internal/util/ws"
|
ws_util "github.com/go-gost/x/internal/util/ws"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
stats_wrapper "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
xrecorder "github.com/go-gost/x/recorder"
|
xrecorder "github.com/go-gost/x/recorder"
|
||||||
"golang.org/x/net/http/httpguts"
|
"golang.org/x/net/http/httpguts"
|
||||||
@@ -114,7 +115,7 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO
|
|||||||
opt(&ho)
|
opt(&ho)
|
||||||
}
|
}
|
||||||
|
|
||||||
pStats := stats.Stats{}
|
pStats := xstats.Stats{}
|
||||||
conn = stats_wrapper.WrapConn(conn, &pStats)
|
conn = stats_wrapper.WrapConn(conn, &pStats)
|
||||||
|
|
||||||
br := bufio.NewReader(conn)
|
br := bufio.NewReader(conn)
|
||||||
@@ -262,7 +263,7 @@ func (h *Sniffer) serveH2(ctx context.Context, conn net.Conn, ho *HandleOptions)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats *stats.Stats, log logger.Logger) (close bool, err error) {
|
func (h *Sniffer) httpRoundTrip(ctx context.Context, rw, cc io.ReadWriter, req *http.Request, ro *xrecorder.HandlerRecorderObject, pStats stats.Stats, log logger.Logger) (close bool, err error) {
|
||||||
close = true
|
close = true
|
||||||
|
|
||||||
ro2 := &xrecorder.HandlerRecorderObject{}
|
ro2 := &xrecorder.HandlerRecorderObject{}
|
||||||
|
|||||||
@@ -5,22 +5,25 @@ import (
|
|||||||
|
|
||||||
"github.com/go-gost/core/observer"
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HandlerStats struct {
|
type HandlerStats struct {
|
||||||
service string
|
service string
|
||||||
stats map[string]*stats.Stats
|
stats map[string]stats.Stats
|
||||||
|
resetTraffic bool
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandlerStats(service string) *HandlerStats {
|
func NewHandlerStats(service string, resetTraffic bool) *HandlerStats {
|
||||||
return &HandlerStats{
|
return &HandlerStats{
|
||||||
service: service,
|
service: service,
|
||||||
stats: make(map[string]*stats.Stats),
|
stats: make(map[string]stats.Stats),
|
||||||
|
resetTraffic: resetTraffic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HandlerStats) Stats(client string) *stats.Stats {
|
func (p *HandlerStats) Stats(client string) stats.Stats {
|
||||||
p.mu.RLock()
|
p.mu.RLock()
|
||||||
pstats := p.stats[client]
|
pstats := p.stats[client]
|
||||||
p.mu.RUnlock()
|
p.mu.RUnlock()
|
||||||
@@ -32,7 +35,7 @@ func (p *HandlerStats) Stats(client string) *stats.Stats {
|
|||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
pstats = p.stats[client]
|
pstats = p.stats[client]
|
||||||
if pstats == nil {
|
if pstats == nil {
|
||||||
pstats = &stats.Stats{}
|
pstats = xstats.NewStats(p.resetTraffic)
|
||||||
}
|
}
|
||||||
p.stats[client] = pstats
|
p.stats[client] = pstats
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ func (p *HandlerStats) Events() (events []observer.Event) {
|
|||||||
if !v.IsUpdated() {
|
if !v.IsUpdated() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
events = append(events, stats.StatsEvent{
|
events = append(events, xstats.StatsEvent{
|
||||||
Kind: "handler",
|
Kind: "handler",
|
||||||
Service: p.service,
|
Service: p.service,
|
||||||
Client: k,
|
Client: k,
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package observer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/core/observer"
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
|
||||||
"github.com/go-gost/plugin/observer/proto"
|
"github.com/go-gost/plugin/observer/proto"
|
||||||
"github.com/go-gost/x/internal/plugin"
|
"github.com/go-gost/x/internal/plugin"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
"github.com/go-gost/x/service"
|
"github.com/go-gost/x/service"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
@@ -67,7 +68,7 @@ func (p *grpcPlugin) Observe(ctx context.Context, events []observer.Event, opts
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
case observer.EventStats:
|
case observer.EventStats:
|
||||||
ev := event.(stats.StatsEvent)
|
ev := event.(xstats.StatsEvent)
|
||||||
req.Events = append(req.Events, &proto.Event{
|
req.Events = append(req.Events, &proto.Event{
|
||||||
Kind: ev.Kind,
|
Kind: ev.Kind,
|
||||||
Service: ev.Service,
|
Service: ev.Service,
|
||||||
@@ -83,11 +84,14 @@ func (p *grpcPlugin) Observe(ctx context.Context, events []observer.Event, opts
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := p.client.Observe(ctx, &req)
|
reply, err := p.client.Observe(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.log.Error(err)
|
p.log.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if reply == nil || !reply.Ok {
|
||||||
|
return errors.New("observe failed")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-5
@@ -4,14 +4,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
"github.com/go-gost/core/observer"
|
"github.com/go-gost/core/observer"
|
||||||
"github.com/go-gost/core/observer/stats"
|
|
||||||
"github.com/go-gost/x/internal/plugin"
|
"github.com/go-gost/x/internal/plugin"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
"github.com/go-gost/x/service"
|
"github.com/go-gost/x/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ type statusEvent struct {
|
|||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type observeResponse struct {
|
type httpPluginResponse struct {
|
||||||
OK bool `json:"ok"`
|
OK bool `json:"ok"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ func (p *httpPlugin) Observe(ctx context.Context, events []observer.Event, opts
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
case observer.EventStats:
|
case observer.EventStats:
|
||||||
ev := e.(stats.StatsEvent)
|
ev := e.(xstats.StatsEvent)
|
||||||
r.Events = append(r.Events, event{
|
r.Events = append(r.Events, event{
|
||||||
Kind: ev.Kind,
|
Kind: ev.Kind,
|
||||||
Service: ev.Service,
|
Service: ev.Service,
|
||||||
@@ -131,7 +131,16 @@ func (p *httpPlugin) Observe(ctx context.Context, events []observer.Event, opts
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return fmt.Errorf(resp.Status)
|
return errors.New(resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
res := httpPluginResponse{}
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !res.OK {
|
||||||
|
return errors.New("observe failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package stats
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/observer"
|
||||||
|
"github.com/go-gost/core/observer/stats"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Stats struct {
|
||||||
|
updated atomic.Bool
|
||||||
|
totalConns atomic.Uint64
|
||||||
|
currentConns atomic.Uint64
|
||||||
|
inputBytes atomic.Uint64
|
||||||
|
outputBytes atomic.Uint64
|
||||||
|
totalErrs atomic.Uint64
|
||||||
|
resetTraffic bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStats(resetTraffic bool) stats.Stats {
|
||||||
|
return &Stats{
|
||||||
|
resetTraffic: resetTraffic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stats) Add(kind stats.Kind, n int64) {
|
||||||
|
if s == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch kind {
|
||||||
|
case stats.KindTotalConns:
|
||||||
|
if n > 0 {
|
||||||
|
s.totalConns.Add(uint64(n))
|
||||||
|
}
|
||||||
|
case stats.KindCurrentConns:
|
||||||
|
s.currentConns.Add(uint64(n))
|
||||||
|
case stats.KindInputBytes:
|
||||||
|
s.inputBytes.Add(uint64(n))
|
||||||
|
case stats.KindOutputBytes:
|
||||||
|
s.outputBytes.Add(uint64(n))
|
||||||
|
case stats.KindTotalErrs:
|
||||||
|
if n > 0 {
|
||||||
|
s.totalErrs.Add(uint64(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.updated.Store(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stats) Get(kind stats.Kind) uint64 {
|
||||||
|
if s == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kind {
|
||||||
|
case stats.KindTotalConns:
|
||||||
|
return s.totalConns.Load()
|
||||||
|
case stats.KindCurrentConns:
|
||||||
|
return s.currentConns.Load()
|
||||||
|
case stats.KindInputBytes:
|
||||||
|
if s.resetTraffic {
|
||||||
|
return s.inputBytes.Swap(0)
|
||||||
|
}
|
||||||
|
return s.inputBytes.Load()
|
||||||
|
case stats.KindOutputBytes:
|
||||||
|
if s.resetTraffic {
|
||||||
|
return s.outputBytes.Swap(0)
|
||||||
|
}
|
||||||
|
return s.outputBytes.Load()
|
||||||
|
case stats.KindTotalErrs:
|
||||||
|
return s.totalErrs.Load()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stats) Reset() {
|
||||||
|
s.updated.Store(false)
|
||||||
|
s.totalConns.Store(0)
|
||||||
|
s.currentConns.Store(0)
|
||||||
|
s.inputBytes.Store(0)
|
||||||
|
s.outputBytes.Store(0)
|
||||||
|
s.totalErrs.Store(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stats) IsUpdated() bool {
|
||||||
|
return s.updated.Swap(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatsEvent struct {
|
||||||
|
Kind string
|
||||||
|
Service string
|
||||||
|
Client string
|
||||||
|
|
||||||
|
TotalConns uint64
|
||||||
|
CurrentConns uint64
|
||||||
|
InputBytes uint64
|
||||||
|
OutputBytes uint64
|
||||||
|
TotalErrs uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (StatsEvent) Type() observer.EventType {
|
||||||
|
return observer.EventStats
|
||||||
|
}
|
||||||
@@ -19,12 +19,12 @@ var (
|
|||||||
|
|
||||||
type conn struct {
|
type conn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapConn(c net.Conn, pStats *stats.Stats) net.Conn {
|
func WrapConn(c net.Conn, pStats stats.Stats) net.Conn {
|
||||||
if pStats == nil {
|
if pStats == nil {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@@ -84,10 +84,10 @@ func (c *conn) Metadata() metadata.Metadata {
|
|||||||
|
|
||||||
type packetConn struct {
|
type packetConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapPacketConn(pc net.PacketConn, stats *stats.Stats) net.PacketConn {
|
func WrapPacketConn(pc net.PacketConn, stats stats.Stats) net.PacketConn {
|
||||||
if stats == nil {
|
if stats == nil {
|
||||||
return pc
|
return pc
|
||||||
}
|
}
|
||||||
@@ -118,10 +118,10 @@ func (c *packetConn) Metadata() metadata.Metadata {
|
|||||||
|
|
||||||
type udpConn struct {
|
type udpConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapUDPConn(pc net.PacketConn, stats *stats.Stats) udp.Conn {
|
func WrapUDPConn(pc net.PacketConn, stats stats.Stats) udp.Conn {
|
||||||
return &udpConn{
|
return &udpConn{
|
||||||
PacketConn: pc,
|
PacketConn: pc,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
// readWriter is an io.ReadWriter with Stats.
|
// readWriter is an io.ReadWriter with Stats.
|
||||||
type readWriter struct {
|
type readWriter struct {
|
||||||
io.ReadWriter
|
io.ReadWriter
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapReadWriter(rw io.ReadWriter, stats *stats.Stats) io.ReadWriter {
|
func WrapReadWriter(rw io.ReadWriter, stats stats.Stats) io.ReadWriter {
|
||||||
if stats == nil {
|
if stats == nil {
|
||||||
return rw
|
return rw
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type listener struct {
|
type listener struct {
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
net.Listener
|
net.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapListener(ln net.Listener, stats *stats.Stats) net.Listener {
|
func WrapListener(ln net.Listener, stats stats.Stats) net.Listener {
|
||||||
if stats == nil {
|
if stats == nil {
|
||||||
return ln
|
return ln
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package recorder
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
@@ -56,7 +57,7 @@ func (p *grpcPlugin) Record(ctx context.Context, b []byte, opts ...recorder.Reco
|
|||||||
|
|
||||||
md, _ := json.Marshal(options.Metadata)
|
md, _ := json.Marshal(options.Metadata)
|
||||||
|
|
||||||
_, err := p.client.Record(ctx,
|
reply, err := p.client.Record(ctx,
|
||||||
&proto.RecordRequest{
|
&proto.RecordRequest{
|
||||||
Data: b,
|
Data: b,
|
||||||
Metadata: md,
|
Metadata: md,
|
||||||
@@ -65,6 +66,9 @@ func (p *grpcPlugin) Record(ctx context.Context, b []byte, opts ...recorder.Reco
|
|||||||
p.log.Error(err)
|
p.log.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if reply == nil || !reply.Ok {
|
||||||
|
return errors.New("record failed")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-gost/core/logger"
|
"github.com/go-gost/core/logger"
|
||||||
@@ -84,7 +83,7 @@ func (p *httpPlugin) Record(ctx context.Context, b []byte, opts ...recorder.Reco
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return fmt.Errorf("%s", resp.Status)
|
return errors.New(resp.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := httpPluginResponse{}
|
res := httpPluginResponse{}
|
||||||
|
|||||||
+34
-13
@@ -21,6 +21,7 @@ import (
|
|||||||
ctxvalue "github.com/go-gost/x/ctx"
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
xnet "github.com/go-gost/x/internal/net"
|
xnet "github.com/go-gost/x/internal/net"
|
||||||
xmetrics "github.com/go-gost/x/metrics"
|
xmetrics "github.com/go-gost/x/metrics"
|
||||||
|
xstats "github.com/go-gost/x/observer/stats"
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,9 +32,9 @@ type options struct {
|
|||||||
postUp []string
|
postUp []string
|
||||||
preDown []string
|
preDown []string
|
||||||
postDown []string
|
postDown []string
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
observer observer.Observer
|
observer observer.Observer
|
||||||
observePeriod time.Duration
|
observerPeriod time.Duration
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ func PostDownOption(cmds []string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatsOption(stats *stats.Stats) Option {
|
func StatsOption(stats stats.Stats) Option {
|
||||||
return func(opts *options) {
|
return func(opts *options) {
|
||||||
opts.stats = stats
|
opts.stats = stats
|
||||||
}
|
}
|
||||||
@@ -87,9 +88,9 @@ func ObserverOption(observer observer.Observer) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ObservePeriodOption(period time.Duration) Option {
|
func ObserverPeriodOption(period time.Duration) Option {
|
||||||
return func(opts *options) {
|
return func(opts *options) {
|
||||||
opts.observePeriod = period
|
opts.observerPeriod = period
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +250,9 @@ func (s *defaultService) Serve() error {
|
|||||||
metrics.Labels{"service": s.name, "client": clientIP}); v != nil {
|
metrics.Labels{"service": s.name, "client": clientIP}); v != nil {
|
||||||
v.Inc()
|
v.Inc()
|
||||||
}
|
}
|
||||||
s.status.stats.Add(stats.KindTotalErrs, 1)
|
if sts := s.status.stats; sts != nil {
|
||||||
|
sts.Add(stats.KindTotalErrs, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -307,10 +310,15 @@ func (s *defaultService) observeStats(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d := s.options.observePeriod
|
d := s.options.observerPeriod
|
||||||
if d < time.Millisecond {
|
if d == 0 {
|
||||||
d = 5 * time.Second
|
d = 5 * time.Second
|
||||||
}
|
}
|
||||||
|
if d < time.Second {
|
||||||
|
d = 1 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
var events []observer.Event
|
||||||
|
|
||||||
ticker := time.NewTicker(d)
|
ticker := time.NewTicker(d)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
@@ -318,20 +326,33 @@ func (s *defaultService) observeStats(ctx context.Context) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
st := s.status.Stats()
|
if len(events) > 0 {
|
||||||
if !st.IsUpdated() {
|
if err := s.options.observer.Observe(ctx, events); err == nil {
|
||||||
|
events = nil
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s.options.observer.Observe(ctx, []observer.Event{
|
|
||||||
stats.StatsEvent{
|
st := s.status.Stats()
|
||||||
|
if st == nil || !st.IsUpdated() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
evs := []observer.Event{
|
||||||
|
xstats.StatsEvent{
|
||||||
Kind: "service",
|
Kind: "service",
|
||||||
Service: s.name,
|
Service: s.name,
|
||||||
TotalConns: st.Get(stats.KindTotalConns),
|
TotalConns: st.Get(stats.KindTotalConns),
|
||||||
CurrentConns: st.Get(stats.KindCurrentConns),
|
CurrentConns: st.Get(stats.KindCurrentConns),
|
||||||
InputBytes: st.Get(stats.KindInputBytes),
|
InputBytes: st.Get(stats.KindInputBytes),
|
||||||
OutputBytes: st.Get(stats.KindOutputBytes),
|
OutputBytes: st.Get(stats.KindOutputBytes),
|
||||||
|
TotalErrs: st.Get(stats.KindTotalErrs),
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
if err := s.options.observer.Observe(ctx, evs); err != nil {
|
||||||
|
events = evs
|
||||||
|
}
|
||||||
|
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -29,7 +29,7 @@ type Status struct {
|
|||||||
createTime time.Time
|
createTime time.Time
|
||||||
state State
|
state State
|
||||||
events []Event
|
events []Event
|
||||||
stats *stats.Stats
|
stats stats.Stats
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ func (p *Status) addEvent(event Event) {
|
|||||||
p.events = append(p.events, event)
|
p.events = append(p.events, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Status) Stats() *stats.Stats {
|
func (p *Status) Stats() stats.Stats {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user