本ページでは、syslog ファイルなど、CSV 形式のログファイルのログエントリを解析する方法について説明します。

CSV 形式ログファイルの標準ログエントリ解析

  • 生のログエントリ
    _program_:error
    _severity_:6
    _priority_:14
    _facility_:1
    topic:syslog-forwarder
    content:10.64.10.20|10/Jun/2019:11:32:16 +0800|m.zf.cn|GET /zf/11874.html HTTP/1.1|200|0.077|6404|10.11.186.82:8001|200|0.060|https://yz.m.sm.cn/s?q=%25%24%23%40%21&from=wy878378&uc_param_str=dnntnwvepffrgibijbprsvdsei|-|Mozilla/5.0 (Linux; Android 9; HWI-AL00 Build/HUAWEIHWI-A00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36|-|-
  • 変換の要件
    1. _program_ フィールドが access に設定されている場合、パイプ区切り値 (PSV) の解析は content フィールドに対して実行され、 content フィールドが削除されます。
    2. request: GET /css/mip-base.css HTTP/1.1 フィールドは request_methodhttp_version、および request フィールドに分割されます。
    3. URL のデコードは http_referer フィールドに対して実行されます。
    4. time フィールドはフォーマットされます。
  • ソリューション
    1. _program_ フィールドが access に設定されている場合、e_psv 関数を使用して content フィールドを解析し、content フィールドを削除します。
      e_if(e_search("_program_==access"), e_compose(e_psv("content", "remote_addr, time_local,host,request,status,request_time,body_bytes_sent,upstream_addr,upstream_status, upstream_response_time,http_referer,http_x_forwarded_for,http_user_agent,session_id,guid", restrict=True), e_drop_fields("content")))
      返されるログエントリは次のとおりです。
      __source__: 1.2.3.4
      __tag__:__client_ip__: 2.3.4.5
      __tag__:__receive_time__: 1562845168
      __topic__:  
      _facility_: 1
      _priority_: 14
      _program_: access
      _severity_: 6
      body_bytes_sent: 6404
      guid: -
      host: m.zf.cn
      http_referer: https://yz.m.sm.cn/s?q=%25%24%23%40%21&from=wy878378&uc_param_str=dnntnwvepffrgibijbprsvdsei
      http_user_agent: Mozilla/5.0 (Linux; Android 9; HWI-AL00 Build/HUAWEIHWI-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36
      http_x_forwarded_for: -
      remote_addr: 10.64.10.20
      request: GET /zf/11874.html HTTP/1.1
      request_time: 0.077
      session_id: -
      status: 200
      time_local: 10/Jun/2019:11:32:16 +0800
      topic: syslog-forwarder
      upstream_addr: 10.11.186.82:8001
      upstream_response_time: 0.060
      upstream_status: 200
    2. e_regex 関数を使用して request フィールドを解析し、request_methodrequest、および http_version フィールドに分割します。
      e_regex("request",r"^(? P<request_method>\w+) (? P<request>. +) (? P<http_version>\w+/[\d\.] +)$")
      返されるログエントリは次のとおりです。
      request: /zf/11874.html
      request_method: GET
      http_version: HTTP/1.1
    3. http_referer フィールドに URL デコードを実行します。
      e_set("http",url_decoding("http_referer"))
      返されるログエントリは次のとおりです。
      http: https://yz.m.sm.cn/s?q=%$#@! &from=wy878378&uc_param_str=dnntnwvepffrgibijbprsvdsei
    4. 時間をフォーマットします。
      e_set("time_local",dt_strptime(v("time"),"%d/%b/%Y:%H:%M:%S +0800"))
      返されるログエントリは次のとおりです。
      time_local: 2019-06-13 13:45:11
    5. 次の構文を実行します。
      e_if(e_search("_program_==access"), e_compose(e_psv("content", "remote_addr, time_local,host,request,status,request_time,body_bytes_sent,upstream_addr,upstream_status, upstream_response_time,http_referer,http_x_forwarded_for,http_user_agent,session_id,guid", restrict=True), e_drop_fields("content")))
      e_regex("request",r"^(? P<request_method>\w+) (? P<request>. +) (? P<http_version>\w+/[\d\.]+)$")
      e_set("http",url_decoding("http_referer"))
      e_set("time_local",dt_strptime(v("time"),"%d/%b/%Y:%H:%M:%S +0800"))
  • 出力ログの内容
    __source__: 1.2.3.4
    __tag__:__client_ip__: 2.3.4.5
    __tag__:__receive_time__: 1562840879
    __topic__:  
    _facility_: 1
    _priority_: 14
    _program_: access
    _severity_: 6
    body_bytes_sent: 6404
    guid: -
    host: m.zf.cn
    http_referer: https://yz.m.sm.cn/s?q=%E8%9B%8B%E8%8A%B1%E9%BE%99%E9%A1%BB%E9%9D%A2%E7%9A%84%E5%81%9A%E6%B3%95&from=wy878378&uc_param_str=dnntnwvepffrgibijbprsvdsei
    http_user_agent: Mozilla/5.0 (Linux; Android 9; HWI-AL00 Build/HUAWEIHWI-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36
    http_x_forwarded_for: -
    remote_addr: 10.64.xx.xx
    request: GET /zf/11874.html HTTP/1.1
    request_time: 0.077
    session_id: -
    status: 200
    time_local: 10/Jun/2019:11:32:16 +0800
    topic: syslog-forwarder
    upstream_addr: 10.11.xx.xx:8001
    upstream_response_time: 0.060
    upstream_status: 200
    http: https://yz.m.sm.cn/s?q=%$#@!&from=wy878378&uc_param_str=dnntnwvepffrgibijbprsvdsei

CSV 形式ログファイルの非標準ログエントリ解析

次の例は、CSV 形式のログファイル内の非標準のログエントリを解析する方法を示しています。
  • 生のログエントリ
    __source__: 1.2.3.4
    __tag__:__client_ip__: 2.3.4.5
    __tag__:__receive_time__: 1562840879
    __topic__:  
    content: 101.132.xx.xx|07/Aug/2019:11:10:37 +0800|www.123.com|GET /alyun/htsw/? ad=5|8|6|11| HTTP/1.1|200|6.729|14559|1.2.3.4:8001|200|6.716|-|-|Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D))||
  • 変換の要件

    content フィールドが解析されます。

  • ソリューション
    content フィールドで、GET /alyun/htsw/? ad=5|8|6|11| HTTP/1.1 部分から e_csv 関数を使用して正しいフィールドを解析できない場合、この内容を抽出し、content フィールド内のその部分を null に置き換えます。
    e_if(e_search("not remote_addr: *"), e_compose(e_regex("content", r"[^\|]+\|[^\|]+\|[^\|]+\|(? P<request>(. +)HTTP/\d.\d)"), e_set("content", regex_replace(v("content"), r"([^\|]+\|[^\|]+\|[^\|]+)\|((. +)HTTP/\d.\d)\|(.+)",replace= r"\1||\4")), e_psv("content", "remote_addr,time_local,host,request,status,request_time,body_bytes_sent,upstream_addr,upstream_status, upstream_response_time,http_referer,http_x_forwarded_for,http_user_agent,session_id,guid", restrict=True)))
    e_drop_fields("content")
  • 出力ログの内容
    __source__: 1.2.3.4
    __tag__:__client_ip__: 2.3.4.5
    __tag__:__receive_time__: 1562840879
    __topic__:  
    body_bytes_sent: 14559
    host: www.123.com
    http_referer: -
    http_user_agent: Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D))
    http_x_forwarded_for: -
    remote_addr: 101.132.xx.xx
    request: GET /alyun/htsw/? ad=5|8|6|11| HTTP/1.1
    request_time: 6.729
    status: 200
    time_local: 07/Aug/2019:11:10:37 +0800
    upstream_addr: 1.2.3.4:8001
    upstream_response_time: 6.716
    upstream_status: 200