Skip to content

Commit a097de1

Browse files
authored
API: Add user IPs and access times tracking (XTLS#4360)
1 parent 5bcdb6a commit a097de1

8 files changed

Lines changed: 262 additions & 61 deletions

File tree

app/stats/command/command.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@ func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsReque
6060
}, nil
6161
}
6262

63+
func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
64+
c := s.stats.GetOnlineMap(request.Name)
65+
66+
if c == nil {
67+
return nil, errors.New(request.Name, " not found.")
68+
}
69+
70+
ips := make(map[string]int64)
71+
for ip, t := range c.IpTimeMap() {
72+
ips[ip] = t.Unix()
73+
}
74+
75+
return &GetStatsOnlineIpListResponse{
76+
Name: request.Name,
77+
Ips: ips,
78+
}, nil
79+
}
80+
6381
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
6482
matcher, err := strmatcher.Substr.New(request.Pattern)
6583
if err != nil {

app/stats/command/command.pb.go

Lines changed: 135 additions & 57 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/stats/command/command.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,17 @@ message SysStatsResponse {
4646
uint32 Uptime = 10;
4747
}
4848

49+
message GetStatsOnlineIpListResponse {
50+
string name = 1;
51+
map<string, int64> ips = 2;
52+
}
53+
4954
service StatsService {
5055
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
5156
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
5257
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
5358
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
59+
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
5460
}
5561

5662
message Config {}

app/stats/command/command_grpc.pb.go

Lines changed: 42 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/stats/online_map.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,13 @@ func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.
7878
}
7979
return list
8080
}
81+
82+
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
83+
list := c.ipList
84+
if time.Since(c.lastCleanup) > c.cleanupPeriod {
85+
list = c.RemoveExpiredIPs(list)
86+
c.lastCleanup = time.Now()
87+
}
88+
89+
return c.ipList
90+
}

features/stats/stats.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package stats
22

33
import (
44
"context"
5+
"time"
56

67
"github.com/xtls/xray-core/common"
78
"github.com/xtls/xray-core/common/errors"
@@ -30,6 +31,8 @@ type OnlineMap interface {
3031
AddIP(string)
3132
// List is the current OnlineMap ip list.
3233
List() []string
34+
// IpTimeMap return client ips and their last access time.
35+
IpTimeMap() map[string]time.Time
3336
}
3437

3538
// Channel is the interface for stats channel.

main/commands/all/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ var CmdAPI = &base.Command{
2727
cmdRemoveRules,
2828
cmdSourceIpBlock,
2929
cmdOnlineStats,
30+
cmdOnlineStatsIpList,
3031
},
3132
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package api
2+
3+
import (
4+
statsService "github.com/xtls/xray-core/app/stats/command"
5+
"github.com/xtls/xray-core/main/commands/base"
6+
)
7+
8+
var cmdOnlineStatsIpList = &base.Command{
9+
CustomFlags: true,
10+
UsageLine: "{{.Exec}} api statsonlineiplist [--server=127.0.0.1:8080] [-name '']",
11+
Short: "Get online user ips list and access times",
12+
Long: `
13+
Get statistics from Xray.
14+
Arguments:
15+
-s, -server
16+
The API server address. Default 127.0.0.1:8080
17+
-t, -timeout
18+
Timeout seconds to call API. Default 3
19+
-email
20+
email of the user.
21+
-reset
22+
Reset the counter to fetching its value (not used).
23+
Example:
24+
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "user1@test.com"
25+
`,
26+
Run: executeOnlineStatsIpList,
27+
}
28+
29+
func executeOnlineStatsIpList(cmd *base.Command, args []string) {
30+
setSharedFlags(cmd)
31+
email := cmd.Flag.String("email", "", "")
32+
cmd.Flag.Parse(args)
33+
statName := "user>>>" + *email + ">>>online"
34+
conn, ctx, close := dialAPIServer()
35+
defer close()
36+
37+
client := statsService.NewStatsServiceClient(conn)
38+
r := &statsService.GetStatsRequest{
39+
Name: statName,
40+
Reset_: false,
41+
}
42+
resp, err := client.GetStatsOnlineIpList(ctx, r)
43+
if err != nil {
44+
base.Fatalf("failed to get stats: %s", err)
45+
}
46+
showJSONResponse(resp)
47+
}

0 commit comments

Comments
 (0)