项目作者: tkuchiki

项目描述 :
Access Log Profiler
高级语言: Go
项目地址: git://github.com/tkuchiki/alp.git
创建时间: 2015-09-24T10:10:02Z
项目社区:https://github.com/tkuchiki/alp

开源协议:MIT License

下载


alp

Test

alp is Access Log Profiler

日本語

Installation

Binary distribution

You can pick your download here, and install it as follows:

  1. sudo install <downloaded file> /usr/local/bin/alp

Using your distribution’s package system

macOS (Homebrew)

Install alp with Homebrew

  • brew install alp

asdf

Install alp with asdf and asdf-alp

  1. asdf plugin-add alp https://github.com/asdf-community/asdf-alp.git
  2. asdf install alp <version>
  3. asdf global alp <version>

The difference between v0.4.0 and v1.0.0

See: The difference between v0.4.0 and v1.0.0

Usage

  1. $ alp --help
  2. alp is the access log profiler for LTSV, JSON, Pcap, and others.
  3. Usage:
  4. alp [flags]
  5. alp [command]
  6. Available Commands:
  7. completion Generate the autocompletion script for the specified shell
  8. count Count by log entries
  9. diff Show the difference between the two profile results
  10. help Help about any command
  11. json Profile the logs for JSON
  12. ltsv Profile the logs for LTSV
  13. pcap Profile the HTTP requests for captured packets
  14. regexp Profile the logs that match a regular expression
  15. Flags:
  16. -h, --help help for alp
  17. -v, --version version for alp
  18. Use "alp [command] --help" for more information about a command.
  19. $ alp ltsv --help
  20. Profile the logs for LTSV
  21. Usage:
  22. alp ltsv [flags]
  23. Flags:
  24. --apptime-label string Change the apptime label (default "apptime")
  25. --config string The configuration file
  26. --decode-uri Decode the URI
  27. --dump string Dump profiled data as YAML
  28. --file string The slowlog file
  29. -f, --filters string Only the logs are profiled that match the conditions
  30. --format string The output format (table, markdown, tsv, csv and html) (default "table")
  31. -h, --help help for ltsv
  32. --limit int The maximum number of results to display (default 5000)
  33. --load string Load the profiled YAML data
  34. --location string Location name for the timezone (default "Local")
  35. -m, --matching-groups string Specifies Query matching groups separated by commas
  36. --method-label string Change the method label (default "method")
  37. --noheaders Output no header line at all (only --format=tsv, csv)
  38. --nosave-pos Do not save position file
  39. -o, --output string Specifies the results to display, separated by commas (default "all")
  40. --page int Number of pages of pagination (default 100)
  41. --percentiles string Specifies the percentiles separated by commas
  42. --pos string The position file
  43. --qs-ignore-values Ignore the value of the query string. Replace all values with xxx (only use with -q)
  44. -q, --query-string Include the URI query string
  45. --reqtime-label string Change the reqtime label (default "reqtime")
  46. -r, --reverse Sort results in reverse order
  47. --show-footers Output footer line at all (only --format=table, markdown)
  48. --size-label string Change the size label (default "size")
  49. --sort string Output the results in sorted order (default "count")
  50. --status-label string Change the status label (default "status")
  51. --time-label string Change the time label (default "time")
  52. --uri-label string Change the uri label (default "uri")
  53. $ alp json --help
  54. Profile the logs for JSON
  55. Usage:
  56. alp json [flags]
  57. Flags:
  58. --body-bytes-key string Change the body_bytes key (default "body_bytes")
  59. --config string The configuration file
  60. --decode-uri Decode the URI
  61. --dump string Dump profiled data as YAML
  62. --file string The slowlog file
  63. -f, --filters string Only the logs are profiled that match the conditions
  64. --format string The output format (table, markdown, tsv, csv and html) (default "table")
  65. -h, --help help for json
  66. --limit int The maximum number of results to display (default 5000)
  67. --load string Load the profiled YAML data
  68. --location string Location name for the timezone (default "Local")
  69. -m, --matching-groups string Specifies Query matching groups separated by commas
  70. --method-key string Change the method key (default "method")
  71. --noheaders Output no header line at all (only --format=tsv, csv)
  72. --nosave-pos Do not save position file
  73. -o, --output string Specifies the results to display, separated by commas (default "all")
  74. --page int Number of pages of pagination (default 100)
  75. --percentiles string Specifies the percentiles separated by commas
  76. --pos string The position file
  77. --qs-ignore-values Ignore the value of the query string. Replace all values with xxx (only use with -q)
  78. -q, --query-string Include the URI query string
  79. --reqtime-key string Change the request_time key (default "request_time")
  80. --restime-key string Change the response_time key (default "response_time")
  81. -r, --reverse Sort results in reverse order
  82. --show-footers Output footer line at all (only --format=table, markdown)
  83. --sort string Output the results in sorted order (default "count")
  84. --status-key string Change the status key (default "status")
  85. --time-key string Change the time key (default "time")
  86. --uri-key string Change the uri key (default "uri")
  87. $ alp regexp --help
  88. Profile the logs that match a regular expression
  89. Usage:
  90. alp regexp [flags]
  91. Flags:
  92. --body-bytes-subexp string Change the body_bytes sub expression (default "body_bytes")
  93. --config string The configuration file
  94. --decode-uri Decode the URI
  95. --dump string Dump profiled data as YAML
  96. --file string The slowlog file
  97. -f, --filters string Only the logs are profiled that match the conditions
  98. --format string The output format (table, markdown, tsv, csv and html) (default "table")
  99. -h, --help help for regexp
  100. --limit int The maximum number of results to display (default 5000)
  101. --load string Load the profiled YAML data
  102. --location string Location name for the timezone (default "Local")
  103. -m, --matching-groups string Specifies Query matching groups separated by commas
  104. --method-subexp string Change the method sub expression (default "method")
  105. --noheaders Output no header line at all (only --format=tsv, csv)
  106. --nosave-pos Do not save position file
  107. -o, --output string Specifies the results to display, separated by commas (default "all")
  108. --page int Number of pages of pagination (default 100)
  109. --pattern string Regular expressions pattern matching the log (default "^(\\S+)\\s\\S+\\s+(\\S+\\s+)+\\[(?P<time>[^]]+)\\]\\s\"(?P<method>\\S*)\\s?(?P<uri>(?:[^\"]*(?:\\\\\")?)*)\\s([^\"]*)\"\\s(?P<status>\\S+)\\s(?P<body_bytes>\\S+)\\s\"((?:[^\"]*(?:\\\\\")?)*)\"\\s\"(?:.+)\"\\s(?P<response_time>\\S+)(?:\\s(?P<request_time>\\S+))?$")
  110. --percentiles string Specifies the percentiles separated by commas
  111. --pos string The position file
  112. --qs-ignore-values Ignore the value of the query string. Replace all values with xxx (only use with -q)
  113. -q, --query-string Include the URI query string
  114. --reqtime-subexp string Change the request_time sub expression (default "request_time")
  115. --restime-subexp string Change the response_time sub expression (default "response_time")
  116. -r, --reverse Sort results in reverse order
  117. --show-footers Output footer line at all (only --format=table, markdown)
  118. --sort string Output the results in sorted order (default "count")
  119. --status-subexp string Change the status sub expression (default "status")
  120. --time-subexp string Change the time sub expression (default "time")
  121. --uri-subexp string Change the uri sub expression (default "uri")
  122. $ alp pcap --help
  123. Profile the HTTP requests for captured packets
  124. Usage:
  125. alp pcap [flags]
  126. Flags:
  127. --config string The configuration file
  128. --decode-uri Decode the URI
  129. --dump string Dump profiled data as YAML
  130. --file string The slowlog file
  131. -f, --filters string Only the logs are profiled that match the conditions
  132. --format string The output format (table, markdown, tsv, csv and html) (default "table")
  133. -h, --help help for pcap
  134. --limit int The maximum number of results to display (default 5000)
  135. --load string Load the profiled YAML data
  136. --location string Location name for the timezone (default "Local")
  137. -m, --matching-groups string Specifies Query matching groups separated by commas
  138. --noheaders Output no header line at all (only --format=tsv, csv)
  139. --nosave-pos Do not save position file
  140. -o, --output string Specifies the results to display, separated by commas (default "all")
  141. --page int Number of pages of pagination (default 100)
  142. --pcap-server-ip strings HTTP server IP address of the captured packets (default [127.0.0.1])
  143. --pcap-server-port uint16 HTTP server TCP port of the captured packets (default 80)
  144. --percentiles string Specifies the percentiles separated by commas
  145. --pos string The position file
  146. --qs-ignore-values Ignore the value of the query string. Replace all values with xxx (only use with -q)
  147. -q, --query-string Include the URI query string
  148. -r, --reverse Sort results in reverse order
  149. --show-footers Output footer line at all (only --format=table, markdown)
  150. --sort string Output the results in sorted order (default "count")
  151. $ alp diff --help
  152. Show the difference between the two profile results
  153. Usage:
  154. alp diff <from> <to> [flags]
  155. Flags:
  156. --from string The comparison source file
  157. -h, --help help for diff
  158. --to string The comparison target file
  159. $ alp count --help
  160. Count by log entries
  161. Usage:
  162. alp count [flags]
  163. Flags:
  164. --file string The access log file
  165. --format string Log format (json,ltsv,regexp) (default "json")
  166. -h, --help help for count
  167. --keys string Log key names (comma separated)
  168. --pattern string Regular expressions pattern matching the log. (only use with --format=regexp) (default "^(\\S+)\\s\\S+\\s+(\\S+\\s+)+\\[(?P<time>[^]]+)\\]\\s\"(?P<method>\\S*)\\s?(?P<uri>(?:[^\"]*(?:\\\\\")?)*)\\s([^\"]*)\"\\s(?P<status>\\S+)\\s(?P<body_bytes>\\S+)\\s\"((?:[^\"]*(?:\\\\\")?)*)\"\\s\"(?:.+)\"\\s(?P<response_time>\\S+)(?:\\s(?P<request_time>\\S+))?$")
  169. -r, --reverse Sort results in reverse order

