GetRecentEvents returns recent events from the timeline
(c *gin.Context)
| 311 | |
| 312 | // GetRecentEvents returns recent events from the timeline |
| 313 | func (h *DashboardHandler) GetRecentEvents(c *gin.Context) { |
| 314 | ctx := c.Request.Context() |
| 315 | |
| 316 | // 检查 Registry 是否可用 |
| 317 | if h.registry == nil { |
| 318 | c.JSON(http.StatusOK, gin.H{ |
| 319 | "success": true, |
| 320 | "data": gin.H{ |
| 321 | "events": []gin.H{}, |
| 322 | "cursor": int64(0), |
| 323 | "message": "Registry not available, real-time events disabled", |
| 324 | }, |
| 325 | }) |
| 326 | return |
| 327 | } |
| 328 | |
| 329 | limitStr := c.DefaultQuery("limit", "100") |
| 330 | limit, err := strconv.Atoi(limitStr) |
| 331 | if err != nil || limit <= 0 { |
| 332 | limit = 100 |
| 333 | } |
| 334 | if limit > 1000 { |
| 335 | limit = 1000 |
| 336 | } |
| 337 | |
| 338 | // 从所有 Agent 的 EventBus 聚合事件 |
| 339 | var allEvents []types.AgentEventEnvelope |
| 340 | for _, eb := range h.registry.GetEventBuses() { |
| 341 | if eb != nil { |
| 342 | evts := eb.GetTimelineRange(0, limit) |
| 343 | allEvents = append(allEvents, evts...) |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | // 按时间戳排序(最新的在前) |
| 348 | sort.Slice(allEvents, func(i, j int) bool { |
| 349 | return allEvents[i].Bookmark.Timestamp > allEvents[j].Bookmark.Timestamp |
| 350 | }) |
| 351 | |
| 352 | // 限制数量 |
| 353 | if len(allEvents) > limit { |
| 354 | allEvents = allEvents[:limit] |
| 355 | } |
| 356 | |
| 357 | // 转换为响应格式 |
| 358 | result := make([]gin.H, 0, len(allEvents)) |
| 359 | for _, env := range allEvents { |
| 360 | result = append(result, gin.H{ |
| 361 | "cursor": env.Cursor, |
| 362 | "timestamp": time.UnixMilli(env.Bookmark.Timestamp), |
| 363 | "event": env.Event, |
| 364 | }) |
| 365 | } |
| 366 | |
| 367 | logging.Info(ctx, "dashboard.events.list", map[string]any{ |
| 368 | "count": len(result), |
| 369 | }) |
| 370 |
nothing calls this directly
no test coverage detected