| @@ -84,4 +84,6 @@ func (s *Server) InitRouters(rt gin.IRoutes, ah *auth.Auth) { | |||
| rt.GET(cliapi.TickTockListJobsPath, certAuth, s.TickTock().ListJobs) | |||
| rt.POST(cliapi.TickTockRunJobPath, certAuth, s.TickTock().RunJob) | |||
| rt.GET(cliapi.SystemStatusPath, certAuth, s.System().Status) | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| package http | |||
| import ( | |||
| "net/http" | |||
| "github.com/gin-gonic/gin" | |||
| "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/types" | |||
| cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1" | |||
| "gitlink.org.cn/cloudream/jcs-pub/common/ecode" | |||
| ) | |||
| type SystemService struct { | |||
| *Server | |||
| } | |||
| func (s *Server) System() *SystemService { | |||
| return &SystemService{ | |||
| Server: s, | |||
| } | |||
| } | |||
| func (s *SystemService) Status(ctx *gin.Context) { | |||
| var req cliapi.SystemStatus | |||
| if err := ctx.ShouldBindQuery(&req); err != nil { | |||
| ctx.JSON(http.StatusBadRequest, types.Failed(ecode.BadArgument, "%v", err)) | |||
| return | |||
| } | |||
| ctx.JSON(http.StatusOK, types.OK(cliapi.SystemStatusResp{ | |||
| SpeedStats: s.svc.SpeedStats.DumpStatus(), | |||
| })) | |||
| } | |||
| @@ -1,10 +1,11 @@ | |||
| package speedstats | |||
| import ( | |||
| "fmt" | |||
| "math/rand/v2" | |||
| "sync" | |||
| "time" | |||
| clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | |||
| ) | |||
| const ( | |||
| @@ -91,13 +92,6 @@ func (p *SpeedStats) Step() { | |||
| p.statsAbove1G[1].Step() | |||
| } | |||
| func (p *SpeedStats) Dump() string { | |||
| p.lock.RLock() | |||
| defer p.lock.RUnlock() | |||
| return fmt.Sprintf("100M: %v, %v\n1G: %v, %v\nAbove1G: %v, %v\n", p.stats100M[0].AvarageSpeed, p.stats100M[1].AvarageSpeed, p.stats1G[0].AvarageSpeed, p.stats1G[1].AvarageSpeed, p.statsAbove1G[0].AvarageSpeed, p.statsAbove1G[1].AvarageSpeed) | |||
| } | |||
| func (p *SpeedStats) ShouldAtClient(size int64) bool { | |||
| p.lock.RLock() | |||
| defer p.lock.RUnlock() | |||
| @@ -126,3 +120,50 @@ func (p *SpeedStats) ShouldAtClient(size int64) bool { | |||
| v := rand.Float64() | |||
| return v < prob | |||
| } | |||
| func (p *SpeedStats) DumpStatus() clitypes.SpeedStatsStatus { | |||
| return clitypes.SpeedStatsStatus{ | |||
| Below100M: []clitypes.SpeedStatsStatusEntry{ | |||
| { | |||
| TotalSize: p.stats100M[0].TotalSize, | |||
| TotalTime: p.stats100M[0].TotalTime, | |||
| AvarageSpeed: p.stats100M[0].AvarageSpeed, | |||
| LastSpeed: p.stats100M[0].LastSpeed, | |||
| }, | |||
| { | |||
| TotalSize: p.stats100M[1].TotalSize, | |||
| TotalTime: p.stats100M[1].TotalTime, | |||
| AvarageSpeed: p.stats100M[1].AvarageSpeed, | |||
| LastSpeed: p.stats100M[1].LastSpeed, | |||
| }, | |||
| }, | |||
| Below1G: []clitypes.SpeedStatsStatusEntry{ | |||
| { | |||
| TotalSize: p.stats1G[0].TotalSize, | |||
| TotalTime: p.stats1G[0].TotalTime, | |||
| AvarageSpeed: p.stats1G[0].AvarageSpeed, | |||
| LastSpeed: p.stats1G[0].LastSpeed, | |||
| }, | |||
| { | |||
| TotalSize: p.stats1G[1].TotalSize, | |||
| TotalTime: p.stats1G[1].TotalTime, | |||
| AvarageSpeed: p.stats1G[1].AvarageSpeed, | |||
| LastSpeed: p.stats1G[1].LastSpeed, | |||
| }, | |||
| }, | |||
| Above1G: []clitypes.SpeedStatsStatusEntry{ | |||
| { | |||
| TotalSize: p.statsAbove1G[0].TotalSize, | |||
| TotalTime: p.statsAbove1G[0].TotalTime, | |||
| AvarageSpeed: p.statsAbove1G[0].AvarageSpeed, | |||
| LastSpeed: p.statsAbove1G[0].LastSpeed, | |||
| }, | |||
| { | |||
| TotalSize: p.statsAbove1G[1].TotalSize, | |||
| TotalTime: p.statsAbove1G[1].TotalTime, | |||
| AvarageSpeed: p.statsAbove1G[1].AvarageSpeed, | |||
| LastSpeed: p.statsAbove1G[1].LastSpeed, | |||
| }, | |||
| }, | |||
| } | |||
| } | |||
| @@ -23,5 +23,10 @@ func (j *SpeedStatsStep) Execute(t *TickTock) { | |||
| }() | |||
| t.speedStats.Step() | |||
| log.Info(t.speedStats.Dump()) | |||
| status := t.speedStats.DumpStatus() | |||
| log.Infof("100M: %f, %f; 1G: %f, %f; Above1G: %f, %f\n", | |||
| status.Below100M[0].AvarageSpeed, status.Below100M[1].AvarageSpeed, | |||
| status.Below1G[0].AvarageSpeed, status.Below1G[1].AvarageSpeed, | |||
| status.Above1G[0].AvarageSpeed, status.Above1G[1].AvarageSpeed, | |||
| ) | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| package api | |||
| import ( | |||
| "net/http" | |||
| "gitlink.org.cn/cloudream/common/sdks" | |||
| clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types" | |||
| ) | |||
| type SystemService struct { | |||
| *Client | |||
| } | |||
| func (c *Client) System() *SystemService { | |||
| return &SystemService{c} | |||
| } | |||
| const SystemStatusPath = "/system/status" | |||
| type SystemStatus struct { | |||
| } | |||
| func (r *SystemStatus) MakeParam() *sdks.RequestParam { | |||
| return sdks.MakeQueryParam(http.MethodGet, SystemStatusPath, r) | |||
| } | |||
| type SystemStatusResp struct { | |||
| SpeedStats clitypes.SpeedStatsStatus `json:"speedStats"` | |||
| } | |||
| func (r *SystemStatusResp) ParseResponse(resp *http.Response) error { | |||
| return sdks.ParseCodeDataJSONResponse(resp, r) | |||
| } | |||
| func (c *SystemService) Status(req SystemStatus) (*SystemStatusResp, error) { | |||
| return JSONAPI(&c.cfg, c.httpCli, &req, &SystemStatusResp{}) | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| package types | |||
| import "time" | |||
| type SpeedStatsStatus struct { | |||
| Below100M []SpeedStatsStatusEntry `json:"below100M"` | |||
| Below1G []SpeedStatsStatusEntry `json:"below1G"` | |||
| Above1G []SpeedStatsStatusEntry `json:"above1G"` | |||
| } | |||
| type SpeedStatsStatusEntry struct { | |||
| TotalSize int64 `json:"totalSize"` | |||
| TotalTime time.Duration `json:"totalTime"` | |||
| AvarageSpeed float64 `json:"avarageSpeed"` | |||
| LastSpeed float64 `json:"lastSpeed"` | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| package admin | |||
| import ( | |||
| "bytes" | |||
| "encoding/json" | |||
| "fmt" | |||
| "github.com/spf13/cobra" | |||
| cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1" | |||
| "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd" | |||
| ) | |||
| func init() { | |||
| var opt statusOpt | |||
| cmd := cobra.Command{ | |||
| Use: "status", | |||
| Args: cobra.ExactArgs(0), | |||
| RunE: func(c *cobra.Command, args []string) error { | |||
| ctx := cmd.GetCmdCtx(c) | |||
| return status(c, ctx, opt, args) | |||
| }, | |||
| } | |||
| AdminCmd.AddCommand(&cmd) | |||
| } | |||
| type statusOpt struct { | |||
| } | |||
| func status(c *cobra.Command, ctx *cmd.CommandContext, opt statusOpt, args []string) error { | |||
| resp, err := ctx.Client.System().Status(cliapi.SystemStatus{}) | |||
| if err != nil { | |||
| return fmt.Errorf("get system status: %v", err) | |||
| } | |||
| bw := bytes.NewBuffer(nil) | |||
| enc := json.NewEncoder(bw) | |||
| enc.SetIndent("", " ") | |||
| err = enc.Encode(resp) | |||
| if err != nil { | |||
| return fmt.Errorf("encode system status: %v", err) | |||
| } | |||
| fmt.Println(bw.String()) | |||
| return nil | |||
| } | |||