[2650-w0] feat(file_server): add WatchManager runner skeleton (pass-through)#2663
[2650-w0] feat(file_server): add WatchManager runner skeleton (pass-through)#2663Takuka0311 wants to merge 6 commits into
Conversation
Introduce WatchManager as a dedicated runner that centralizes access to the underlying EventListener. EventDispatcher now acquires and releases directory watches through WatchManager::AcquireWatch/ReleaseWatch instead of calling EventListener::AddWatch/RemoveWatch directly. This W0 step is pure pass-through: the two calls forward one-to-one to the previous syscalls with no added dedup, ref-counting or lifecycle change, so behavior is unchanged. The decision logic (inode recheck, mInotifyWatchNum accounting, blacklist/limit checks) stays in EventDispatcher. A runner_name = "watch_manager" MetricsRecordRef is registered on construction to establish an observability baseline. Closes alibaba#2652 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WatchManagerUnittest is not a friend of WriteMetrics, so calling the private GetHead() failed to compile (MSVC C2248 on CI, also an error on GCC/Clang). Iterate the committed records through the public DoSnapshot() instead, and free the caller-owned copies it returns to avoid a leak. Fixes alibaba#2652
Add TestSharedEventListenerInstance asserting WatchManager stores the same EventListener singleton that EventDispatcher captures. Both obtain it via EventListener::GetInstance() (Meyers singleton), so the pointers are guaranteed equal; this test makes the invariant explicit so a future refactor giving WatchManager its own listener fails loudly instead of silently desyncing the dispatcher's event loop. Addresses review on alibaba#2663. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| // MetricsRecordRef and commits it to WriteMetrics. | ||
| void TestMetricsRecordRegistered() { | ||
| WatchManager* wm = WatchManager::GetInstance(); | ||
| APSARA_TEST_TRUE_FATAL(wm->GetMetricsRecordRef().HasLabel( |
There was a problem hiding this comment.
c++的lint报错了,修复一下。
core/file_server/EventDispatcher.cpp:26:1: error: code should be clang-formatted [-Wclang-format-violations]
#include <errno.h>
^
Failed on file: core/file_server/EventDispatcher.cpp
core/unittest/file_server/WatchManagerUnittest.cpp:108:67: error: code should be clang-formatted [-Wclang-format-violations]
APSARA_TEST_TRUE_FATAL(wm->GetMetricsRecordRef().HasLabel(
^
core/unittest/file_server/WatchManagerUnittest.cpp:109:42: error: code should be clang-formatted [-Wclang-format-violations]
METRIC_LABEL_KEY_RUNNER_NAME, METRIC_LABEL_VALUE_RUNNER_NAME_WATCH_MANAGER));
^
Failed on file: core/unittest/file_server/WatchManagerUnittest.cpp
There was a problem hiding this comment.
c++的lint报错了,修复一下。 core/file_server/EventDispatcher.cpp:26:1: error: code should be clang-formatted [-Wclang-format-violations] #include <errno.h>
处理结果
已修复。用 CI 同款 clang-format 18.1.8(--style=file --dry-run --Werror)本地复现并修复:
core/file_server/EventDispatcher.cpp:clang-format对 include 按 大小写敏感 排序,file_server/WatchManager.h的大写W(0x57)须排在小写的checkpoint/、event/之前。将其上移一行即可(报错定位在:26是该 include block 的起始行)。core/unittest/file_server/WatchManagerUnittest.cpp:TestMetricsRecordRegistered中的HasLabel(...)断言按 120 列换行规则重排。
纯格式改动,无逻辑变更。
本地验证(loongcollector-build-linux:2.1.17 镜像,与 CI 对齐):
# 1) clang-format 18.1.8 —— 全部改动文件干净
$ clang-format --style=file --dry-run --Werror \
core/file_server/EventDispatcher.cpp \
core/unittest/file_server/WatchManagerUnittest.cpp
# exit 0,无输出
# 2) 编译 + 单测
$ make watch_manager_unittest event_dispatcher_dir_unittest
[100%] Built target watch_manager_unittest
[100%] Built target event_dispatcher_dir_unittest
$ ./unittest/file_server/watch_manager_unittest --gtest_filter=WatchManagerUnittest.*
[ PASSED ] 4 tests.
$ ./unittest/controller/event_dispatcher_dir_unittest --gtest_filter=EventDispatcherDirUnittest.*
[ PASSED ] 3 tests.
commit:ff840c15(已 push 到 PR head)。
说明:本地已
merge upstream/main同步主干;因合入的 AgentSight 升级依赖更新版coolbpf子模块,而本机无法访问该子模块远端,post-merge 全量构建无法在本地完成。故上述编译/单测在与合并树等价的 pre-merge 基线上验证(我改的两个文件均未被本次 merge 触碰),合并树交由具备子模块访问权限的 CI 校验。
[epic-console] from=agent role=feedback-handler action=none
clang-format 18 (CI StaticCheck) sorts includes case-sensitively, so "file_server/WatchManager.h" must precede the lowercase checkpoint/ and event/ entries. Also wrap the WatchManager label assertion in WatchManagerUnittest to match clang-format. Formatting only; no logic change. Fixes alibaba#2652
目标
新建
WatchManager作为独立 runner,包裹EventListener,对外暴露AcquireWatch(path)/ReleaseWatch(wd)统一中转AddWatch/RemoveWatch。本步骤为 pass-through 骨架:两处调用一对一转发原 syscall,不改任何去重/引用计数/生命周期语义;构造时注册runner_name = "watch_manager"的MetricsRecordRef,建立可观测基线。关联:Epic #2651,Discussion #2650 线 1 步骤 W0。
改动范围
core/file_server/WatchManager.{h,cpp}:pass-through runner,注册 watch_manager MetricsRecordRef。core/file_server/EventDispatcher.cpp:仅将AddWatch(:242)/RemoveWatch(:871)两处调用改为经WatchManager中转;判定逻辑(inode 复查、mInotifyWatchNum计数、黑名单/上限)保持不变。core/monitor/metric_constants/RunnerMetrics.cpp+MetricConstants.h:新增METRIC_LABEL_VALUE_RUNNER_NAME_WATCH_MANAGER = "watch_manager"常量。core/unittest/file_server/(新增WatchManagerUnittest+ CMakeLists);core/unittest/CMakeLists.txt挂载子目录。未创建
core/file_server/CMakeLists.txt:core 源码经SUB_DIRECTORIES_LISTGLOB 收集,WatchManager.cpp自动纳入编译。Test plan
本地 Docker 构建镜像(
loongcollector-build-linux:2.1.17,WITHSPL=OFF ENABLE_AGENTSIGHT=OFF)编译并运行:WatchManagerUnittest.TestAcquireReleasePassThrough— 断言逐次一对一转发、wd 原样返回、release 转发一致。WatchManagerUnittest.TestNoDedupAtWatchManager— 断言本层不去重(同路径两次 add 转发两次),与旧行为等价。WatchManagerUnittest.TestMetricsRecordRegistered— 断言runner_name=watch_manager的 MetricsRecordRef 成功注册并提交到 WriteMetrics。EventDispatcherDirUnittest.*(TestFindAllSubDirAndHandler / TestUnregisterAllDir / TestStopAllDir)。结果:
watch_manager_unittest3/3 PASSED,event_dispatcher_dir_unittest3/3 PASSED,构建 exit 0(-Werror全绿)。Closes #2652