{"id":15674793,"url":"https://github.com/zimbatm/lines","last_synced_at":"2026-02-15T08:33:09.331Z","repository":{"id":65209026,"uuid":"8877073","full_name":"zimbatm/lines","owner":"zimbatm","description":"structured logs for humans","archived":false,"fork":false,"pushed_at":"2020-11-12T08:25:40.000Z","size":10,"stargazers_count":14,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-09T21:09:46.686Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zimbatm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-03-19T11:32:31.000Z","updated_at":"2020-11-12T08:25:42.000Z","dependencies_parsed_at":"2023-01-16T15:00:11.048Z","dependency_job_id":null,"html_url":"https://github.com/zimbatm/lines","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zimbatm/lines","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbatm%2Flines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbatm%2Flines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbatm%2Flines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbatm%2Flines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zimbatm","download_url":"https://codeload.github.com/zimbatm/lines/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimbatm%2Flines/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29473718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T06:58:05.414Z","status":"ssl_error","status_checked_at":"2026-02-15T06:58:05.085Z","response_time":118,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":[],"created_at":"2024-10-03T15:50:50.671Z","updated_at":"2026-02-15T08:33:09.316Z","avatar_url":"https://github.com/zimbatm.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"Lines - structured logs for humans\n==================================\n\nA log format that's readable by humans and easily parseable by computers.\n\nSTATUS: DRAFT\n=============\n\nThings are starting to stabilize.\n\nThe unit separator is probably going to change. The number format could get\nsome human-readable love. There's still a lot of specification needed\nregarding Unicode and non-visible characters.\n\nThe rest should be pretty much stable.\n\nRationale\n---------\n\nAll these log lines. Most of them are assembled using methods like\nsprintf() which makes them readable to humans but what if you want to\nanalyse them ? You need custom parsers for every one of these.\n\nNow most of your infrastructure are pieces of code that won't change\nmuch. For example apache access logs. You write the parser once and you're\ngood to go. But what about your application. Wouldn't it be nice if you could\njust dump some application data, have is still readable, and that it\nwould still be parseable by computers ? That's where Lines enters the\ngame.\n\nLines is an opinionated logging that tries to solve this problem. It\nacknowledges that log lines are read by human but should also be analyzed by\nsoftware.\n\nWhy not JSON ?\n--------------\n\n[JSON](http://json.org/) is great for the web but not really readable when\ncompacted on a single line. We also would like to keep more data types if\npossible like date/time.\n\nExample\n-------\n\n```\nat=2013-03-17T23:41:08Z app=myapp pid=3452 env=dev name='Token Load' sql='SELECT \"tokens\".* FROM \"tokens\" WHERE \"tokens\".\"deleted_at\" IS NULL ORDER BY \"tokens\".\"id\" ASC LIMIT 1' elapsed=0.941:s\nat=2013-03-17T23:41:08Z app=myapp pid=3452 env=dev msg='Token not found'\nat=2013-03-17T23:41:08Z app=myapp pid=3452 env=dev remote_addr=[127.0.0.1] method=GET path=/ status=400 length=28 elapsed=0.167:s\n```\n\nSyntax\n------\n\nEvery log entry is a single UTF-8 encoded line.\n\nThe following syntax is described using the\n[EBNF](https://en.wikipedia.org/wiki/EBNF) syntax:\n\n```ebnf\nline = pair , { space, pair } ;\n\nspace = \" \"\n\npair = ( string | literal ), '=', value ;\n\nvalue = object\n      | list\n      | string\n      | literal ;\n\nobject = '{', ( \"...\" | \"\" | pair, { space, pair } ), '}' ;\n\nlist = '[', value, { space, value }, ']' ;\n\nstring = \"'\", ? UTF-8 text where \\' \\r \\n \\\\ are escaped ?, \"'\"\n       | '\"', ? UTF-8 text where \\\" \\r \\n \\\\ are escaped ?, '\"' ;\n\nliteral = ? UTF-8 visible characters ? - [ \"=\" | \"}\" | \"]\" | space ] ;\n```\n\nA literal in a value position can then be further down-parsed into more\nspecific values. These are officially supported types:\n\n```ebnf\nboolean = \"#t\" | \"#f\" ;\nnil = \"nil\" ;\nnumber = [ \"-\" ], digit, { digit }, [ \".\", { digit } ] ;\ntime =\n  digit, digit, digit, digit, \"-\", digit, digit, \"-\", digit, digit, \"T\",\n  digit, digit, \":\", digit, digit, \":\", digit, digit, \"Z\" ;\nunit = number, \":\", literal ;\n```\n\nGenerator notes\n---------------\n\nStrings can be represented as literals if they don't contain any of the\nforbidden characters. To avoid confusion during parsing it is also recommended\nto avoid the literal form if the string contains \":\" or other characters\n\nIf you want the generator can also generate other forms of literals that are\nlanguage specific. A parser who doesn't recognise the literal will parse it as\na string.\n\nTo avoid circular generation keep track of the depth of the tree. When passing\na certain level, replace the content of arrays with \"[...]\" and of objects\nwith \"{...}\"\n\nParser notes\n------------\n\n`unit` allows you to keep the unit with your numbers. For example `3:ms`. If\nthe language has no native support for the unit it can create a (number,\nstring) tuple or array instead.\n\nThe \"{...}\" format encountered when the object is too deep should be parsed as\n`{\"...\": \"\"}` in JSON notation.\n\nSemantic\n--------\n\nThe semantic is quite free-format but it could be helpful to agree on a couple\nof conventions:\n\n* The \"at\" key contains the time at which the line was created\n* The \"app\" key contain the process name\n* The \"pid\" key contain the process pid\n* The \"elapsed\" key might contain some time measurement (with unit!)\n\nLibrary specifics\n-----------------\n\nThe logger should never raise an exception if it doesn't understand the type\nthat was given to him. One possible fallback it to create a string\nrepresentation of the type instead but it's up to the library implementer.\nJust don't raise exceptions.\n\nWhen the parent log format already includes some of the log data it's allowed\nto strip some values of the line. Eg: syslog already includes timestamp, app\nname and PID.\n\nLog levels are overrated.\n\nImplementations\n---------------\n\nSubmit a pull-request to add yours.\n\n* [lines-ruby](https://github.com/zimbatm/lines-ruby)\n\nRelated projects\n----------------\n\n* Lots of inspiration from the scrolls project: https://github.com/asenchi/scrolls\n* @kr for the another gist on the format:\nhttps://gist.github.com/kr/0e8d5ee4b954ce604bb2\n* The lograge project: https://github.com/roidrage/lograge\n* logfmt: http://godoc.org/github.com/kr/logfmt\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzimbatm%2Flines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzimbatm%2Flines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzimbatm%2Flines/lists"}