Skip to content

Commit c73b120

Browse files
IronsDuclaude
andauthored
docs: update README to reflect post-refactor project state (#36)
* docs: update README to reflect post-refactor project state Sync documentation with the Drogon decoupling and singleton removal refactoring: updated project structure, dependency list, integration examples (non-singleton API, ProfilerHttpHandlers, Drogon optional), and added logging configuration section. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: fix outdated references and add README TOC - Fix profiler_lib → profiler_core/profiler_web across docs and cmake examples - Fix mainpage.dox: remove singleton pattern, update includes and features - Fix docs/README.md: update broken library API links - Fix 06_using_find_package.md: update file structure, link targets - Add navigation TOC to README.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 444b531 commit c73b120

8 files changed

Lines changed: 172 additions & 81 deletions

File tree

README.md

Lines changed: 136 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
# C++ Remote Profiler
22

3-
类似 Go pprof 和 brpc pprof service 的 C++ 远程性能分析工具,基于 gperftools 和 Drogon 框架实现。
3+
类似 Go pprof 和 brpc pprof service 的 C++ 远程性能分析工具,基于 gperftools 和 Drogon 框架(可选)实现。
4+
5+
## 目录
6+
7+
- [版本说明](#-版本说明)
8+
- [功能特性](#-功能特性)
9+
- [设计理念](#-设计理念)
10+
- [快速开始](#-快速开始)
11+
- [使用方法](#-使用方法)
12+
- [如何查看火焰图](#-如何查看火焰图)
13+
- [API 端点](#-api-端点)
14+
- [项目结构](#-项目结构)
15+
- [运行测试](#-运行测试)
16+
- [代码格式检查](#-代码格式检查)
17+
- [集成到你的项目](#-集成到你的项目)
18+
- [配置说明](#-配置说明)
19+
- [注意事项](#-注意事项)
20+
- [与其他工具的对比](#-与其他工具的对比)
21+
- [许可证](#-许可证)
422

523
**当前版本**: v0.1.0 (开发阶段)
624

@@ -39,9 +57,13 @@
3957

4058
-**CPU Profiling**: 使用 gperftools 进行 CPU 性能分析
4159
-**Heap Profiling**: 内存使用分析和内存泄漏检测(调用 tcmalloc sample)
60+
-**Heap Growth Profiling**: 堆增长分析,无需 TCMALLOC_SAMPLE_PARAMETER 环境变量
4261
-**线程堆栈捕获**: 获取所有线程的调用堆栈,支持动态线程数
4362
-**标准 pprof 接口**: 支持 Go pprof 工具直接访问
4463
-**Web 界面**: 美观的 Web 控制面板,支持一键式火焰图分析
64+
-**框架无关**: ProfilerHttpHandlers 提供框架无关的 handler,可集成任意 Web 框架
65+
-**Drogon 可选**: Web 界面依赖 Drogon,但核心 profiling 功能完全独立
66+
-**可配置日志系统**: 支持自定义 LogSink,集成到应用日志系统
4567
-**RESTful API**: 完整的 HTTP API 接口
4668
-**依赖管理**: 使用 vcpkg 管理所有依赖
4769
-**信号处理器安全**: 保存并恢复用户程序的信号处理器
@@ -53,6 +75,11 @@
5375
1. **标准 pprof 模式**: 提供 `/pprof/profile``/pprof/heap` 接口,返回原始 profile 文件,兼容 Go pprof 工具
5476
2. **一键分析模式**: 提供 `/api/cpu/analyze` 等接口,直接返回 SVG,适合浏览器查看
5577

78+
**架构特点**:
79+
- **核心库与 Web 解耦**: `profiler_core` 不依赖任何 Web 框架,`profiler_web` 是可选的 Drogon 适配层
80+
- **框架无关的 Handler**: `ProfilerHttpHandlers` 返回 `HandlerResponse` 结构体,可与任意 Web 框架集成
81+
- **非单例设计**: `ProfilerManager` 是普通类,用户自行管理生命周期
82+
5683
**接口命名规则**:
5784
- `/pprof/*` - 标准 Go pprof 接口
5885
- `/api/*` - 自定义分析接口(浏览器直接查看)
@@ -116,11 +143,14 @@ cd vcpkg
116143
```
117144

118145
这将自动安装以下依赖:
119-
- drogon (Web 框架)
146+
- drogon (Web 框架,可选)
120147
- gtest (测试框架)
121148
- nlohmann-json (JSON 库)
122149
- openssl
123150
- zlib
151+
- protobuf
152+
- backward-cpp (栈回溯)
153+
- gperftools (CPU/Heap 性能分析)
124154

125155
### 4. 编译项目
126156

@@ -290,24 +320,34 @@ cpp-remote-profiler/
290320
├── build.sh # 构建脚本
291321
├── start.sh # 启动脚本
292322
├── include/
293-
│ ├── profiler_manager.h # Profiler 管理器
294-
│ ├── symbolize.h # 符号化引擎
295-
│ ├── web_resources.h # Web 资源(嵌入的 HTML)
296-
│ ├── web_server.h # HTTP 服务器
297-
│ └── version.h # 版本信息
323+
│ ├── profiler_manager.h # Profiler 管理器(非单例)
324+
│ ├── profiler_version.h.in # 版本信息模板(CMake 生成)
325+
│ ├── version.h # 版本宏(向后兼容)
326+
│ └── profiler/
327+
│ ├── http_handlers.h # 框架无关的 HTTP 处理器
328+
│ ├── drogon_adapter.h # Drogon 适配层(可选)
329+
│ ├── log_sink.h # 日志 Sink 接口
330+
│ └── logger.h # 日志配置接口
298331
├── src/
299-
│ ├── profiler_manager.cpp
300-
│ ├── symbolize.cpp
332+
│ ├── profiler_manager.cpp # Profiler 管理器实现
333+
│ ├── symbolize.cpp # 符号化引擎
334+
│ ├── http_handlers.cpp # HTTP 处理器实现(框架无关)
335+
│ ├── drogon_adapter.cpp # Drogon 适配层实现(可选)
301336
│ ├── web_resources.cpp # 嵌入的 Web 资源
302-
│ └── web_server.cpp # HTTP 路由处理
337+
│ └── internal/ # 内部实现(不对外暴露)
338+
│ ├── log_manager.h/cpp # 日志管理器
339+
│ ├── default_log_sink.h/cpp # 默认日志实现(std::cout/cerr)
340+
│ ├── log_macros.h # 内部日志宏
341+
│ └── ... # 其他内部头文件
303342
├── example/
304343
│ ├── main.cpp # 示例程序主入口
305344
│ ├── workload.cpp # 工作负载示例
306345
│ ├── workload.h
307346
│ └── custom_signal.cpp # 自定义信号示例
308347
├── tests/
309-
│ ├── test_cpu_profile.cpp
310-
│ └── test_full_flow.cpp
348+
│ ├── test_cpu_profile.cpp # CPU profiling 测试
349+
│ ├── test_full_flow.cpp # 完整流程测试
350+
│ └── test_logger.cpp # 日志系统测试
311351
├── docs/ # 用户文档
312352
│ ├── README.md # 文档索引
313353
│ └── user_guide/ # 用户指南
@@ -317,15 +357,20 @@ cpp-remote-profiler/
317357
│ ├── 04_troubleshooting.md
318358
│ ├── 05_installation.md
319359
│ └── 06_using_find_package.md
360+
├── scripts/
361+
│ └── check-format.sh # 代码格式检查脚本
320362
└── vcpkg/ # vcpkg 包管理器
321363
```
322364

323365
## 🧪 运行测试
324366

325367
```bash
326368
cd build
369+
ctest --output-on-failure
370+
# 或单独运行:
327371
./test_cpu_profile
328372
./test_full_flow
373+
./test_logger
329374
```
330375

331376
运行完整的火焰图测试:
@@ -377,49 +422,70 @@ http://localhost:8080
377422

378423
## 💡 集成到你的项目
379424

380-
### 选项 1: 作为 HTTP 服务集成(推荐)
425+
### 选项 1: 仅使用核心 profiling 功能(无 Web 依赖)
426+
427+
只需链接 `profiler_core`,不需要 Drogon:
381428

382-
将 profiler 作为一个独立的 HTTP 服务运行:
429+
```cmake
430+
find_package(cpp-remote-profiler REQUIRED)
431+
target_link_libraries(my_app cpp-remote-profiler::profiler_core)
432+
```
383433

384434
```cpp
385-
#include <drogon/drogon.h>
435+
#include "profiler_manager.h"
386436

387437
int main() {
388-
// 启动 profiler HTTP 服务
389-
// 监听 8080 端口,提供 /prof 和 /heap 接口
390-
// 你的主程序可以在其他端口运行
391-
// 通过 HTTP 请求获取 profile 数据
438+
profiler::ProfilerManager profiler;
439+
440+
// 启动 CPU profiling
441+
profiler.startCPUProfiler("cpu.prof");
442+
443+
// ... 运行你的代码 ...
444+
445+
profiler.stopCPUProfiler();
446+
return 0;
392447
}
393448
```
394449

395-
### 选项 2: 使用 gperftools 直接集成
450+
### 选项 2: 使用 Drogon Web 界面(推荐)
451+
452+
链接 `profiler_web` 即可获得完整的 Web 控制面板:
453+
454+
```cmake
455+
find_package(cpp-remote-profiler REQUIRED)
456+
find_package(Drogon CONFIG REQUIRED)
457+
target_link_libraries(my_app
458+
cpp-remote-profiler::profiler_web
459+
Drogon::Drogon
460+
)
461+
```
396462

397463
```cpp
398-
#include <gperftools/profiler.h>
464+
#include "profiler_manager.h"
465+
#include "profiler/drogon_adapter.h"
466+
#include <drogon/drogon.h>
399467

400468
int main() {
401-
// 启动 CPU profiler
402-
ProfilerStart("/tmp/my_app.prof");
469+
profiler::ProfilerManager profiler;
470+
profiler::registerDrogonHandlers(profiler);
471+
drogon::app().addListener("0.0.0.0", 8080).run();
472+
}
473+
```
403474

404-
// 运行需要分析的代码
405-
yourCodeToProfile();
475+
### 选项 3: 与任意 Web 框架集成
406476

407-
// 停止 CPU profiler
408-
ProfilerStop();
477+
使用框架无关的 `ProfilerHttpHandlers`,只链接 `profiler_core`
409478

410-
// 使用 pprof 工具分析
411-
// go tool pprof /tmp/my_app.prof
412-
return 0;
413-
}
414-
```
479+
```cpp
480+
#include "profiler_manager.h"
481+
#include "profiler/http_handlers.h"
415482

416-
### 编译你的程序
483+
profiler::ProfilerManager profiler;
484+
profiler::ProfilerHttpHandlers handlers(profiler);
417485

418-
```bash
419-
g++ -o your_app your_app.cpp \
420-
-ltcmalloc_and_profiler \
421-
-lprofiler \
422-
-lpthread
486+
// 调用 handler,获得框架无关的响应
487+
auto resp = handlers.handleCpuAnalyze(10, "flamegraph");
488+
// resp.status, resp.content_type, resp.body → 用你的框架包装
423489
```
424490
425491
### 配置信号(可选)
@@ -430,10 +496,10 @@ g++ -o your_app your_app.cpp \
430496
#include "profiler_manager.h"
431497
432498
int main() {
433-
// 在使用 Profiler 之前设置信号
499+
// 在创建 ProfilerManager 之前设置信号
434500
profiler::ProfilerManager::setStackCaptureSignal(SIGRTMIN + 5);
435501
436-
auto& profiler = profiler::ProfilerManager::getInstance();
502+
profiler::ProfilerManager profiler;
437503
438504
// ... 正常使用 profiler ...
439505
}
@@ -446,6 +512,32 @@ int main() {
446512

447513
**示例程序**:参考 `example/custom_signal.cpp` 查看详细用法。
448514

515+
### 配置日志(可选)
516+
517+
可以自定义日志输出,集成到你的应用日志系统:
518+
519+
```cpp
520+
#include "profiler_manager.h"
521+
#include "profiler/log_sink.h"
522+
523+
class MyAppLogSink : public profiler::LogSink {
524+
public:
525+
void log(profiler::LogLevel level, const char* file, int line,
526+
const char* function, const char* message) override {
527+
// 转发到你的日志系统
528+
MY_APP_LOG("[Profiler] {}:{} - {}", file, line, message);
529+
}
530+
};
531+
532+
int main() {
533+
profiler::ProfilerManager profiler;
534+
profiler.setLogSink(std::make_shared<MyAppLogSink>());
535+
profiler.setLogLevel(profiler::LogLevel::Debug);
536+
537+
// ... 正常使用 profiler ...
538+
}
539+
```
540+
449541
## ⚙️ 配置说明
450542
451543
### 环境变量
@@ -485,11 +577,11 @@ cd vcpkg
485577
1. **编译选项**: 使用 `-g` 编译选项保留调试符号,以便正确显示函数名
486578
2. **性能开销**: CPU profiler 会有 1-5% 的性能开销
487579
3. **Heap Profiler**: 需要 tcmalloc 内存分配器和 `TCMALLOC_SAMPLE_PARAMETER` 环境变量
488-
4. **生产环境**: 谨慎使用,建议在开发/测试环境中使用
489-
5. **并发限制**: 同一时间只能有一个 CPU profiling 请求
490-
6. **环境变量**: 使用 heap profiling 前必须设置 `TCMALLOC_SAMPLE_PARAMETER`
580+
4. **Heap Growth**: 无需 `TCMALLOC_SAMPLE_PARAMETER`,可即时获取堆增长数据
581+
5. **生产环境**: 谨慎使用,建议在开发/测试环境中使用
582+
6. **并发限制**: 同一时间只能有一个 CPU profiling 请求
491583
7. **信号冲突**: 默认使用 SIGUSR1,如与你的程序冲突,请使用 `setStackCaptureSignal()` 配置其他信号
492-
8. **线程安全**: 线程堆栈捕获使用信号处理器,确保程序正确处理 SIGUSR1(或配置的信号)
584+
8. **线程安全**: 所有公共 API 都是线程安全的
493585

494586
## 🎨 与其他工具的对比
495587

cmake/examples/CMakeLists.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ FetchContent_MakeAvailable(cpp-remote-profiler)
2929
# Find dependencies (manual - since we're not using vcpkg here)
3030
find_package(PkgConfig REQUIRED)
3131
pkg_check_modules(GPERFTOOLS REQUIRED libprofiler libtcmalloc)
32-
find_package(Drogon REQUIRED)
32+
# Drogon is pulled in automatically by profiler_web target
3333

3434
# ============================================================================
3535
# Build example executable
@@ -38,8 +38,7 @@ find_package(Drogon REQUIRED)
3838
add_executable(fetch_content_example FetchContent_integration_example.cpp)
3939

4040
target_link_libraries(fetch_content_example
41-
profiler_lib
42-
Drogon::Drogon
41+
cpp-remote-profiler::profiler_web
4342
${GPERFTOOLS_LIBRARIES}
4443
)
4544

@@ -51,4 +50,4 @@ target_link_libraries(fetch_content_example
5150
# add_subdirectory(/path/to/cpp-remote-profiler)
5251

5352
# Then link:
54-
# target_link_libraries(your_app profiler_lib)
53+
# target_link_libraries(your_app cpp-remote-profiler::profiler_core)

cmake/examples/FetchContent_example.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ FetchContent_MakeAvailable(cpp-remote-profiler)
4848

4949
# Link to your target
5050
# target_link_libraries(your_target
51-
# cpp-remote-profiler::profiler_lib
51+
# cpp-remote-profiler::profiler_web
5252
# Drogon::Drogon # Required if using web features
5353
# )

docs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
详细的 API 文档(待完善)。
5555

5656
- [ProfilerManager API](library_api/profiler_manager.md)
57-
- [Symbolize API](library_api/symbolize.md)
58-
- [Web Server API](library_api/web_server.md)
57+
- [HTTP Handlers API](library_api/http_handlers.md)
58+
- [Log Sink API](library_api/log_sink.md)
5959

6060
### 开发者指南
6161
贡献者和维护者文档。

docs/mainpage.dox

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,26 @@
1010
*
1111
* - @b CPU @b Profiling: CPU performance analysis using gperftools
1212
* - @b Heap @b Profiling: Memory usage analysis and leak detection
13+
* - @b Heap @b Growth @b Profiling: Heap growth analysis (no env var needed)
1314
* - @b Thread @b Stack @b Capture: Get call stacks of all threads
1415
* - @b Standard @b pprof @b Interface: Compatible with Go pprof tools
16+
* - @b Framework @b Agnostic: ProfilerHttpHandlers work with any web framework
1517
* - @b Web @b Interface: Beautiful web control panel with one-click flame graph
1618
* - @b RESTful @b API: Complete HTTP API endpoints
19+
* - @b Configurable @b Logging: Custom LogSink integration
1720
*
1821
* @section getting_started Getting Started
1922
*
2023
* @subsection quick_example Quick Example
2124
*
2225
* @code{.cpp}
23-
* #include <drogon/drogon.h>
2426
* #include "profiler_manager.h"
25-
* #include "web_server.h"
27+
* #include "profiler/drogon_adapter.h"
28+
* #include <drogon/drogon.h>
2629
*
2730
* int main() {
28-
* auto& profiler = profiler::ProfilerManager::getInstance();
29-
*
30-
* // Register HTTP handlers
31-
* profiler::registerHttpHandlers(profiler);
32-
*
33-
* // Start HTTP server
31+
* profiler::ProfilerManager profiler;
32+
* profiler::registerDrogonHandlers(profiler);
3433
* drogon::app().addListener("0.0.0.0", 8080).run();
3534
* return 0;
3635
* }

0 commit comments

Comments
 (0)