{"id":22298107,"url":"https://github.com/stefafafan/seki","last_synced_at":"2026-02-20T20:35:30.069Z","repository":{"id":264278642,"uuid":"890275358","full_name":"stefafafan/seki","owner":"stefafafan","description":"A CLI tool to help parse and aggregate access log data for further analysis.","archived":false,"fork":false,"pushed_at":"2025-04-21T14:03:13.000Z","size":82,"stargazers_count":1,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-25T00:57:34.246Z","etag":null,"topics":["analyzer","json","log","nginx","profiler","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stefafafan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-11-18T09:47:34.000Z","updated_at":"2025-01-26T12:27:32.000Z","dependencies_parsed_at":"2024-12-31T02:24:23.671Z","dependency_job_id":"3208303e-7dba-42ee-a74f-b11d52a95c58","html_url":"https://github.com/stefafafan/seki","commit_stats":null,"previous_names":["stefafafan/seki"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/stefafafan/seki","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefafafan%2Fseki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefafafan%2Fseki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefafafan%2Fseki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefafafan%2Fseki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stefafafan","download_url":"https://codeload.github.com/stefafafan/seki/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stefafafan%2Fseki/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29663475,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T19:49:36.704Z","status":"ssl_error","status_checked_at":"2026-02-20T19:44:05.372Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analyzer","json","log","nginx","profiler","rust"],"created_at":"2024-12-03T17:59:44.318Z","updated_at":"2026-02-20T20:35:30.039Z","avatar_url":"https://github.com/stefafafan.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# seki\n\nseki is a CLI tool to help parse and aggregate access log data for further analysis. The tool is intended to be used with nginx access logs (JSON format), piped out to tools like `jq`.\n\nThe name seki comes from the Japanese terms 積 (from 蓄積 which means accumulate) and 析 (from 分析 which means analysis). These kanji are both read \"seki\".\n\nThis tool is heavily influenced by [tkuchiki/alp](https://github.com/tkuchiki/alp) and [matsuu/kataribe](https://github.com/matsuu/kataribe).\n\n## Why seki?\n\nOther tools do everything for you from aggregation to pretty-print display. For most users these tools are sufficient.\n\nseki focuses on parsing and outputting metrics as JSON, for easy integration and processing.\n\n## Installation\n\n### Download assets from the releases page\n\nThe https://github.com/stefafafan/seki/releases page has assets including binaries along with an installer shellscript.\n\nEither download the corresponding binary or use the installer shellscript.\n\n```sh\n# Using the binary\nsudo install \u003cdownloaded asset file\u003e /usr/local/bin/seki\n```\n\n### Using cargo-binstall\n\nIf you have [cargo-binstall](https://github.com/cargo-bins/cargo-binstall), you can use this as well.\n\n```sh\ncargo binstall seki\n```\n\n### Build from source\n\nWith [Rust](https://rustup.rs/) installed:\n\n```sh\ncargo install seki\n```\n\n## Usage\n\nseki reads access log in JSON format from stdin, and outputs to stdout as JSON.\n\n```sh\ncat access.log | seki\n```\n\nseki parses the following keys, make sure the access log has these:\n- `method`\n- `uri`\n- `status`\n- `response_time`\n\nFor nginx, set the log_format to something like this:\n\n```nginx.conf\nlog_format json escape=json '{'\n                            '\"time\":\"$time_iso8601\",'\n                            '\"host\":\"$remote_addr\",'\n                            '\"method\":\"$request_method\",'\n                            '\"uri\":\"$request_uri\",'\n                            '\"status\":\"$status\",'\n                            '\"body_bytes\":\"$body_bytes_sent\",'\n                            '\"referer\":\"$http_referer\",'\n                            '\"ua\":\"$http_user_agent\",'\n                            '\"request_time\":\"$request_time\",'\n                            '\"response_time\":\"$upstream_response_time\"'\n                            '}';\n```\n\n### Grouping endpoints with the config file\n\nSometimes you will want to group endpoints together (for example, `/post/123` and `/post/456`).\n\nCreate a `config.toml` file to define these groupings.\n\n```sh\ncp config.toml.example config.toml\n# edit config.toml with your favorite editor.\n```\n\nYou can either use the default path to the config file, or specify with the command line option.\n\n```sh\n# uses config.toml if it exists\n$ cat access.log | seki\n# setting the path to the config file.\n$ cat access.log | seki --config ~/foo/config.toml\n```\n\n## Examples\n\nLet's say you have an access log file like this:\n\n```sh\n$ cat access.log\n{\"time\":\"19/Nov/2024:09:18:34 +0900\",\"status\":\"200\",\"method\":\"GET\",\"uri\":\"/foobar\",\"response_time\":\"0.476\"}\n{\"time\":\"19/Nov/2024:09:18:58 +0900\",\"status\":\"400\",\"method\":\"GET\",\"uri\":\"/\",\"response_time\":\"0.239\"}\n{\"time\":\"19/Nov/2024:09:19:22 +0900\",\"status\":\"302\",\"method\":\"GET\",\"uri\":\"/hello\",\"response_time\":\"0.113\"}\n{\"time\":\"19/Nov/2024:09:20:12 +0900\",\"status\":\"200\",\"method\":\"GET\",\"uri\":\"/foobar\",\"response_time\":\"0.732\"}\n```\n\nseki aggregates the logs into one simple JSON.\n\n```sh\n$ cat access.log | seki\n[\n  {\n    \"method\": \"GET\",\n    \"uri\": \"/hello\",\n    \"count\": 1,\n    \"status_code\": {\n      \"status_1xx\": 0,\n      \"status_2xx\": 0,\n      \"status_3xx\": 1,\n      \"status_4xx\": 0,\n      \"status_5xx\": 0\n    },\n    \"response_time\": {\n      \"min\": 0.0,\n      \"max\": 0.113,\n      \"avg\": 0.113,\n      \"sum\": 0.113,\n      \"p50\": 0.113,\n      \"p75\": 0.113,\n      \"p90\": 0.113,\n      \"p95\": 0.113,\n      \"p99\": 0.113\n    }\n  },\n  {\n    \"method\": \"GET\",\n    \"uri\": \"/foobar\",\n    \"count\": 2,\n    \"status_code\": {\n      \"status_1xx\": 0,\n      \"status_2xx\": 2,\n      \"status_3xx\": 0,\n      \"status_4xx\": 0,\n      \"status_5xx\": 0\n    },\n    \"response_time\": {\n      \"min\": 0.0,\n      \"max\": 0.732,\n      \"avg\": 0.604,\n      \"sum\": 1.208,\n      \"p50\": 0.732,\n      \"p75\": 0.732,\n      \"p90\": 0.732,\n      \"p95\": 0.732,\n      \"p99\": 0.732\n    }\n  },\n  {\n    \"method\": \"GET\",\n    \"uri\": \"/\",\n    \"count\": 1,\n    \"status_code\": {\n      \"status_1xx\": 0,\n      \"status_2xx\": 0,\n      \"status_3xx\": 0,\n      \"status_4xx\": 1,\n      \"status_5xx\": 0\n    },\n    \"response_time\": {\n      \"min\": 0.0,\n      \"max\": 0.239,\n      \"avg\": 0.239,\n      \"sum\": 0.239,\n      \"p50\": 0.239,\n      \"p75\": 0.239,\n      \"p90\": 0.239,\n      \"p95\": 0.239,\n      \"p99\": 0.239\n    }\n  }\n]\n```\n\n### Using seki with jq\n\nThe previous example can be used in conjunction with [jq](https://github.com/jqlang/jq). The following sample demonstrates sorting the `uri`s by `response_time.sum`.\n\n```sh\n$ cat access.log | seki | \\\n    jq 'sort_by(-.response_time.sum) | .[] | {uri: .uri, response_time_sum: .response_time.sum}'\n{\n  \"uri\": \"/foobar\",\n  \"response_time_sum\": 1.208\n}\n{\n  \"uri\": \"/\",\n  \"response_time_sum\": 0.239\n}\n{\n  \"uri\": \"/hello\",\n  \"response_time_sum\": 0.113\n}\n```\n\nIf you prefer a tabular format, maybe you can use jq in conjunction with the column command to do this:\n\n```sh\n$ cat access.log | seki | \\\n    jq -r \"sort_by(-.response_time.sum) | \\\n        .[] | \\\n        [.method + \\\" \\\" + .uri, \\\n        .status_code.status_2xx, \\\n        .status_code.status_3xx, \\\n        .status_code.status_4xx, \\\n        .status_code.status_5xx, \\\n        .response_time.sum] | \\\n        @tsv\" | \\\n    column -t\nGET  /foobar  2  0  0  0  1.208\nGET  /        0  0  1  0  0.239\nGET  /hello   0  1  0  0  0.113\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefafafan%2Fseki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstefafafan%2Fseki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstefafafan%2Fseki/lists"}