ltsv

  • Parses a log in LTSV format
  • By default, the following labels are parsed:
    • time
      • datetime
    • method
      • HTTP Method
    • uri
      • URI
    • status
      • HTTP Status Code
    • apptime
      • Response time from the upstream server
    • reqtime
      • Request Processing Time (Response time after receiving a request)
  • The --xxx-label option can you change the name to any label
  1. $ cat example/logs/ltsv_access.log
  2. time:2015-09-06T05:58:05+09:00 method:POST uri:/foo/bar?token=xxx&uuid=1234 status:200 size:12 apptime:0.057
  3. time:2015-09-06T05:58:41+09:00 method:POST uri:/foo/bar?token=yyy status:200 size:34 apptime:0.100
  4. time:2015-09-06T06:00:42+09:00 method:GET uri:/foo/bar?token=zzz status:200 size:56 apptime:0.123
  5. time:2015-09-06T06:00:43+09:00 method:GET uri:/foo/bar status:400 size:15 apptime:-
  6. time:2015-09-06T05:58:44+09:00 method:POST uri:/foo/bar?token=yyy status:200 size:34 apptime:0.234
  7. time:2015-09-06T05:58:44+09:00 method:POST uri:/hoge/piyo?id=yyy status:200 size:34 apptime:0.234
  8. time:2015-09-06T05:58:05+09:00 method:POST uri:/foo/bar?token=xxx&uuid=1234 status:200 size:12 apptime:0.057
  9. time:2015-09-06T05:58:41+09:00 method:POST uri:/foo/bar?token=yyy status:200 size:34 apptime:0.100
  10. time:2015-09-06T06:00:42+09:00 method:GET uri:/foo/bar?token=zzz status:200 size:56 apptime:0.123
  11. time:2015-09-06T06:00:43+09:00 method:GET uri:/foo/bar status:400 size:15 apptime:-
  12. time:2015-09-06T06:00:43+09:00 method:GET uri:/diary/entry/1234 status:200 size:15 apptime:0.135
  13. time:2015-09-06T06:00:43+09:00 method:GET uri:/diary/entry/5678 status:200 size:30 apptime:0.432
  14. time:2015-09-06T06:00:43+09:00 method:GET uri:/foo/bar/5xx status:504 size:15 apptime:60.000
  15. $ cat example/logs/ltsv_access.log | alp ltsv
  16. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  17. | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 | P95 | P99 | STDDEV | MIN(BODY) | MAX(BODY) | SUM(BODY) | AVG(BODY) |
  18. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  19. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /req | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  20. | 1 | 0 | 1 | 0 | 0 | 0 | POST | /hoge/piyo | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.000 | 34.000 | 34.000 | 34.000 | 34.000 |
  21. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/1234 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  22. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/5678 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.000 | 30.000 | 30.000 | 30.000 | 30.000 |
  23. | 1 | 0 | 0 | 0 | 0 | 1 | GET | /foo/bar/5xx | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  24. | 2 | 0 | 2 | 0 | 0 | 0 | GET | /foo/bar | 0.123 | 0.123 | 0.246 | 0.123 | 0.123 | 0.123 | 0.123 | 0.000 | 56.000 | 56.000 | 112.000 | 56.000 |
  25. | 5 | 0 | 5 | 0 | 0 | 0 | POST | /foo/bar | 0.057 | 0.234 | 0.548 | 0.110 | 0.234 | 0.234 | 0.234 | 0.065 | 12.000 | 34.000 | 126.000 | 25.200 |
  26. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+

