{"id":34955972,"url":"https://github.com/null-object-0000/http-log-snap","last_synced_at":"2025-12-29T13:48:00.423Z","repository":{"id":327329258,"uuid":"1107406079","full_name":"null-object-0000/http-log-snap","owner":"null-object-0000","description":"一个轻量级的 Java HTTP 请求/响应日志记录库，快照式捕获完整的 HTTP 交互。同时支持客户端（如 OkHttp）和服务端（如 Spring MVC）场景。","archived":false,"fork":false,"pushed_at":"2025-12-04T07:18:38.000Z","size":141,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-06T03:01:40.845Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/null-object-0000.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-01T05:05:28.000Z","updated_at":"2025-12-04T07:18:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/null-object-0000/http-log-snap","commit_stats":null,"previous_names":["null-object-0000/http-log-snap"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/null-object-0000/http-log-snap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fhttp-log-snap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fhttp-log-snap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fhttp-log-snap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fhttp-log-snap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/null-object-0000","download_url":"https://codeload.github.com/null-object-0000/http-log-snap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fhttp-log-snap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28062355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-26T02:00:06.189Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-26T22:10:56.748Z","updated_at":"2025-12-26T22:10:57.370Z","avatar_url":"https://github.com/null-object-0000.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HTTP Log Snap 📸\n\n一个轻量级的 Java HTTP 请求/响应日志记录库，**快照式**捕获完整的 HTTP 交互。\n\n同时支持 **客户端**（OkHttp）和 **服务端**（Spring MVC）场景。\n\n## ✨ 为什么选择 HTTP Log Snap？\n\n- 🔄 **双向支持** - 客户端发起请求、服务端处理请求，一套 API 全搞定\n- ⏱️ **详细耗时** - DNS、连接、TTFB、下载...每个阶段耗时一目了然\n- 📊 **多种格式** - 文本格式便于调试，JSON 格式便于分析\n- 🛡️ **脱敏支持** - Authorization、Cookie 等敏感头自动脱敏\n- 🎯 **零侵入** - 不改业务代码，Filter/EventListener 即插即用\n- 🔧 **可扩展** - 格式化器、输出目标、适配器全部可定制\n\n## 📦 安装\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.null-object-0000\u003c/groupId\u003e\n    \u003cartifactId\u003ehttp-log-snap\u003c/artifactId\u003e\n    \u003cversion\u003e0.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## 🚀 30 秒上手\n\n### 客户端（OkHttp）\n\n```java\n// 1. 创建 OkHttpClient\nOkHttpClient client = new OkHttpClient.Builder()\n    .eventListenerFactory(OkHttpLoggingEventListener.FACTORY)\n    .build();\n\n// 2. 创建 Logger\nHttpRequestLogger logger = HttpRequestLogger.forClient(HttpLogContext.of(\"创建订单\"));\nlogger.putExtra(\"orderId\", \"ORD123\");\n\n// 3. 发起请求\nString body = \"{\\\"name\\\":\\\"test\\\"}\";\nlogger.start(body);\nRequest request = new Request.Builder()\n    .url(\"https://api.example.com/orders\")\n    .tag(HttpRequestLogger.class, logger)\n    .post(RequestBody.create(body, MediaType.parse(\"application/json\")))\n    .build();\ntry (Response response = client.newCall(request).execute()) {\n    logger.end(response.body().string());\n}\n\n// 4. 输出日志\nlogger.log();\n```\n\n### 服务端（Spring Boot）\n\n```yaml\n# application.yml\nmc:\n  http:\n    logging:\n      enabled: true\n```\n\n```java\n// 方式1：实现 HttpLogCustomizer 统一定制（推荐）\n@Component\npublic class MyHttpLogCustomizer implements HttpLogCustomizer {\n    @Override\n    public void customize(HttpRequestLogger logger, HttpServletRequest request) {\n        // 添加 traceId\n        logger.putExtra(\"traceId\", request.getHeader(\"X-Trace-Id\"));\n        // 根据路径设置接口名称\n        if (request.getRequestURI().startsWith(\"/api/users\")) {\n            logger.setInterfaceName(\"用户服务\");\n        }\n    }\n}\n\n// 方式2：在 Controller 中按需设置\nHttpRequestLogger logger = HttpRequestLoggerHolder.get();\nif (logger != null) {\n    logger.putExtra(\"orderId\", \"ORD123\");\n}\n\n// 方式3：在全局异常处理器中记录异常（如果有 GlobalExceptionHandler）\n@RestControllerAdvice\npublic class GlobalExceptionHandler {\n    @ExceptionHandler(Exception.class)\n    public BaseResponse\u003c?\u003e errorHandler(Exception e) {\n        HttpLoggingExceptionHandler.record(e);  // 添加这一行\n        // ... 原有逻辑\n        return BaseResponse.error();\n    }\n}\n```\n\n**搞定！** 服务端自动记录所有 HTTP 请求/响应。\n\n## 📝 日志输出效果\n\n### 客户端日志\n\n```\n15:42:31.123 --- LOG EXTRAS -------------------------------------------------------\n{\"userId\":10086,\"source\":\"app\"}\n15:42:31.123 --- START [NONE] 获取用户信息 (total: 245ms)\n15:42:31.180 --\u003e DNS LOOKUP (50ms)\n15:42:31.210 --\u003e CONNECTING (30ms) [192.168.1.100:54321 -\u003e 203.0.113.50:443]\n15:42:31.215 --\u003e REQUEST START ---------------------------------------------------\u003e\nGET https://api.example.com/users/123 HTTP/2\nAuthorization: ██\n\n15:42:31.350 \u003c-- RESPONSE START \u003c--------------------------------------------------\nHTTP/2 200 OK (130ms)\nContent-Type: application/json\n\n{\"id\":123,\"name\":\"张三\",\"email\":\"zhangsan@example.com\"}\n15:42:31.368 \u003c-- END RESPONSE (18ms, 256-byte body)\n```\n\n### 服务端日志\n\n```\n15:42:31.100 --- LOG EXTRAS -------------------------------------------------------\n{\"orderId\":\"ORD123\",\"channel\":\"web\"}\n15:42:31.100 --- START [SERVER] 用户登录 -\u003e UserController.login (total: 156ms) [client: 192.168.1.50:52341]\n15:42:31.102 --\u003e REQUEST START ---------------------------------------------------\u003e\nPOST http://localhost:8080/api/login HTTP/1.1\nContent-Type: application/json\n\n{\"username\":\"zhangsan\",\"password\":\"****\"}\n15:42:31.245 \u003c-- RESPONSE START \u003c--------------------------------------------------\n200 OK (handler: 135ms)\n\n{\"code\":0,\"message\":\"success\",\"data\":{\"token\":\"eyJ...\"}}\n15:42:31.256 \u003c-- END RESPONSE (11ms, 128-byte body)\n```\n\n### JSON 格式（便于 ELK 分析）\n\n```json\n{\n  \"type\": \"HTTP_CLIENT\",\n  \"duration_ms\": 245,\n  \"network\": {\n    \"local_address\": \"192.168.1.100:54321\",\n    \"remote_address\": \"203.0.113.50:443\"\n  },\n  \"request\": {\n    \"method\": \"GET\",\n    \"url\": \"https://api.example.com/users/123\"\n  },\n  \"response\": {\n    \"code\": 200,\n    \"body\": \"{\\\"id\\\":123,\\\"name\\\":\\\"张三\\\"}\"\n  },\n  \"timing\": {\n    \"dns_lookup_ms\": 50,\n    \"connection_ms\": 30,\n    \"server_processing_ms\": 130\n  }\n}\n```\n\n## ⏱️ 性能指标\n\n| 客户端指标 | 服务端指标 |\n|-----------|-----------|\n| DNS 解析时间 | 请求体读取时间 |\n| TCP/TLS 连接时间 | Handler 执行时间 |\n| 请求发送时间 | 响应构建时间 |\n| TTFB（首字节时间）| 响应发送时间 |\n| 内容下载时间 | 框架开销时间 |\n\n## ⚙️ 默认配置\n\n| 配置项 | 默认值                    | 说明                 |\n|--------|------------------------|--------------------|\n| 格式化器 | `JsonHttpLogFormatter` | JSON 格式            |\n| 输出目标 | `Slf4jLogOutput`       | 输出到 SLF4J（INFO 级别） |\n| 请求体/响应体最大长度 | `无限制` | 默认不限制，可通过配置设置限制（超过限制会被截断） |\n\n**⚠️ 重要提示：** 请求体和响应体的最大记录长度默认**无限制**（`-1`）。如果设置了限制值，超过此长度的内容会被截断，并在日志中显示 `... [truncated N bytes]` 提示。建议根据实际日志系统的限制（如单条日志限制为 512KB 的系统）来设置合适的限制值。可通过配置修改 `maxPayloadLength`、`maxRequestBodyLength` 或 `maxResponseBodyLength`。\n\n**切换格式化器：**\n\n```java\n// 使用 JSON 格式\nHttpRequestLogger.setDefaultFormatter(new JsonHttpLogFormatter());\n\n// 使用美化的 JSON 格式\nHttpRequestLogger.setDefaultFormatter(new JsonHttpLogFormatter(true));\n\n// 使用 JSON 格式 + 记录完整事件序列（用于分析调用链路）\nHttpRequestLogger.setDefaultFormatter(new JsonHttpLogFormatter()\n    .setPrettyPrint(true)\n    .setIncludeEvents(true));\n```\n\n**切换输出目标：**\n\n```java\n// 输出到控制台\nHttpRequestLogger.setDefaultOutput(new ConsoleLogOutput());\n\n// 输出到 SLF4J DEBUG 级别\nHttpRequestLogger.setDefaultOutput(new Slf4jLogOutput(Slf4jLogOutput.LogLevel.DEBUG));\n\n// 同时输出到多个目标\nHttpRequestLogger.setDefaultOutput(CompositeLogOutput.of(\n    new Slf4jLogOutput(),\n    new ConsoleLogOutput()\n));\n```\n\n**配置请求体/响应体最大长度：**\n\n```java\n// 服务端：通过 HttpLoggingFilter 配置\nHttpLoggingFilter filter = new HttpLoggingFilter();\nfilter.setMaxPayloadLength(512 * 1024); // 设置为 512KB\n\n// 格式化器：通过 AbstractHttpLogFormatter 配置\nJsonHttpLogFormatter formatter = new JsonHttpLogFormatter();\nformatter.setMaxRequestBodyLength(512 * 1024);  // 请求体最大长度\nformatter.setMaxResponseBodyLength(512 * 1024); // 响应体最大长度\n\n// Spring Boot 自动配置（application.yml）\nmc:\n  http:\n    logging:\n      max-payload-length: 512000  # 512KB（单位：字节，-1 表示无限制）\n```\n\n## 📚 文档\n\n- [📖 使用指南](docs/guide.md) - 完整的使用教程\n- [🔧 高级用法](docs/advanced.md) - 自定义格式化器、输出目标、适配器\n- 💡 接入示例 - 在 IDE 中直接运行：\n  - OkHttp 客户端: `src/test/java/.../demo/OkHttpClientDemo.java`\n  - Spring Boot 服务端: `src/test/java/.../demo/SpringBootServerDemo.java`\n\n## 🤝 贡献\n\n欢迎提交 Issue 和 Pull Request！\n\n## 📄 许可证\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnull-object-0000%2Fhttp-log-snap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnull-object-0000%2Fhttp-log-snap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnull-object-0000%2Fhttp-log-snap/lists"}