4. Access Log 格式字符串详解:常用命令符与格式化选项

Envoy 的 Access Log 格式字符串由一系列命令符(Command Operators)和格式化选项组成。命令符以 % 包裹,用于从请求/响应中提取特定字段;格式化选项则控制字段的显示方式、长度、默认值等。掌握这些元素是定制高效、可读性强的日志格式的基础。

核心原则:命令符区分大小写,且必须严格遵循 %OPERATOR_NAME% 或 %OPERATOR_NAME(PARAMETER)% 的语法。Envoy 在解析格式字符串时,会从左到右依次替换每个命令符为实际值。

4.1 常用命令符分类与详解

命令符按数据来源可分为三大类:请求相关(%REQ%)、响应相关(%RESP%)和动态元数据(%DYNAMIC_METADATA%)。此外还有大量基础命令符用于获取时间、连接信息等。

类别 命令符 说明 典型输出示例
请求 %REQ(X?Y):Z% 提取请求头 X,若不存在则返回 Y,并截断为 Z 字符 GET / application/json
%START_TIME% 请求开始时间(ISO 8601 格式) 2025-03-21T14:30:00.000Z
%REQ_WITHOUT_QUERY% 不带查询参数的请求路径 /api/v1/users
响应 %RESP(X?Y):Z% 提取响应头 X,若不存在则返回 Y,并截断为 Z 字符 200 / text/html
%RESPONSE_CODE% HTTP 响应状态码 200 / 503
元数据 %DYNAMIC_METADATA(NS:KEY):Z% 从动态元数据中提取命名空间 NS 下的键 KEY,截断为 Z 字符 canary-v2 / 0.95
%METADATA(NS:KEY)% 从静态元数据(Listener/Cluster 配置)中提取值 us-east-1
连接 %DOWNSTREAM_REMOTE_ADDRESS% 下游客户端 IP 地址 10.0.0.1:54321
%UPSTREAM_HOST% 上游目标主机地址 192.168.1.10:8080
时间 %DURATION% 整个请求处理耗时(毫秒) 12

4.2 核心命令符深度解析

4.2.1 %REQ%:请求头提取器

%REQ(X?Y):Z% 是最常用的请求头提取命令符。其语法结构为:

  • X:要提取的请求头名称(不区分大小写)。
  • ?Y(可选):当请求头 X 不存在时,返回的默认值。如果省略 ?Y 且头不存在,则输出 -。
  • :Z(可选):最大字符截断长度。如果提取的值超过 Z 个字符,则截断并追加 ..。
示例:
%REQ(USER-AGENT?unknown):50% → 提取 User-Agent 头,若不存在则输出 unknown,且最多保留 50 个字符。
%REQ(AUTHORIZATION)% → 提取 Authorization 头,若不存在则输出 -。

4.2.2 %RESP%:响应头提取器

%RESP(X?Y):Z% 的语法与 %REQ% 完全一致,但提取的是响应头。注意:响应头仅在响应阶段可用,如果日志在请求阶段被刷新,则可能输出默认值。

避坑提示:对于 %RESP(X)%,如果上游未返回该响应头,且未指定默认值 ?Y,Envoy 会输出 -。这在调试时容易误判为“头被删除”,实际是上游未发送。

4.2.3 %DYNAMIC_METADATA%:动态元数据提取器

%DYNAMIC_METADATA(NS:KEY):Z% 用于提取 Envoy 在请求处理过程中动态附加的元数据。这些元数据通常由 RBAC 过滤器、外部授权(ExtAuthz)、Lua 过滤器或 Wasm 扩展写入。

  • NS:元数据的命名空间(Namespace),通常与写入过滤器的名称一致。
  • KEY:元数据中的具体键名,支持点号分隔的嵌套路径(如 auth.result)。
  • :Z(可选):截断长度。
典型场景:
%DYNAMIC_METADATA(envoy.filters.http.ext_authz:auth.principal)% → 提取外部授权过滤器写入的认证主体信息。
%DYNAMIC_METADATA(envoy.filters.http.rbac:shadow_engine_result)% → 提取 RBAC 影子模式下的评估结果。

4.3 格式化选项:控制输出精度

格式化选项通过 : 附加在命令符后,用于控制数值格式、时间格式和字符串长度。