Log format

Apache

  1. LogFormat "time:%t\tforwardedfor:%{X-Forwarded-For}i\thost:%h\treq:%r\tstatus:%>s\tmethod:%m\turi:%U%q\tsize:%B\treferer:%{Referer}i\tua:%{User-Agent}i\treqtime_microsec:%D\tapptime:%D\tcache:%{X-Cache}o\truntime:%{X-Runtime}o\tvhost:%{Host}i" ltsv

Nginx

  1. log_format ltsv "time:$time_local"
  2. "\thost:$remote_addr"
  3. "\tforwardedfor:$http_x_forwarded_for"
  4. "\treq:$request"
  5. "\tstatus:$status"
  6. "\tmethod:$request_method"
  7. "\turi:$request_uri"
  8. "\tsize:$body_bytes_sent"
  9. "\treferer:$http_referer"
  10. "\tua:$http_user_agent"
  11. "\treqtime:$request_time"
  12. "\tcache:$upstream_http_x_cache"
  13. "\truntime:$upstream_http_x_runtime"
  14. "\tapptime:$upstream_response_time"
  15. "\tvhost:$host";

H2O

  1. access-log:
  2. format: "time:%t\thost:%h\tua:\"%{User-agent}i\"\tstatus:%s\treq:%r\turi:%U\tapptime:%{duration}x\tsize:%b\tmethod:%m"

