Files
higress/plugins/wasm-go/extensions/log-request-response

log-request-response 插件

这个插件用于在 Higress 的访问日志中添加以下信息:

  • HTTP 请求头(添加为 %FILTER_STATE(wasm.log-request-headers:PLAIN)%
  • POST、PUT、PATCH 请求的请求体内容(添加为 %FILTER_STATE(wasm.log-request-body:PLAIN)%
  • 响应头(添加为 %FILTER_STATE(wasm.log-response-headers:PLAIN)%
  • 响应体内容(添加为 %FILTER_STATE(wasm.log-response-body:PLAIN)%

配置参数

在 Higress 控制台配置该插件时,使用以下结构化的 YAML 配置:

# 请求相关配置
request:
  # 请求头配置
  headers:
    # 是否记录请求头默认false
    enabled: true
  # 请求体配置
  body:
    # 是否记录请求体内容默认false
    enabled: true
    # 最大记录长度限制单位字节默认10KB
    maxSize: 10240
    # 需要记录请求体的内容类型(默认包含常见的内容类型)
    contentTypes:
      - application/json
      - application/xml
      - application/x-www-form-urlencoded
      - text/plain

# 响应相关配置
response:
  # 响应头配置
  headers:
    # 是否记录响应头默认false
    enabled: true
  # 响应体配置
  body:
    # 是否记录响应体内容默认false
    enabled: true
    # 最大记录长度限制单位字节默认10KB
    maxSize: 10240
    # 需要记录响应体的内容类型(默认包含常见的内容类型)
    contentTypes:
      - application/json
      - application/xml
      - text/plain
      - text/html

工作原理

  1. 请求处理时,插件会根据配置决定是否记录请求头和请求体
  2. 只有当请求方法为 POST、PUT 或 PATCH且内容类型在配置的 request.body.contentTypes 列表中时,才会记录请求体
  3. 响应处理时,插件会根据配置决定是否记录响应头和响应体
  4. 只有当响应的内容类型在配置的 response.body.contentTypes 列表中时,才会记录响应体
  5. 所有记录的内容都会被限制在配置的 maxSize 指定的大小内
  6. 插件对请求体和响应体都使用流式处理方式,不会阻止或修改原始内容传递
  7. 记录的内容会被存储在 Envoy 的 Filter State 中,可以通过访问日志配置获取

编译方法

# 先整理依赖
go mod tidy

# 编译
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o ./main.wasm ./main.go

访问日志配置

要在 Higress 访问日志中显示插件添加的 Filter State 数据,需要修改 Higress 的访问日志配置。编辑 ConfigMap

kubectl edit cm -n higress-system higress-config

envoyAccessLogService.config.accessLog 下的 format 字段中添加以下内容:

{
  "request_headers": "%FILTER_STATE(wasm.log-request-headers:PLAIN)%",
  "request_body": "%FILTER_STATE(wasm.log-request-body:PLAIN)%",
  "response_headers": "%FILTER_STATE(wasm.log-response-headers:PLAIN)%",
  "response_body": "%FILTER_STATE(wasm.log-response-body:PLAIN)%"
}

完整的访问日志配置可能会像这样(添加到现有配置中):

mesh:
  accessLogFile: "/dev/stdout"
  accessLogFormat: |
    {
      "authority": "%REQ(:AUTHORITY)%",
      "bytes_received": "%BYTES_RECEIVED%",
      "bytes_sent": "%BYTES_SENT%",
      "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
      "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
      "duration": "%DURATION%",
      "method": "%REQ(:METHOD)%",
      "path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
      "protocol": "%PROTOCOL%",
      "request_id": "%REQ(X-REQUEST-ID)%",
      "requested_server_name": "%REQUESTED_SERVER_NAME%",
      "response_code": "%RESPONSE_CODE%",
      "response_flags": "%RESPONSE_FLAGS%",
      "route_name": "%ROUTE_NAME%",
      "start_time": "%START_TIME%",
      "trace_id": "%REQ(X-B3-TRACEID)%",
      "upstream_cluster": "%UPSTREAM_CLUSTER%",
      "upstream_host": "%UPSTREAM_HOST%",
      "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%",
      "upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
      "upstream_transport_failure_reason": "%UPSTREAM_TRANSPORT_FAILURE_REASON%",
      "user_agent": "%REQ(USER-AGENT)%",
      "x_forwarded_for": "%REQ(X-FORWARDED-FOR)%",
      "request_headers": "%FILTER_STATE(wasm.log-request-headers:PLAIN)%",
      "request_body": "%FILTER_STATE(wasm.log-request-body:PLAIN)%",
      "response_headers": "%FILTER_STATE(wasm.log-response-headers:PLAIN)%",
      "response_body": "%FILTER_STATE(wasm.log-response-body:PLAIN)%"
    }

日志输出示例

配置完成后Higress 的访问日志中将包含这些额外的字段(取决于您的配置启用了哪些选项):

{
  "authority": "example.com",
  "method": "POST",
  "path": "/api/users",
  "response_code": 200,
  "request_headers": "{\"host\":\"example.com\",\"path\":\"/api/users\",\"method\":\"POST\",\"content-type\":\"application/json\"}",
  "request_body": "{\"name\":\"测试用户\",\"email\":\"test@example.com\"}",
  "response_headers": "{\"content-type\":\"application/json\",\"status\":\"200\"}",
  "response_body": "{\"id\":123,\"status\":\"success\"}"
}

注意事项

  1. 所有日志记录选项默认都是关闭的false需要明确启用才会记录相应内容
  2. 对于大型请求体或响应体,可以通过 request.body.maxSizeresponse.body.maxSize 参数限制记录的长度,以避免日志过大
  3. 插件使用流式处理方式处理请求体和响应体,不会对原始内容产生任何影响
  4. 只有指定内容类型的 POST、PUT、PATCH 请求才会记录请求体内容
  5. 只有指定内容类型的响应才会记录响应体内容
  6. 请确保合理配置该插件,避免记录敏感信息到日志中