Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/stats/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsReque
}, nil
}

func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
c := s.stats.GetOnlineMap(request.Name)

if c == nil {
return nil, errors.New(request.Name, " not found.")
}

ips := make(map[string]int64)
for ip, t := range c.IpTimeMap() {
ips[ip] = t.Unix()
}

return &GetStatsOnlineIpListResponse{
Name: request.Name,
Ips: ips,
}, nil
}

func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
matcher, err := strmatcher.Substr.New(request.Pattern)
if err != nil {
Expand Down
192 changes: 135 additions & 57 deletions app/stats/command/command.pb.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions app/stats/command/command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,17 @@ message SysStatsResponse {
uint32 Uptime = 10;
}

message GetStatsOnlineIpListResponse {
string name = 1;
map<string, int64> ips = 2;
}

service StatsService {
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
}

message Config {}
46 changes: 42 additions & 4 deletions app/stats/command/command_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions app/stats/online_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,13 @@ func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.
}
return list
}

func (c *OnlineMap) IpTimeMap() map[string]time.Time {
list := c.ipList
if time.Since(c.lastCleanup) > c.cleanupPeriod {
list = c.RemoveExpiredIPs(list)
c.lastCleanup = time.Now()
}

return c.ipList
}
3 changes: 3 additions & 0 deletions features/stats/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package stats

import (
"context"
"time"

"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
Expand Down Expand Up @@ -30,6 +31,8 @@ type OnlineMap interface {
AddIP(string)
// List is the current OnlineMap ip list.
List() []string
// IpTimeMap return client ips and their last access time.
IpTimeMap() map[string]time.Time
}

// Channel is the interface for stats channel.
Expand Down
1 change: 1 addition & 0 deletions main/commands/all/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ var CmdAPI = &base.Command{
cmdRemoveRules,
cmdSourceIpBlock,
cmdOnlineStats,
cmdOnlineStatsIpList,
},
}
47 changes: 47 additions & 0 deletions main/commands/all/api/stats_online_ip_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package api

import (
statsService "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/main/commands/base"
)

var cmdOnlineStatsIpList = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api statsonlineiplist [--server=127.0.0.1:8080] [-name '']",
Short: "Get online user ips list and access times",
Long: `
Get statistics from Xray.
Arguments:
-s, -server
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-email
email of the user.
-reset
Reset the counter to fetching its value (not used).
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "user1@test.com"
`,
Run: executeOnlineStatsIpList,
}

func executeOnlineStatsIpList(cmd *base.Command, args []string) {
setSharedFlags(cmd)
email := cmd.Flag.String("email", "", "")
cmd.Flag.Parse(args)
statName := "user>>>" + *email + ">>>online"
conn, ctx, close := dialAPIServer()
defer close()

client := statsService.NewStatsServiceClient(conn)
r := &statsService.GetStatsRequest{
Name: statName,
Reset_: false,
}
resp, err := client.GetStatsOnlineIpList(ctx, r)
if err != nil {
base.Fatalf("failed to get stats: %s", err)
}
showJSONResponse(resp)
}
Loading