json

  • Parse a log with one JSON per line
  • By default, the following keys are parsed:
    • time
      • datetime
    • method
      • HTTP Method
    • uri
      • URI
    • status
      • HTTP Status Code
    • response_time
      • Response time from the upstream server
    • request_time
      • Request Processing Time (Response time after receiving a request)
  • The --xxx-key option can you change the name to any key
  1. $ cat example/logs/json_access.log
  2. {"time":"2015-09-06T05:58:05+09:00","method":"POST","uri":"/foo/bar?token=xxx&uuid=1234","status":200,"body_bytes":12,"response_time":0.057}
  3. {"time":"2015-09-06T05:58:41+09:00","method":"POST","uri":"/foo/bar?token=yyy","status":200,"body_bytes":34,"response_time":0.100}
  4. {"time":"2015-09-06T06:00:42+09:00","method":"GET","uri":"/foo/bar?token=zzz","status":200,"body_bytes":56,"response_time":0.123}
  5. {"time":"2015-09-06T06:00:43+09:00","method":"GET","uri":"/foo/bar","status":400,"body_bytes":15,"response_time":"-"}
  6. {"time":"2015-09-06T05:58:44+09:00","method":"POST","uri":"/foo/bar?token=yyy","status":200,"body_bytes":34,"response_time":0.234}
  7. {"time":"2015-09-06T05:58:44+09:00","method":"POST","uri":"/hoge/piyo?id=yyy","status":200,"body_bytes":34,"response_time":0.234}
  8. {"time":"2015-09-06T05:58:05+09:00","method":"POST","uri":"/foo/bar?token=xxx&uuid=1234","status":200,"body_bytes":12,"response_time":0.057}
  9. {"time":"2015-09-06T05:58:41+09:00","method":"POST","uri":"/foo/bar?token=yyy","status":200,"body_bytes":34,"response_time":0.100}
  10. {"time":"2015-09-06T06:00:42+09:00","method":"GET","uri":"/foo/bar?token=zzz","status":200,"body_bytes":56,"response_time":0.123}
  11. {"time":"2015-09-06T06:00:43+09:00","method":"GET","uri":"/foo/bar","status":400,"body_bytes":15,"response_time":"-"}
  12. {"time":"2015-09-06T06:00:43+09:00","method":"GET","uri":"/diary/entry/1234","status":200,"body_bytes":15,"response_time":0.135}
  13. {"time":"2015-09-06T06:00:43+09:00","method":"GET","uri":"/diary/entry/5678","status":200,"body_bytes":30,"response_time":0.432}
  14. {"time":"2015-09-06T06:00:43+09:00","method":"GET","uri":"/foo/bar/5xx","status":504,"body_bytes":15,"response_time":60.000}
  15. $ cat example/logs/json_access.log | alp json
  16. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  17. | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 | P95 | P99 | STDDEV | MIN(BODY) | MAX(BODY) | SUM(BODY) | AVG(BODY) |
  18. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  19. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /req | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  20. | 1 | 0 | 1 | 0 | 0 | 0 | POST | /hoge/piyo | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.000 | 34.000 | 34.000 | 34.000 | 34.000 |
  21. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/1234 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  22. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/5678 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.000 | 30.000 | 30.000 | 30.000 | 30.000 |
  23. | 1 | 0 | 0 | 0 | 0 | 1 | GET | /foo/bar/5xx | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  24. | 2 | 0 | 2 | 0 | 0 | 0 | GET | /foo/bar | 0.123 | 0.123 | 0.246 | 0.123 | 0.123 | 0.123 | 0.123 | 0.000 | 56.000 | 56.000 | 112.000 | 56.000 |
  25. | 5 | 0 | 5 | 0 | 0 | 0 | POST | /foo/bar | 0.057 | 0.234 | 0.548 | 0.110 | 0.234 | 0.234 | 0.234 | 0.065 | 12.000 | 34.000 | 126.000 | 25.200 |
  26. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+

