From b95f29318530bd1c2f9007e26398b777dc91fad6 Mon Sep 17 00:00:00 2001 From: tiny-craft <137850705+tiny-craft@users.noreply.github.com> Date: Thu, 2 Nov 2023 22:28:12 +0800 Subject: [PATCH] feat: add slow log --- backend/services/connection_service.go | 62 ++++++ .../src/components/content/ContentLogPane.vue | 2 +- .../src/components/content/ContentPane.vue | 6 +- .../components/content_value/ContentSlog.vue | 198 ++++++++++++++++++ frontend/src/langs/en-us.json | 13 +- frontend/src/langs/zh-cn.json | 13 +- frontend/src/stores/connections.js | 18 ++ 7 files changed, 307 insertions(+), 5 deletions(-) create mode 100644 frontend/src/components/content_value/ContentSlog.vue diff --git a/backend/services/connection_service.go b/backend/services/connection_service.go index e519760..8f65844 100644 --- a/backend/services/connection_service.go +++ b/backend/services/connection_service.go @@ -11,6 +11,7 @@ import ( "net" "net/url" "os" + "sort" "strconv" "strings" "sync" @@ -33,6 +34,14 @@ type cmdHistoryItem struct { Cost int64 `json:"cost"` } +type slowLogItem struct { + Timestamp int64 `json:"timestamp"` + Client string `json:"client"` + Addr string `json:"addr"` + Cmd string `json:"cmd"` + Cost int64 `json:"cost"` +} + type connectionService struct { ctx context.Context conns *ConnectionsStorage @@ -1613,6 +1622,59 @@ func (c *connectionService) CleanCmdHistory() (resp types.JSResp) { return } +// GetSlowLogs get slow log list +func (c *connectionService) GetSlowLogs(connName string, db int, num int64) (resp types.JSResp) { + item, err := c.getRedisClient(connName, db) + if err != nil { + resp.Msg = err.Error() + return + } + + client, ctx := item.client, item.ctx + var logs []redis.SlowLog + if cluster, ok := client.(*redis.ClusterClient); ok { + // cluster mode + var mu sync.Mutex + err = cluster.ForEachShard(ctx, func(ctx context.Context, cli *redis.Client) error { + if subLogs, _ := client.SlowLogGet(ctx, num).Result(); len(subLogs) > 0 { + mu.Lock() + logs = append(logs, subLogs...) + mu.Unlock() + } + return nil + }) + } else { + logs, err = client.SlowLogGet(ctx, num).Result() + } + if err != nil { + resp.Msg = err.Error() + return + } + + sort.Slice(logs, func(i, j int) bool { + return logs[i].Time.UnixMilli() > logs[j].Time.UnixMilli() + }) + if len(logs) > int(num) { + logs = logs[:num] + } + + list := sliceutil.Map(logs, func(i int) slowLogItem { + return slowLogItem{ + Timestamp: logs[i].Time.UnixMilli(), + Client: logs[i].ClientName, + Addr: logs[i].ClientAddr, + Cmd: sliceutil.JoinString(logs[i].Args, " "), + Cost: logs[i].Duration.Milliseconds(), + } + }) + + resp.Success = true + resp.Data = map[string]any{ + "list": list, + } + return +} + // update or insert key info to database //func (c *connectionService) updateDBKey(connName string, db int, keys []string, separator string) { // dbStruct := map[string]any{} diff --git a/frontend/src/components/content/ContentLogPane.vue b/frontend/src/components/content/ContentLogPane.vue index 12714c3..def1835 100644 --- a/frontend/src/components/content/ContentLogPane.vue +++ b/frontend/src/components/content/ContentLogPane.vue @@ -74,7 +74,7 @@ defineExpose({ diff --git a/frontend/src/components/content/ContentPane.vue b/frontend/src/components/content/ContentPane.vue index 5815ffb..21cac89 100644 --- a/frontend/src/components/content/ContentPane.vue +++ b/frontend/src/components/content/ContentPane.vue @@ -13,6 +13,7 @@ import ContentValueWrapper from '@/components/content_value/ContentValueWrapper. import ContentCli from '@/components/content_value/ContentCli.vue' import Monitor from '@/components/icons/Monitor.vue' import Pub from '@/components/icons/Pub.vue' +import ContentSlog from '@/components/content_value/ContentSlog.vue' const themeVars = useThemeVars() @@ -164,7 +165,7 @@ watch( - + + - +