格式化选项 适用命令符 说明 示例
:Z %REQ%, %RESP%, %DYNAMIC_METADATA% 字符串截断为 Z 字符,超长部分以 .. 结尾 %REQ(HOST):20% → example.com 或 very-long-hostname...
%START_TIME%:%s %START_TIME% Unix 时间戳(秒) 1742555400
%START_TIME%:%f %START_TIME% Unix 时间戳(微秒) 1742555400123456
%DURATION%:%f %DURATION% 浮点数格式,保留微秒精度 12.345
%BYTES_RECEIVED%:Z %BYTES_RECEIVED% 数字右对齐,最小宽度 Z %BYTES_RECEIVED%:10 → 1024

4.4 命令符组合与格式字符串构建

一个完整的 Access Log 格式字符串由多个命令符和分隔符(如空格、制表符 \t、竖线 |)拼接而成。Envoy 支持两种格式定义方式:

  1. 内联字符串:直接在配置文件中写 "%START_TIME% %REQ(X-METHOD)% %RESPONSE_CODE%"。
  2. 格式字符串文件:通过 access_log_format_string 字段引用外部文件,便于管理和复用。
生产级格式示例:
[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %UPSTREAM_HOST% "%REQ(USER-AGENT):50%" "%REQ(REFERER):50%" "%DYNAMIC_METADATA(envoy.filters.http.ext_authz:auth.principal)?-"

该格式包含了时间、请求行、状态码、响应标志、流量字节、耗时、上游地址、客户端信息以及外部授权元数据,适用于微服务网关的全面审计。

命令符数据流与格式化处理流程 原始请求/响应 动态元数据 连接/时间信息 命令符解析引擎 %REQ(X?Y):Z% | %RESP(X?Y):Z% | %DYNAMIC_METADATA(NS:KEY):Z% | %DURATION%:%f 格式化选项应用 截断 :Z | 时间格式 :%s / :%f | 数字对齐 :Z 格式化日志行输出 [2025-03-21T14:30:00.000Z] "GET /api ..." 200 12ms 数据源 解析 → 格式化 → 输出

4.5 常见陷阱与最佳实践

陷阱 1:命令符大小写敏感
%req(X-My-Header)% 是无效的,必须写作 %REQ(X-My-Header)%。Envoy 只识别大写命令符名称。
陷阱 2:默认值中的特殊字符
如果默认值 ?Y 中包含 ? 或 : 字符,需要使用反斜杠转义,例如 %REQ(X?question\?mark)%。
最佳实践:
  • 始终为 %REQ% 和 %RESP% 指定默认值,避免日志中出现大量 - 导致解析困难。
  • 对长字符串(如 User-Agent)使用截断选项 :Z,防止日志行过长影响存储和查询性能。
  • 使用 %DYNAMIC_METADATA% 时,确保命名空间与过滤器配置完全一致,否则输出始终为默认值。
  • 在开发环境中先使用 %REQ(HEADER)% 不带默认值,以便快速发现缺失的请求头。

4.6 实战:构建变更门禁审计日志格式

在变更门禁场景中,我们需要记录每个请求的变更操作类型、目标资源、审批状态以及执行用户。以下是一个针对门禁场景的格式字符串:

format_string: |
  [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%"
  %RESPONSE_CODE% %RESPONSE_FLAGS%
  user="%REQ(X-AUTH-USER?unknown)%"
  action="%REQ(X-CHANGE-ACTION?none)%"
  resource="%REQ(X-CHANGE-RESOURCE?none)%"
  approval="%DYNAMIC_METADATA(envoy.filters.http.ext_authz:approval.status)?pending%"
  duration=%DURATION%ms
  upstream=%UPSTREAM_HOST%
字段说明:
  • X-AUTH-USER:由前置认证过滤器注入的请求头,标识操作人。
  • X-CHANGE-ACTION 和 X-CHANGE-RESOURCE:客户端发送的变更意图。
  • approval:从外部授权过滤器动态元数据中提取的审批状态,可能为 approved、rejected 或 pending。
  • duration:记录整个审批流程的耗时,用于性能监控。

通过上述格式,运维人员可以快速检索到所有 approval="rejected" 的日志行,定位被拒绝的变更请求及其原因。