Log format

Apache

  1. LogFormat "{\"time\":\"%t\",\"forwardedfor\":\"%{X-Forwarded-For}i\",\"host\":\"%h\",\"req\":\"%r\",\"status\":%>s,\"method\":\"%m\",\"uri\":\"%U%q\",\"body_bytes\":%B,\"referer\":\"%{Referer}i\",\"ua\":\"%{User-Agent}i\",\"reqtime_microsec\":%D,\"response_time\":%D,\"cache\":\"%{X-Cache}o\",\"runtime\":\"%{X-Runtime}o\",\"vhost\":\"%{Host}i\"}" json

Nginx

  1. log_format json escape=json '{"time":"$time_local",'
  2. '"host":"$remote_addr",'
  3. '"forwardedfor":"$http_x_forwarded_for",'
  4. '"req":"$request",'
  5. '"status":"$status",'
  6. '"method":"$request_method",'
  7. '"uri":"$request_uri",'
  8. '"body_bytes":$body_bytes_sent,'
  9. '"referer":"$http_referer",'
  10. '"ua":"$http_user_agent",'
  11. '"request_time":$request_time,'
  12. '"cache":"$upstream_http_x_cache",'
  13. '"runtime":"$upstream_http_x_runtime",'
  14. '"response_time":"$upstream_response_time",'
  15. '"vhost":"$host"}';

H2O

  1. access-log:
  2. escape: json
  3. format: '{"time":"%t","host":"%h","ua":"%{User-agent}i","status":%s,"req":"%r","uri":"%U","response_time":%{duration}x,"body_bytes":%b,"method":"%m"}'

regexp

  • Parses the log to match the regular expression
  • By default, the following named capture groups are parsed:
    • time
      • datetime
    • method
      • HTTP Method
    • uri
      • URI
    • status
      • HTTP Status Code
    • response_time
      • Response time from the upstream server
    • request_time
      • Request Processing Time (Response time after receiving a request)
  • The --xxx-subexp option can you change the name to any named capture groups
  1. $ cat example/logs/combined_access.log
  2. 127.0.0.1 - - [06/Sep/2015:05:58:05 +0900] "POST /foo/bar?token=xxx&uuid=1234 HTTP/1.1" 200 12 "-" "curl/7.54.0" "-" 0.057
  3. 127.0.0.1 - - [06/Sep/2015:05:58:41 +0900] "POST /foo/bar?token=yyy HTTP/1.1" 200 34 "-" "curl/7.54.0" "-" 0.100
  4. 127.0.0.1 - - [06/Sep/2015:06:00:42 +0900] "GET /foo/bar?token=zzz HTTP/1.1" 200 56 "-" "curl/7.54.0" "-" 0.123
  5. 127.0.0.1 - - [06/Sep/2015:06:00:43 +0900] "GET /foo/bar HTTP/1.1" 400 15 "-" "curl/7.54.0" "-" -
  6. 127.0.0.1 - - [06/Sep/2015:05:58:44 +0900] "POST /foo/bar?token=yyy HTTP/1.1" 200 34 "-" "curl/7.54.0" "-" 0.234
  7. 127.0.0.1 - - [06/Sep/2015:05:58:44 +0900] "POST /hoge/piyo?id=yyy HTTP/1.1" 200 34 "-" "curl/7.54.0" "-" 0.234
  8. 127.0.0.1 - - [06/Sep/2015:05:58:05 +0900] "POST foo/bar?token=xxx&uuid=1234 HTTP/1.1" 200 12 "-" "curl/7.54.0" "-" 0.057
  9. 127.0.0.1 - - [06/Sep/2015:05:58:41 +0900] "POST /foo/bar?token=yyy HTTP/1.1" 200 34 "-" "curl/7.54.0" "-" 0.100
  10. 127.0.0.1 - - [06/Sep/2015:06:00:42 +0900] "GET /foo/bar?token=zzz HTTP/1.1" 200 56 "-" "curl/7.54.0" "-" 0.123
  11. 127.0.0.1 - - [06/Sep/2015:06:00:43 +0900] "GET /foo/bar HTTP/1.1" 400 15 "-" "curl/7.54.0" "-" -
  12. 127.0.0.1 - - [06/Sep/2015:06:00:43 +0900] "GET /diary/entry/1234 HTTP/1.1" 200 15 "-" "curl/7.54.0" "-" 0.135
  13. 127.0.0.1 - - [06/Sep/2015:06:00:43 +0900] "GET /diary/entry/5678 HTTP/1.1" 200 30 "-" "curl/7.54.0" "-" 0.432
  14. 127.0.0.1 - - [06/Sep/2015:06:00:43 +0900] "GET /foo/bar/5xx HTTP/1.1" 504 15 "-" "curl/7.54.0" "-" 60.000
  15. $ cat example/logs/combined_access.log | alp regexp
  16. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  17. | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 | P95 | P99 | STDDEV | MIN(BODY) | MAX(BODY) | SUM(BODY) | AVG(BODY) |
  18. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  19. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /req | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  20. | 1 | 0 | 1 | 0 | 0 | 0 | POST | /hoge/piyo | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.000 | 34.000 | 34.000 | 34.000 | 34.000 |
  21. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/1234 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  22. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/5678 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.000 | 30.000 | 30.000 | 30.000 | 30.000 |
  23. | 1 | 0 | 0 | 0 | 0 | 1 | GET | /foo/bar/5xx | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  24. | 2 | 0 | 2 | 0 | 0 | 0 | GET | /foo/bar | 0.123 | 0.123 | 0.246 | 0.123 | 0.123 | 0.123 | 0.123 | 0.000 | 56.000 | 56.000 | 112.000 | 56.000 |
  25. | 5 | 0 | 5 | 0 | 0 | 0 | POST | /foo/bar | 0.057 | 0.234 | 0.548 | 0.110 | 0.234 | 0.234 | 0.234 | 0.065 | 12.000 | 34.000 | 126.000 | 25.200 |
  26. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+

