From 2509956f0f26e67daf316ebcc6f429cf2a669ab2 Mon Sep 17 00:00:00 2001 From: GoEdgeLab Date: Wed, 19 Jan 2022 16:53:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0API=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E8=80=97=E6=97=B6=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/rpc/rpc_client.go | 4 + internal/web/actions/default/api/index.go | 15 +++- internal/web/actions/default/api/init.go | 1 + .../web/actions/default/api/methodStats.go | 78 +++++++++++++++++++ web/views/@default/api/index.html | 1 + web/views/@default/api/methodStats.html | 46 +++++++++++ 6 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 internal/web/actions/default/api/methodStats.go create mode 100644 web/views/@default/api/methodStats.html diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index 0c42d9e7..b39278b1 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -161,6 +161,10 @@ func (this *RPCClient) APINodeRPC() pb.APINodeServiceClient { return pb.NewAPINodeServiceClient(this.pickConn()) } +func (this *RPCClient) APIMethodStatRPC() pb.APIMethodStatServiceClient { + return pb.NewAPIMethodStatServiceClient(this.pickConn()) +} + func (this *RPCClient) UserNodeRPC() pb.UserNodeServiceClient { return pb.NewUserNodeServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/api/index.go b/internal/web/actions/default/api/index.go index 7cda3313..292e6978 100644 --- a/internal/web/actions/default/api/index.go +++ b/internal/web/actions/default/api/index.go @@ -9,6 +9,7 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/iwind/TeaGo/logs" "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" "time" ) @@ -26,11 +27,11 @@ func (this *IndexAction) RunGet(params struct{}) { this.ErrorPage(err) return } - count := countResp.Count - page := this.NewPage(count) + var count = countResp.Count + var page = this.NewPage(count) this.Data["page"] = page.AsHTML() - nodeMaps := []maps.Map{} + var nodeMaps = []maps.Map{} if count > 0 { nodesResp, err := this.RPC().APINodeRPC().ListEnabledAPINodes(this.AdminContext(), &pb.ListEnabledAPINodesRequest{ Offset: page.Offset, @@ -106,5 +107,13 @@ func (this *IndexAction) RunGet(params struct{}) { } this.Data["nodes"] = nodeMaps + // 检查是否有调试数据 + countMethodStatsResp, err := this.RPC().APIMethodStatRPC().CountAPIMethodStatsWithDay(this.AdminContext(), &pb.CountAPIMethodStatsWithDayRequest{Day: timeutil.Format("Ymd")}) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["hasMethodStats"] = countMethodStatsResp.Count > 0 + this.Show() } diff --git a/internal/web/actions/default/api/init.go b/internal/web/actions/default/api/init.go index 03c74fae..8e12573e 100644 --- a/internal/web/actions/default/api/init.go +++ b/internal/web/actions/default/api/init.go @@ -16,6 +16,7 @@ func init() { Helper(settingutils.NewAdvancedHelper("apiNodes")). Prefix("/api"). Get("", new(IndexAction)). + Get("/methodStats", new(MethodStatsAction)). GetPost("/node/createPopup", new(node.CreatePopupAction)). Post("/delete", new(DeleteAction)). EndAll() diff --git a/internal/web/actions/default/api/methodStats.go b/internal/web/actions/default/api/methodStats.go new file mode 100644 index 00000000..00eeaac2 --- /dev/null +++ b/internal/web/actions/default/api/methodStats.go @@ -0,0 +1,78 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package api + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" + "sort" + "strings" +) + +type MethodStatsAction struct { + actionutils.ParentAction +} + +func (this *MethodStatsAction) Init() { + this.Nav("", "", "") +} + +func (this *MethodStatsAction) RunGet(params struct { + Order string + Method string + Tag string +}) { + this.Data["order"] = params.Order + this.Data["method"] = params.Method + this.Data["tag"] = params.Tag + + statsResp, err := this.RPC().APIMethodStatRPC().FindAPIMethodStatsWithDay(this.AdminContext(), &pb.FindAPIMethodStatsWithDayRequest{Day: timeutil.Format("Ymd")}) + if err != nil { + this.ErrorPage(err) + return + } + var pbStats = statsResp.ApiMethodStats + + switch params.Order { + case "method": + sort.Slice(pbStats, func(i, j int) bool { + return pbStats[i].Method < pbStats[j].Method + }) + case "costMs.desc": + sort.Slice(pbStats, func(i, j int) bool { + return pbStats[i].CostMs > pbStats[j].CostMs + }) + case "peekMs.desc": + sort.Slice(pbStats, func(i, j int) bool { + return pbStats[i].PeekMs > pbStats[j].PeekMs + }) + case "calls.desc": + sort.Slice(pbStats, func(i, j int) bool { + return pbStats[i].CountCalls > pbStats[j].CountCalls + }) + } + + var statMaps = []maps.Map{} + for _, stat := range pbStats { + if len(params.Method) > 0 && !strings.Contains(strings.ToLower(stat.Method), strings.ToLower(params.Method)) { + continue + } + if len(params.Tag) > 0 && !strings.Contains(strings.ToLower(stat.Tag), strings.ToLower(params.Tag)) { + continue + } + + statMaps = append(statMaps, maps.Map{ + "id": stat.Id, + "method": stat.Method, + "tag": stat.Tag, + "costMs": stat.CostMs, + "peekMs": stat.PeekMs, + "countCalls": stat.CountCalls, + }) + } + this.Data["stats"] = statMaps + + this.Show() +} diff --git a/web/views/@default/api/index.html b/web/views/@default/api/index.html index d15974cf..73bf2fa3 100644 --- a/web/views/@default/api/index.html +++ b/web/views/@default/api/index.html @@ -2,6 +2,7 @@ [添加节点] + 用时统计

暂时还没有节点。

diff --git a/web/views/@default/api/methodStats.html b/web/views/@default/api/methodStats.html new file mode 100644 index 00000000..df95dcb1 --- /dev/null +++ b/web/views/@default/api/methodStats.html @@ -0,0 +1,46 @@ +{$layout} + +
+
+
+
+ +
+
+ +
+
+ +
+
+ +   + 清除条件 +
+
+
+ + + + + + + + + + + + + + + + + + +
方法标签平均耗时峰值耗时调用次数
{{stat.method}}{{stat.tag}}{{stat.costMs}}ms{{stat.peekMs}}ms{{stat.countCalls}}次
\ No newline at end of file