mirror of
https://github.com/fatedier/frp.git
synced 2026-07-16 09:19:17 +08:00
api: expose v2 proxy timestamps as unix seconds (#5402)
This commit is contained in:
@@ -239,9 +239,11 @@ func toProxyStats(name string, proxyStats *ProxyStatistics) *ProxyStats {
|
|||||||
}
|
}
|
||||||
if !proxyStats.LastStartTime.IsZero() {
|
if !proxyStats.LastStartTime.IsZero() {
|
||||||
ps.LastStartTime = proxyStats.LastStartTime.Format("01-02 15:04:05")
|
ps.LastStartTime = proxyStats.LastStartTime.Format("01-02 15:04:05")
|
||||||
|
ps.LastStartAt = proxyStats.LastStartTime.Unix()
|
||||||
}
|
}
|
||||||
if !proxyStats.LastCloseTime.IsZero() {
|
if !proxyStats.LastCloseTime.IsZero() {
|
||||||
ps.LastCloseTime = proxyStats.LastCloseTime.Format("01-02 15:04:05")
|
ps.LastCloseTime = proxyStats.LastCloseTime.Format("01-02 15:04:05")
|
||||||
|
ps.LastCloseAt = proxyStats.LastCloseTime.Unix()
|
||||||
}
|
}
|
||||||
return ps
|
return ps
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ func TestServerMetricsUsesClockForProxyTimestamps(t *testing.T) {
|
|||||||
clk.SetTime(closedAt)
|
clk.SetTime(closedAt)
|
||||||
metrics.CloseProxy("proxy", "tcp")
|
metrics.CloseProxy("proxy", "tcp")
|
||||||
require.Equal(closedAt, metrics.info.ProxyStatistics["proxy"].LastCloseTime)
|
require.Equal(closedAt, metrics.info.ProxyStatistics["proxy"].LastCloseTime)
|
||||||
|
|
||||||
|
stats := metrics.GetProxyByName("proxy")
|
||||||
|
require.Equal(start.Format("01-02 15:04:05"), stats.LastStartTime)
|
||||||
|
require.Equal(closedAt.Format("01-02 15:04:05"), stats.LastCloseTime)
|
||||||
|
require.Equal(start.Unix(), stats.LastStartAt)
|
||||||
|
require.Equal(closedAt.Unix(), stats.LastCloseAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerMetricsClearUselessInfoUsesClock(t *testing.T) {
|
func TestServerMetricsClearUselessInfoUsesClock(t *testing.T) {
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ type ProxyStats struct {
|
|||||||
TodayTrafficOut int64
|
TodayTrafficOut int64
|
||||||
LastStartTime string
|
LastStartTime string
|
||||||
LastCloseTime string
|
LastCloseTime string
|
||||||
|
LastStartAt int64
|
||||||
|
LastCloseAt int64
|
||||||
CurConns int64
|
CurConns int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -545,8 +545,8 @@ func (c *Controller) buildV2ProxyResp(ps *mem.ProxyStats) model.V2ProxyResp {
|
|||||||
TodayTrafficIn: ps.TodayTrafficIn,
|
TodayTrafficIn: ps.TodayTrafficIn,
|
||||||
TodayTrafficOut: ps.TodayTrafficOut,
|
TodayTrafficOut: ps.TodayTrafficOut,
|
||||||
CurConns: ps.CurConns,
|
CurConns: ps.CurConns,
|
||||||
LastStartTime: ps.LastStartTime,
|
LastStartAt: ps.LastStartAt,
|
||||||
LastCloseTime: ps.LastCloseTime,
|
LastCloseAt: ps.LastCloseAt,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,10 +421,22 @@ func TestAPIV2ProxyListDetailAndUsers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp = performRequest(router, "/api/v2/proxies/tcp-alice")
|
resp = performRequest(router, "/api/v2/proxies/tcp-alice")
|
||||||
|
rawProxyDetailResp := decodeResponse[v2EnvelopeForTest[map[string]json.RawMessage]](t, resp)
|
||||||
|
assertRawJSONKeysFromMessage(t, rawProxyDetailResp.Data["status"],
|
||||||
|
"curConns",
|
||||||
|
"lastCloseAt",
|
||||||
|
"lastStartAt",
|
||||||
|
"phase",
|
||||||
|
"todayTrafficIn",
|
||||||
|
"todayTrafficOut",
|
||||||
|
)
|
||||||
proxyDetailResp := decodeResponse[v2EnvelopeForTest[model.V2ProxyResp]](t, resp)
|
proxyDetailResp := decodeResponse[v2EnvelopeForTest[model.V2ProxyResp]](t, resp)
|
||||||
if proxyDetailResp.Data.Name != "tcp-alice" || proxyDetailResp.Data.User != "alice" {
|
if proxyDetailResp.Data.Name != "tcp-alice" || proxyDetailResp.Data.User != "alice" {
|
||||||
t.Fatalf("proxy detail mismatch: %#v", proxyDetailResp.Data)
|
t.Fatalf("proxy detail mismatch: %#v", proxyDetailResp.Data)
|
||||||
}
|
}
|
||||||
|
if proxyDetailResp.Data.Status.LastStartAt != 1783504200 || proxyDetailResp.Data.Status.LastCloseAt != 1783504300 {
|
||||||
|
t.Fatalf("proxy detail timestamp mismatch: %#v", proxyDetailResp.Data.Status)
|
||||||
|
}
|
||||||
|
|
||||||
resp = performRequest(router, "/api/v2/users?page=1&pageSize=50")
|
resp = performRequest(router, "/api/v2/users?page=1&pageSize=50")
|
||||||
userResp := decodeResponse[v2EnvelopeForTest[model.V2PageResp[model.V2UserResp]]](t, resp)
|
userResp := decodeResponse[v2EnvelopeForTest[model.V2PageResp[model.V2UserResp]]](t, resp)
|
||||||
@@ -744,6 +756,10 @@ func newV2TestController(t *testing.T) *Controller {
|
|||||||
TodayTrafficIn: 30,
|
TodayTrafficIn: 30,
|
||||||
TodayTrafficOut: 40,
|
TodayTrafficOut: 40,
|
||||||
CurConns: 2,
|
CurConns: 2,
|
||||||
|
LastStartTime: "07-08 12:30:00",
|
||||||
|
LastCloseTime: "07-08 12:31:40",
|
||||||
|
LastStartAt: 1783504200,
|
||||||
|
LastCloseAt: 1783504300,
|
||||||
},
|
},
|
||||||
"http-alice": {
|
"http-alice": {
|
||||||
Name: "http-alice",
|
Name: "http-alice",
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ type V2ProxyStatusResp struct {
|
|||||||
TodayTrafficIn int64 `json:"todayTrafficIn"`
|
TodayTrafficIn int64 `json:"todayTrafficIn"`
|
||||||
TodayTrafficOut int64 `json:"todayTrafficOut"`
|
TodayTrafficOut int64 `json:"todayTrafficOut"`
|
||||||
CurConns int64 `json:"curConns"`
|
CurConns int64 `json:"curConns"`
|
||||||
LastStartTime string `json:"lastStartTime"`
|
LastStartAt int64 `json:"lastStartAt,omitempty"`
|
||||||
LastCloseTime string `json:"lastCloseTime"`
|
LastCloseAt int64 `json:"lastCloseAt,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type V2ProxyTrafficResp struct {
|
type V2ProxyTrafficResp struct {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { buildQueryString, http } from './http'
|
import { buildQueryString, http } from './http'
|
||||||
|
import { formatUnixSeconds } from '../utils/format'
|
||||||
import type { V2Page } from './http'
|
import type { V2Page } from './http'
|
||||||
import type {
|
import type {
|
||||||
GetProxyResponse,
|
GetProxyResponse,
|
||||||
@@ -47,8 +48,8 @@ export const toLegacyProxyStats = (proxy: ProxyV2Info): ProxyStatsInfo => ({
|
|||||||
todayTrafficIn: proxy.status.todayTrafficIn,
|
todayTrafficIn: proxy.status.todayTrafficIn,
|
||||||
todayTrafficOut: proxy.status.todayTrafficOut,
|
todayTrafficOut: proxy.status.todayTrafficOut,
|
||||||
curConns: proxy.status.curConns,
|
curConns: proxy.status.curConns,
|
||||||
lastStartTime: proxy.status.lastStartTime,
|
lastStartTime: formatUnixSeconds(proxy.status.lastStartAt),
|
||||||
lastCloseTime: proxy.status.lastCloseTime,
|
lastCloseTime: formatUnixSeconds(proxy.status.lastCloseAt),
|
||||||
status: proxy.status.phase,
|
status: proxy.status.phase,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ export interface ProxyV2Status {
|
|||||||
todayTrafficIn: number
|
todayTrafficIn: number
|
||||||
todayTrafficOut: number
|
todayTrafficOut: number
|
||||||
curConns: number
|
curConns: number
|
||||||
lastStartTime: string
|
lastStartAt?: number
|
||||||
lastCloseTime: string
|
lastCloseAt?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TrafficResponse {
|
export interface TrafficResponse {
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ export function formatDistanceToNow(date: Date): string {
|
|||||||
return Math.floor(seconds) + ' seconds ago'
|
return Math.floor(seconds) + ' seconds ago'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatUnixSeconds(seconds?: number): string {
|
||||||
|
if (seconds == null || !Number.isFinite(seconds) || seconds <= 0) return ''
|
||||||
|
|
||||||
|
const date = new Date(seconds * 1000)
|
||||||
|
const pad = (value: number) => value.toString().padStart(2, '0')
|
||||||
|
return `${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
|
||||||
|
}
|
||||||
|
|
||||||
export function formatFileSize(bytes: number): string {
|
export function formatFileSize(bytes: number): string {
|
||||||
if (!Number.isFinite(bytes) || bytes < 0) return '0 B'
|
if (!Number.isFinite(bytes) || bytes < 0) return '0 B'
|
||||||
if (bytes === 0) return '0 B'
|
if (bytes === 0) return '0 B'
|
||||||
|
|||||||
Reference in New Issue
Block a user