Log format

Apache

  1. LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D" combined_plus

Nginx

  1. log_format combined_plus '$remote_addr - $remote_user [$time_local] '
  2. '"$request" $status $body_bytes_sent '
  3. '"$http_referer" "$http_user_agent" $upstream_response_time $request_time';

H2O

  1. access-log:
  2. format: "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\" %{duration}x"

pcap

  • Parses the pcap file to extract HTTP request/response packets to analyze the stats
    • Note that the actual response time may time duration from the actual response time because the difference in the timestamp of packet capturing is regarded as the real response time
    • The IP address and TCP port number of the server are required to distinguish between HTTP requests/responses to the server
  • Able to specify the IP address of the HTTP server with the --pcap-server-ip option
    • This option can be specified more than once
    • By default, it automatically obtains the IP address from the network interfaces of its own host and uses it
    • However, 127.0.0.1 and ::1 will be the defaults in environments where permissions to retrieve network interface information are restricted.
  • Able to specify the TCP port of the HTTP server with the --pcap-server-port option
    • The default server port number is 80.
  • Cannot be used with --pos. (not yet supported)
  1. $ sudo tcpdump -i lo port 5000 -s0 -w http.cap -Z $USER
  2. tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
  3. 10000 packets captured
  4. 20000 packets received by filter
  5. 0 packets dropped by kernel
  6. $ alp pcap --file=http.cap --pcap-server-port=5000
  7. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  8. | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 | P95 | P99 | STDDEV | MIN(BODY) | MAX(BODY) | SUM(BODY) | AVG(BODY) |
  9. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+
  10. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /req | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.321 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  11. | 1 | 0 | 1 | 0 | 0 | 0 | POST | /hoge/piyo | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.234 | 0.000 | 34.000 | 34.000 | 34.000 | 34.000 |
  12. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/1234 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  13. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/5678 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.000 | 30.000 | 30.000 | 30.000 | 30.000 |
  14. | 1 | 0 | 0 | 0 | 0 | 1 | GET | /foo/bar/5xx | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 60.000 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  15. | 2 | 0 | 2 | 0 | 0 | 0 | GET | /foo/bar | 0.123 | 0.123 | 0.246 | 0.123 | 0.123 | 0.123 | 0.123 | 0.000 | 56.000 | 56.000 | 112.000 | 56.000 |
  16. | 5 | 0 | 5 | 0 | 0 | 0 | POST | /foo/bar | 0.057 | 0.234 | 0.548 | 0.110 | 0.234 | 0.234 | 0.234 | 0.065 | 12.000 | 34.000 | 126.000 | 25.200 |
  17. +-------+-----+-----+-----+-----+-----+--------+-------------------+--------+--------+--------+--------+--------+--------+--------+--------+-----------+-----------+-----------+-----------+

