avoid reset in QueryStatsRequest (#4202)

This commit is contained in:
Amirmohammad Sadat Shokouhi 2026-05-10 12:29:42 +03:30 committed by GitHub
parent 7cd26a0583
commit 14165fc54d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 17 additions and 5 deletions

View file

@ -212,7 +212,7 @@ func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, []*xray.ClientTraffic,
} }
defer s.xrayAPI.Close() defer s.xrayAPI.Close()
traffic, clientTraffic, err := s.xrayAPI.GetTraffic(true) traffic, clientTraffic, err := s.xrayAPI.GetTraffic()
if err != nil { if err != nil {
logger.Debug("Failed to fetch Xray traffic:", err) logger.Debug("Failed to fetch Xray traffic:", err)
return nil, nil, err return nil, nil, err
@ -242,6 +242,7 @@ func (s *XrayService) RestartXray(isForce bool) error {
p = xray.NewProcess(xrayConfig) p = xray.NewProcess(xrayConfig)
result = "" result = ""
s.xrayAPI.StatsLastValues = nil
err = p.Start() err = p.Start()
if err != nil { if err != nil {
return err return err

View file

@ -35,6 +35,7 @@ type XrayAPI struct {
StatsServiceClient *statsService.StatsServiceClient StatsServiceClient *statsService.StatsServiceClient
grpcClient *grpc.ClientConn grpcClient *grpc.ClientConn
isConnected bool isConnected bool
StatsLastValues map[string]int64
} }
func getRequiredUserString(user map[string]any, key string) (string, error) { func getRequiredUserString(user map[string]any, key string) (string, error) {
@ -79,6 +80,9 @@ func (x *XrayAPI) Init(apiPort int) error {
x.grpcClient = conn x.grpcClient = conn
x.isConnected = true x.isConnected = true
if x.StatsLastValues == nil {
x.StatsLastValues = make(map[string]int64)
}
hsClient := command.NewHandlerServiceClient(conn) hsClient := command.NewHandlerServiceClient(conn)
ssClient := statsService.NewStatsServiceClient(conn) ssClient := statsService.NewStatsServiceClient(conn)
@ -274,7 +278,7 @@ func (x *XrayAPI) RemoveUser(inboundTag, email string) error {
} }
// GetTraffic queries traffic statistics from the Xray core, optionally resetting counters. // GetTraffic queries traffic statistics from the Xray core, optionally resetting counters.
func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) { func (x *XrayAPI) GetTraffic() ([]*Traffic, []*ClientTraffic, error) {
if x.grpcClient == nil { if x.grpcClient == nil {
return nil, nil, common.NewError("xray api is not initialized") return nil, nil, common.NewError("xray api is not initialized")
} }
@ -289,7 +293,7 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
return nil, nil, common.NewError("xray StatusServiceClient is not initialized") return nil, nil, common.NewError("xray StatusServiceClient is not initialized")
} }
resp, err := (*x.StatsServiceClient).QueryStats(ctx, &statsService.QueryStatsRequest{Reset_: reset}) resp, err := (*x.StatsServiceClient).QueryStats(ctx, &statsService.QueryStatsRequest{Reset_: false})
if err != nil { if err != nil {
logger.Debug("Failed to query Xray stats:", err) logger.Debug("Failed to query Xray stats:", err)
return nil, nil, err return nil, nil, err
@ -299,10 +303,17 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
emailTrafficMap := make(map[string]*ClientTraffic) emailTrafficMap := make(map[string]*ClientTraffic)
for _, stat := range resp.GetStat() { for _, stat := range resp.GetStat() {
lastValue, ok := x.StatsLastValues[stat.Name]
x.StatsLastValues[stat.Name] = stat.Value
if !ok || stat.Value < lastValue {
// skip first time of seen stat
continue
}
value := stat.Value - lastValue
if matches := trafficRegex.FindStringSubmatch(stat.Name); len(matches) == 4 { if matches := trafficRegex.FindStringSubmatch(stat.Name); len(matches) == 4 {
processTraffic(matches, stat.Value, tagTrafficMap) processTraffic(matches, value, tagTrafficMap)
} else if matches := clientTrafficRegex.FindStringSubmatch(stat.Name); len(matches) == 3 { } else if matches := clientTrafficRegex.FindStringSubmatch(stat.Name); len(matches) == 3 {
processClientTraffic(matches, stat.Value, emailTrafficMap) processClientTraffic(matches, value, emailTrafficMap)
} }
} }
return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil