格式规则和命令操作符:

格式规则:

访问日志格式包含提取并相关数据并插入到格式指定处的命令运算符, 目前支持两种格式 

    format strings: 格式字符串

    format dictionaries: 格式字典

命令操作符:

    用于提取数据并插入到日志中

    有些操作符对于TCP和HTTP来说其含义有所不同

    几个操作符示例

    %REQ(X?Y):Z%: 记录HTTP请求报文的指定标头( X) 的值, Y是备用标头, Z是可选参数, 表示字符串截断并保留最多Z个字符; X和Y标头均不存在时记录为“-”; TCP不支持;

    %RESP(X?Y):Z%: 记录HTTP响应报文的指定标头的值; TCP不支持;

    %DURATION%:

        HTTP: 从开始时间到最后一个字节输出的请求的总持续时长( 以毫秒为单位) ;

        TCP: 下游连接的总持续时长( 以毫秒为单位);


访问日志格式:

默认格式:

[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%"
%RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION%
%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%"
"%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n

HTTP2示例:

[2019-10-25T10:17:00.310Z] "POST /api/v1/locations HTTP/2" 204 - 154 0 226 100 "10.0.35.28"
"nsq2http" "cc21d9b0-cf5c-432b-8c7e-98aeb7988cd2" "locations" "tcp://172.19.0.8:80"

HTTP/1.1示例:

[2019-10-25T10:32:38.228Z] "GET / HTTP/1.1" 200 - 0 78 1007 1006 "-" "curl/7.58.0" "f509df84-34d2-4643-a0fd-260f2dc67714"
"172.19.0.2" "172.19.0.3:80"

JSON格式:

json_format: {"start": "[%START_TIME%] ", "method": "%REQ(:METHOD)%", "url": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
"protocol": "%PROTOCOL%", "status": "%RESPONSE_CODE%", "respflags": "%RESPONSE_FLAGS%", "bytes-received":
"%BYTES_RECEIVED%", "bytes-sent": "%BYTES_SENT%", "duration": "%DURATION%", "upstream-service-time": "%RESP(X-ENVOYUPSTREAM-SERVICE-TIME)%", "x-forwarded-for": "%REQ(X-FORWARDED-FOR)%", "user-agent": "%REQ(USER-AGENT)%", "requestid": "%REQ(X-REQUEST-ID)%", "authority": "%REQ(:AUTHORITY)%", "upstream-host": "%UPSTREAM_HOST%", "remote-ip":
"%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%"}

输出格式:

{"start":"[2019-10-29T12:10:31.974Z] ","status":"200","upstream-host":"172.19.0.6:8786","upstream-service-time":"8","bytesreceived":"0","url":"/","authority":"172.19.0.7","protocol":"HTTP/1.1","duration":"8","bytes-sent":"81","request-id":"fd052903-2b2b-
4f0e-b457-00e3e3cdf7b2","x-forwarded-for":"172.19.0.1","respflags":"-","method":"GET","user-agent":"curl/7.58.0","remoteip":"172.19.0.1"}

配置语法和案例:

filter_chains:
  filters:
  - name: envoy.http_connection_manager
    config:
      ...
      access_log:
        name: ... # 要实例化的访问日志实现的名称, 该名称必须与静态注册的访问日志相匹配, 当前的内置的日志记录器有envoy.file_access_log、
                  # envoy.http_grpc_access_log和envoy.tcp_grpc_access_log, 且它们三者分别有着各自不同的配置;
        filter: {...} # 日志信息过滤器, 用于确定指定的信息是否能够写入日志;
        config: {...} # 由name字段实例出的日志实现的具体配置信息; 下面给出的嵌套字段属于envoy.file_access_log;
          path: ... # 本地文件系统上的日志文件路径;
          format: ... # 访问日志格式字符串, Envoy有默认的日志格式, 也支持用户自定义; format与json_format二者仅能使用其一;
          json_format: {...} # json格式的访问日志字符串;

示例:

node:
  id: front-envoy
  cluster: mycluster

admin:
  access_log_path: "/dev/null"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

static_resources:
  listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 80
    name: listener_http
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          codec_type: auto
          access_log:
          - name: envoy.file_access_log
            config:
              path: "/dev/stdout"
              json_format: {"start": "[%START_TIME%] ", "method": "%REQ(:METHOD)%", "url": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", "protocol": "%PROTOCOL%", "status": "%RESPONSE_CODE%", "respflags": "%RESPONSE_FLAGS%", "bytes-received": "%BYTES_RECEIVED%", "bytes-sent": "%BYTES_SENT%", "duration": "%DURATION%", "upstream-service-time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%", "x-forwarded-for": "%REQ(X-FORWARDED-FOR)%", "user-agent": "%REQ(USER-AGENT)%", "request-id": "%REQ(X-REQUEST-ID)%", "authority": "%REQ(:AUTHORITY)%", "upstream-host": "%UPSTREAM_HOST%", "remote-ip": "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%"}
              #format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" \"%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%\"\n"
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: vh_001
              domains: ["*"] 
              routes:
              - match: 
                  prefix: "/"
                route:
                  cluster: mycluster
          http_filters:
          - name: envoy.router

  clusters:
  - name: mycluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    http2_protocol_options: {}
    load_assignment:
      cluster_name: blue
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: myservice
                port_value: 80

收集日志的filebeat配置:

filebeat.inputs:
- type: container
  paths: 
    - '/var/lib/docker/containers/*/*.log'

processors:
- add_docker_metadata:
    host: "unix:///var/run/docker.sock"

- decode_json_fields:
    fields: ["message"]
    target: "json"
    overwrite_keys: true

output.elasticsearch:
  hosts: ["elasticsearch:9200"]
  indices:
    - index: "filebeat-%{[agent.version]}-%{+yyyy.MM.dd}"

logging.json: true
logging.metrics.enabled: false