diff

  • Show the difference between the two profile results
  • + means an increasing number of requests and body size, and response time is slower
  • - means a decreasing number of requests and body size, and response time is faster
  1. $ cat /path/to/access.log | alp json --dump dumpfile1.yaml
  2. $ cat /path/to/access.log | alp json --dump dumpfile2.yaml
  3. $ alp diff dumpfile1.yaml dumpfile2.yaml -o count,2xx,method,uri,min,max,sum,avg,p90 --show-footers
  4. +---------+---------+--------+-------------------+-----------------+-----------------+-----------------+-----------------+-----------------+
  5. | COUNT | 2XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 |
  6. +---------+---------+--------+-------------------+-----------------+-----------------+-----------------+-----------------+-----------------+
  7. | 1 | 1 | GET | /req | 0.221 (-0.100) | 0.221 (-0.100) | 0.221 (-0.100) | 0.221 (-0.100) | 0.221 (-0.100) |
  8. | 1 | 1 | GET | /new | 0.221 | 0.221 | 0.221 | 0.221 | 0.221 |
  9. | 1 | 1 | POST | /hoge/piyo | 0.134 (-0.100) | 0.134 (-0.100) | 0.134 (-0.100) | 0.134 (-0.100) | 0.134 (-0.100) |
  10. | 1 | 1 | GET | /diary/entry/1234 | 0.035 (-0.100) | 0.035 (-0.100) | 0.035 (-0.100) | 0.035 (-0.100) | 0.035 (-0.100) |
  11. | 1 | 0 | GET | /foo/bar/5xx | 59.000 (-1.000) | 59.000 (-1.000) | 59.000 (-1.000) | 59.000 (-1.000) | 59.000 (-1.000) |
  12. | 2 (+1) | 2 (+1) | GET | /diary/entry/5678 | 0.332 (-0.100) | 2.332 (+1.900) | 2.664 (+2.232) | 1.332 (+0.900) | 2.332 (+1.900) |
  13. | 2 | 2 | GET | /foo/bar | 0.023 (-0.100) | 0.023 (-0.100) | 0.046 (-0.200) | 0.023 (-0.100) | 0.023 (-0.100) |
  14. | 5 | 5 | POST | /foo/bar | 0.047 (-0.010) | 0.134 (-0.100) | 0.378 (-0.170) | 0.076 (-0.034) | 0.134 (-0.100) |
  15. +---------+---------+--------+-------------------+-----------------+-----------------+-----------------+-----------------+-----------------+
  16. | 14 (+2) | 13 (+2) |
  17. +---------+---------+--------+-------------------+-----------------+-----------------+-----------------+-----------------+-----------------+

Global options

See: Usage samples

  • -c, --config
    • The configuration file
    • YAML
  • --file=FILE
    • The access log file
  • -d, --dump=DUMP
    • File path for creating the profile results to a file
  • -l, --load=LOAD
    • File path to read the results of the profile created with the -d, --dump option
    • Can expect it to work fast if you change the --sort and --reverse options for the same profile results
  • --sort=count
    • Output the results in sorted order
    • Sort in ascending order
    • max, min, sum, avg
    • max-body, min-body, sum-body, avg-body
    • p90, p95, p99, stddev
    • uri
    • method
    • count
    • The default is count
    • p90, p95, and p99 are modified by the values specified in --percentiles
  • -r, --reverse
    • Sort in desecending order
  • -q, --query-string
    • URIs up to and including query strings are included in the profile
  • --qs-ignore-values
    • Ignore the value of the query string
    • It’s not enabled unless use with -q, --query-string
  • --decode-uri
    • Decode the URI
  • --format=table
    • Print the profile results in a table, Markdown, TSV, CSV and HTML format
    • The default is table format
  • --noheaders
    • Print no header when TSV and CSV format
  • --show-footers
    • Print the total number of each 1xx ~ 5xx in the footer of the table or Markdown format
  • --limit=5000
    • Maximum number of profile results to be printed
    • This setting is to avoid using too much memory
    • The default is 5000 lines
  • --location="Local"
    • The timezone of the time specified in the filter condition.
    • Default is localhost timezone
  • -o, --output="all"
    • Specify the profile results to be print, separated by commas
    • count,1xx, 2xx, 3xx, 4xx, 5xx, method, uri, min, max, sum, avg, p90, p95, p99, stddev, min_body, max_body, sum_body, avg_body
      • p90, p95, and p99 are modified by the values specified in --percentiles
    • The default is all
  • -m, --matching-groups=PATTERN,...
    • Treat URIs that match regular expressions as the same URI
    • Evaluate in the specified order. If matched, no further evaluation is performed.
    • See URI matching groups
  • -f, --filters=FILTERS
    • Filters the targets for profile
    • See Filter
  • --pos=POSITION_FILE
    • Stores the number of bytes to which the file has been read.
    • If the number of bytes is stored in the POSITION_FILE, the data after that number of bytes will be profiled
    • You can profile without truncating the file
      • Also, it is expected to work fast because it seeks and skips files
  • --nosave-pos
    • Data after the number of bytes specified by --pos is profiled, but the number of bytes reads is not stored
  • --percentiles
    • Specifies the percentile values to output, separated by commas
    • The default is 90,95,99

