feat(k8s): 事件页补全时间/次数/来源等字段

- 后端解析 source/reportingComponent 与 object_kind/name
- 新增 EventTable 统一展示:最后/首次时间、次数、重复跨度、类型、原因、对象、来源、消息
- Deployment 事件 Tab 与事件中心共用表格组件
This commit is contained in:
Logan.Li committed 2026-06-26 15:13:35 +08:00
1 parent ee2588fb52
commit b2939470f4
8 files changed
+323 -176

No files matched your search

+78 -23
View File
@@ -7,6 +7,7 @@ import (
"time"
"ezops/model"
k8sclient "ezops/pkg/kubernetesclient"
"github.com/gin-gonic/gin"
)
@@ -23,31 +24,42 @@ func (h *KubernetesHandler) ListEvents(c *gin.Context) {
if err != nil { c.JSON(500, model.Response{Code: 500, Message: "K8s API error: " + err.Error()}); return }
type EventSummary struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
Type string `json:"type"`
Reason string `json:"reason"`
Message string `json:"message"`
Object string `json:"object"`
Count int `json:"count"`
FirstTime string `json:"first_time"`
LastTime string `json:"last_time"`
Namespace string `json:"namespace"`
Name string `json:"name"`
Type string `json:"type"`
Reason string `json:"reason"`
Message string `json:"message"`
Object string `json:"object"`
ObjectKind string `json:"object_kind"`
ObjectName string `json:"object_name"`
Source string `json:"source"`
Count int `json:"count"`
FirstTime string `json:"first_time"`
LastTime string `json:"last_time"`
EventTime string `json:"event_time"`
}
result := []EventSummary{}
for _, e := range events.Items {
if eventType != "" && e.Type != eventType { continue }
object := fmt.Sprintf("%s/%s", e.InvolvedObject.Kind, e.InvolvedObject.Name)
objectKind := e.InvolvedObject.Kind
objectName := e.InvolvedObject.Name
object := fmt.Sprintf("%s/%s", objectKind, objectName)
if e.InvolvedObject.Namespace != "" {
object = fmt.Sprintf("%s/%s/%s", e.InvolvedObject.Namespace, e.InvolvedObject.Kind, e.InvolvedObject.Name)
object = fmt.Sprintf("%s/%s/%s", e.InvolvedObject.Namespace, objectKind, objectName)
}
firstTime, lastTime, eventTime := formatEventTimes(e)
count := int(e.Count)
if count <= 0 {
count = 1
}
firstTime := ""; if !e.FirstTimestamp.IsZero() { firstTime = e.FirstTimestamp.Format(time.RFC3339) }
lastTime := ""; if !e.LastTimestamp.IsZero() { lastTime = e.LastTimestamp.Format(time.RFC3339) }
result = append(result, EventSummary{
Namespace: e.Metadata.Namespace, Name: e.Metadata.Name, Type: e.Type, Reason: e.Reason,
Message: e.Message, Object: object, Count: int(e.Count),
FirstTime: firstTime, LastTime: lastTime,
Message: e.Message, Object: object, ObjectKind: objectKind, ObjectName: objectName,
Source: formatEventSource(e), Count: count,
FirstTime: firstTime, LastTime: lastTime, EventTime: eventTime,
})
}
sort.Slice(result, func(i, j int) bool { return result[i].LastTime > result[j].LastTime })
c.JSON(200, model.Response{Code: 200, Data: result})
}
@@ -122,15 +134,20 @@ func (h *KubernetesHandler) GetEventsSummary(c *gin.Context) {
// Collect recent warning events (top 10 by lastTimestamp)
if len(recentWarnings) < 50 {
firstTime, lastTime, eventTime := formatEventTimes(e)
recentWarnings = append(recentWarnings, map[string]interface{}{
"namespace": nsName,
"type": e.Type,
"reason": e.Reason,
"message": e.Message,
"object": fmt.Sprintf("%s/%s", e.InvolvedObject.Kind, e.InvolvedObject.Name),
"count": count,
"last_time": e.LastTimestamp.Format(time.RFC3339),
"first_time": e.FirstTimestamp.Format(time.RFC3339),
"namespace": nsName,
"type": e.Type,
"reason": e.Reason,
"message": e.Message,
"object": fmt.Sprintf("%s/%s", e.InvolvedObject.Kind, e.InvolvedObject.Name),
"object_kind": e.InvolvedObject.Kind,
"object_name": e.InvolvedObject.Name,
"source": formatEventSource(e),
"count": count,
"last_time": lastTime,
"first_time": firstTime,
"event_time": eventTime,
})
}
} else {
@@ -200,6 +217,44 @@ func (h *KubernetesHandler) GetEventsSummary(c *gin.Context) {
c.JSON(200, model.Response{Code: 200, Data: result})
}
// formatEventSource 格式化事件来源(component / reportingComponent)// Logan.Li
func formatEventSource(e k8sclient.EventItem) string {
if e.ReportingComponent != "" {
if e.ReportingInstance != "" {
return e.ReportingComponent + "/" + e.ReportingInstance
}
return e.ReportingComponent
}
src := e.Source.Component
if e.Source.Host != "" {
if src != "" {
return src + "@" + e.Source.Host
}
return e.Source.Host
}
return src
}
// formatEventTimes 提取首次/最后/事件时间(RFC3339)// Logan.Li
func formatEventTimes(e k8sclient.EventItem) (first, last, eventTime string) {
if !e.FirstTimestamp.IsZero() {
first = e.FirstTimestamp.Format(time.RFC3339)
}
if !e.LastTimestamp.IsZero() {
last = e.LastTimestamp.Format(time.RFC3339)
}
if !e.EventTime.IsZero() {
eventTime = e.EventTime.Format(time.RFC3339)
}
if last == "" && eventTime != "" {
last = eventTime
}
if first == "" && eventTime != "" {
first = eventTime
}
return first, last, eventTime
}
// ============================================================================
// Capacity Analysis — CPU/Memory request/limit per Deployment
// ============================================================================