ambiguous-pointer opened a new pull request, #1487:
URL: https://github.com/apache/dubbo-admin/pull/1487
This change introduces a complete event timeline feature for applications,
instances, and services
based on [discussion
#1474](https://github.com/apache/dubbo-admin/discussions/1474) and
[issue #1472](https://github.com/apache/dubbo-admin/issues/1472).
It ingests Kubernetes events via the cluster API and records platform
events from ZooKeeper
and Nacos registration centers, merging them into a unified, time-sorted
timeline with full
frontend visualization.
---
## ๐ What's New
### Kubernetes Event Ingestion
* **K8sEvent resource type**
`K8sEventResource` with proto `K8sEvent` spec
(`api/mesh/v1alpha1/k8s_event.proto` +
Go generated code). Captures namespace, reason, message, type, involved
object kind/name,
source component/host, first/last timestamps, count, and a static
`EventSource: "KUBERNETES"` marker.
* **K8sEventListerWatcher**
New `K8sEventListerWatcher`
(`pkg/engine/kubernetes/listerwatcher/k8s_event.go`) watches
`api/v1/events` across all namespaces using `client-go`'s `ListWatch` +
`TransformFunc`.
Registered in the K8s `EngineFactory` alongside the existing
`PodListerWatcher`.
* **K8sEvent store indexes** (`pkg/core/store/index/k8s_event.go`)
`ByK8sEventInvolvedObjKind`, `ByK8sEventInvolvedObjName`,
`ByK8sEventType`, `ByK8sEventSource`
โ enables efficient queries by mesh, involved object, event type, and
source.
### Platform Event Recording (ZooKeeper & Nacos)
* **PlatformEvent resource type**
`PlatformEventResource` with `PlatformEvent` spec
(`pkg/core/resource/apis/mesh/v1alpha1/platformevent_types.go`).
Carries `AppName`, `InstanceName`, `InstanceIP`, `ServiceName`, `Type`
(normal/warning),
`Message`, `Source` (Zookeeper/Nacos), `SourceType`
(provider/consumer/config), `Category`,
`Action`, and `EventTime`.
* **Shared platform event recorder**
(`pkg/core/discovery/subscriber/platform_event_recorder.go`)
`recordPlatformEvent()` utility that creates `PlatformEventResource`
instances and persists
them directly to the store via
`storeRouter.ResourceKindRoute(PlatformEventKind)`.
* **ZooKeeper config change events**
`ZKConfigEventSubscriber` (`pkg/core/discovery/subscriber/zk_config.go`)
records
`tag-route`, `condition-route`, and `dynamic-config`
added/updated/deleted events
via `recordConfigPlatformEvent()`.
* **ZooKeeper metadata change events**
`ZKMetadataEventSubscriber`
(`pkg/core/discovery/subscriber/zk_metadata.go`) records
provider and consumer metadata added/updated events via
`recordMetadataPlatformEvent()`.
* **Nacos instance registration/deregistration events**
`NacosServiceEventSubscriber`
(`pkg/core/discovery/subscriber/nacos_service.go`)
records `Nacos instance registered`, `deregistered`, and `updated`
events with
application name, IP, and port via `recordNacosInstanceEvents()`.
* **Nacos consumer metadata change events**
Same subscriber records `Nacos consumer metadata added` / `updated`
events
via `recordNacosConsumerEvents()`.
* **PlatformEvent store indexes**
(`pkg/core/store/index/platform_event.go`)
`ByPlatformEventAppName`, `ByPlatformEventInstanceName`,
`ByPlatformEventInstanceIP`,
`ByPlatformEventServiceName`, `ByPlatformEventSourceType` โ enables
per-entity event queries.
### Unified Event Timeline Query Service
* **Console API endpoints** (`pkg/console/service/event.go`)
| Endpoint | Description |
|---|---|
| `GET /application/event` | Lists K8s + Platform events for an
application |
| `GET /instance/event` | Lists K8s + Platform events for an instance (by
name/IP) |
| `GET /service/event` | Lists K8s + Platform events for a service |
Each endpoint queries both `K8sEvent` and `PlatformEvent` stores in
parallel,
merges results, sorts by time descending, and returns paginated unified
timeline entries.
```json
{
"code": "Success",
"message": "success",
"data": {
"list": [
{
"time": "2026-06-07 17:39:14",
"type": "warning",
"message": "Error updating Endpoint Slices...",
"source": "endpoint-slice-controller"
},
{
"time": "2026-06-07 10:25:04",
"type": "normal",
"message": "Zookeeper provider metadata added: demo-app โ
com.example.TestService",
"source": "Zookeeper"
},
{
"time": "2026-06-07 10:25:05",
"type": "normal",
"message": "Nacos instance registered: shop-order
10.244.1.29:20882",
"source": "Nacos"
}
],
"total": 78
}
}
```
### Frontend Event Timeline Visualization
* **EventTimeline shared component**
(`ui-vue3/src/components/EventTimeline.vue`)
Reusable Vue component with alternating left/right timeline layout using
Ant Design.
Each event node displays: timestamp, icon (check-circle for normal,
warning for warnings),
message text, and source tag. Supports infinite scroll with "load more"
pagination.
Degraded/expired events show an empty state with "่ฟๆไบไปถไธไผๅญๅจ" (expired
events
are not stored) watermark.
* **Application event tab**
(`ui-vue3/src/views/resources/applications/tabs/event.vue`)
Wires the EventTimeline component into the application detail page as an
"ไบไปถ" tab.
Queries events filtered by `appName` and current `mesh`.
* **Instance event tab**
(`ui-vue3/src/views/resources/instances/tabs/event.vue`)
Wires the EventTimeline component into the instance detail page as an
"ไบไปถ" tab.
Queries events filtered by `instanceName` and `instanceIP`.
* **Service event tab**
(`ui-vue3/src/views/resources/services/tabs/event.vue`)
Wires the EventTimeline component into the service detail page as an
"ไบไปถ" tab.
Queries events filtered by `serviceName`.
* **Event tab restored in routes** (`ui-vue3/src/router/defaultRoutes.ts`)
Event tab routes previously commented out are now enabled for all three
resource types.
### Minor Improvements
* **EventBus log level** (`pkg/core/events/component.go`)
"no subscriber for resource" message downgraded from `INFO` to `DEBUG`
to reduce
log noise (991 occurrences per 5 minutes for `K8sEvent` and `Service`).
---
## ๐ Affected Areas / Review Checklist
| Area | Files | What to Review |
|---|---|---|
| API | `api/mesh/v1alpha1/k8s_event.go`, `k8s_event.proto` | New proto +
generated code for K8sEvent |
| Console API | `pkg/console/service/event.go`, `handler/event.go`,
`model/event.go`, `router/router.go` | Event query logic, merge + sort +
pagination |
| Core Component | `pkg/core/events/component.go` | Log level change |
| Core Component |
`pkg/core/resource/apis/mesh/v1alpha1/k8sevent_types.go`,
`platformevent_types.go` | Resource type definitions |
| Core Component | `pkg/core/store/index/k8s_event.go`,
`platform_event.go` | Index definitions for queries |
| Discovery Subscriber | `pkg/core/discovery/subscriber/nacos_service.go`,
`zk_config.go`, `zk_metadata.go` | PlatformEvent recording side-effects |
| Discovery Subscriber |
`pkg/core/discovery/subscriber/platform_event_recorder.go` | Shared recording
utility |
| Engine | `pkg/engine/kubernetes/factory.go`,
`listerwatcher/k8s_event.go` | K8s Event ListWatcher registration + transform |
| Frontend | `ui-vue3/src/components/EventTimeline.vue` | Reusable
timeline component |
| Frontend |
`ui-vue3/src/views/resources/{applications,instances,services}/tabs/event.vue`
| Event tab pages |
| Frontend | `ui-vue3/src/api/service/{app,instance,service}.ts` | Event
API calls |
| Frontend | `ui-vue3/src/router/defaultRoutes.ts` | Route restoration |
| Frontend | `ui-vue3/src/types/api.ts` | EventItem type definition |
---
## ๐ Data Flow Architecture
```
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ K8s API โ โ ZK /services/* โ โ Nacos naming โ
โ /api/v1/ โ โ /dubbo/metadata/ โ โ service list โ
โ events โ โ /dubbo/config/ โ โ / config page โ
โโโโโโโโฌโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ListerWatcher (List + Watch via client-go / ZK client / โ
โ nacos-sdk-go) โ
โ โ
โ K8sEventLW PodLW ZKLW(x4) NacosLW(x6) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Informer (DeltaFIFO โ Store + EventBus) โ
โ HandleDeltas(): โ
โ indexer.Add/Update/Delete(resource) โ Store โ
โ EmitEvent() โ eventBus.Send(ResourceChangedEvent) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโโ
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Store (PG/Memory/ โ โ EventBus โ Subscribers โ
โ MySQL) โ โ โ
โ โ โ ZKConfigEventSubscriber โ
โ K8sEvent โ โ โโ recordConfigPlatformEvent()โ
โ PlatformEvent โ โ ZKMetadataEventSubscriber โ
โ Application โ โ โโ recordMetadataPlatformEvt()โ
โ Instance โ โ NacosServiceEventSubscriber โ
โ Service โ โ โโ recordNacosInstanceEvents()โ
โโโโโโโโโโฌโโโโโโโโโโโโ โ โโ recordNacosConsumerEvents()โ
โ โโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโ
โ โ
โ โโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโ
โ โ recordPlatformEvent() โ
โ โ โ eventStore.Add( โ
โ โ PlatformEventResource) โ
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Console API (event.go) โ
โ ListApplicationEvents() / ListInstanceEvents() / โ
โ ListServiceEvents() โ
โ โ
โ Query K8sEvent + PlatformEvent stores โ
โ โ Merge โ Sort by time DESC โ Paginate โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Frontend EventTimeline.vue โ
โ Alternating L/R timeline with infinite scroll โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ 2026-06-07 17:39:14 โ โ
โ โ โ Error updating Endpoint Slices... โ โ
โ โ endpoint-slice-ctrlโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ 2026-06-07 10:25:04 โ โ
โ โ โ Zookeeper provider metadata added: โ โ
โ โ demo-app โ com.example.TestService โ โ
โ โ Zookeeper โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
---
## ๐งช E2E Verification
Tested against a 6-node kind cluster (`cluster-ha-new`, k8s v1.35.1) with:
| Component | Status | Events Recorded |
|---|---|---|
| K8s Engine | 78 K8sEvent rows | Pod scheduling, creation, readiness
probes, restart |
| ZooKeeper discovery | 11 PlatformEvent rows | Consumer/provider metadata
added/updated |
| Nacos2 discovery | 2 PlatformEvent rows | Instance
registered/deregistered |
| PostgreSQL persistence | 9 PlatformEvent rows persisted across restart |
Events survive backend restart |
| Frontend event tabs | All 3 resource types verified | Timeline, source
tags, icons render correctly |
| Registry dropdown | Switching between ZK / Nacos / default mesh | Events
filter correctly by mesh |
---
## ๐ฎ Known Limitations
1. **K8s events use mesh "default"** โ K8s events are not associated with
any discovery
mesh. The frontend registry selector must be set to "default" (or
unset) to view
K8s events. There is a UX gap: the registry dropdown does not show
"default" as an
explicit option.
2. **No event TTL / cleanup** โ Events accumulate indefinitely in the
store. There is
no retention policy, TTL, or automatic cleanup mechanism for any store
backend.
3. **No subscriber for K8sEvent and Service** โ K8sEvent and Service
resources are
stored but no event subscriber processes them (by design โ they only
need storage).
The EventBus emits a "no subscriber" debug log for these kinds.
4. **PlatformEvent bypasses EventBus** โ PlatformEvents are created as
side-effects
within subscriber `ProcessEvent` methods and stored directly via
`eventStore.Add()`, bypassing the EventBus entirely. This means
PlatformEvents
themselves cannot be observed by downstream subscribers.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]