URI matching groups

Consider the following cases like /diary/entry/1234 and /diary/entry/5678.
If you simply profile URIs with different parameters on the same route, they will be profiled by parameter, but you may want to profile them by the route.

  1. $ cat example/logs/ltsv_access.log | alp ltsv --filters "Uri matches '^/diary/entry'"
  2. +-------+-----+-----+-----+-----+-----+--------+-------------------+-------+-------+-------+-------+-------+-------+-------+--------+-----------+-----------+-----------+-----------+
  3. | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 | P95 | P99 | STDDEV | MIN(BODY) | MAX(BODY) | SUM(BODY) | AVG(BODY) |
  4. +-------+-----+-----+-----+-----+-----+--------+-------------------+-------+-------+-------+-------+-------+-------+-------+--------+-----------+-----------+-----------+-----------+
  5. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/1234 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.135 | 0.000 | 15.000 | 15.000 | 15.000 | 15.000 |
  6. | 1 | 0 | 1 | 0 | 0 | 0 | GET | /diary/entry/5678 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.432 | 0.000 | 30.000 | 30.000 | 30.000 | 30.000 |
  7. +-------+-----+-----+-----+-----+-----+--------+-------------------+-------+-------+-------+-------+-------+-------+-------+--------+-----------+-----------+-----------+-----------+
  1. $ cat example/logs/ltsv_access.log | alp ltsv --filters "Uri matches '^/diary/entry'" -m "/diary/entry/.+"
  2. +-------+-----+-----+-----+-----+-----+--------+-----------------+-------+-------+-------+-------+-------+-------+-------+--------+-----------+-----------+-----------+-----------+
  3. | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | MIN | MAX | SUM | AVG | P90 | P95 | P99 | STDDEV | MIN(BODY) | MAX(BODY) | SUM(BODY) | AVG(BODY) |
  4. +-------+-----+-----+-----+-----+-----+--------+-----------------+-------+-------+-------+-------+-------+-------+-------+--------+-----------+-----------+-----------+-----------+
  5. | 2 | 0 | 2 | 0 | 0 | 0 | GET | /diary/entry/.+ | 0.135 | 0.432 | 0.567 | 0.283 | 0.432 | 0.432 | 0.432 | 0.148 | 15.000 | 30.000 | 45.000 | 22.500 |
  6. +-------+-----+-----+-----+-----+-----+--------+-----------------+-------+-------+-------+-------+-------+-------+-------+--------+-----------+-----------+-----------+-----------+

In such a case, there is an option -m, --matching-groups=PATTERN,....
You can also specify multiple items separated by commas.

Filter

It is a function to include or exclude targets according to the conditions.

Variables

Filter on the following variables:.

Operators

The following operators are available:.

  • +, -, *, /, %, **(pow)
  • ==, !=, <, >, <=, >=
  • not, !
  • and, &&
  • or, ||
  • matches
    • e.g.
      • Uri matches "PATTERN"
      • not(Uri matches "PATTERN")
  • contains
    • e.g.
      • Uri contains "STRING"
      • not(Uri contains "STRING")
  • startsWith
    • e.g.
      • Uri startsWith "PREFIX"
      • not(Uri startsWith "PREFIX")
  • endsWith
    • e.g.
      • Uri endsWith "SUFFIX"
      • not(Uri endsWith "SUFFIX")
  • in
    • e.g.
      • Method in ["GET", "POST"]
      • Method not in ["GET", "POST"]

See: https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md

Functions

  • TimeAgo(duration)
    • now - duration
    • ns, us or µs, ms, s, m, h
    • e.g.
      • Time >= TimeAgo("5m")
  • BetweenTime(val, start, end)
    • Like SQL’s BETWEEN, returns start <= val && val <= end
    • e.g.
      • BetweenTime(Time, "2019-08-06T00:00:00", "2019-08-06T00:05:00")

Usage samples

See: Usage samples

Donation

Donations are welcome as always!
:heart: Sponsor