{"id":16663834,"url":"https://github.com/jonathanj/eliottree","last_synced_at":"2025-04-04T14:05:26.605Z","repository":{"id":28164359,"uuid":"31665258","full_name":"jonathanj/eliottree","owner":"jonathanj","description":"Render Eliot logs as an ASCII tree","archived":false,"fork":false,"pushed_at":"2024-11-19T14:57:06.000Z","size":932,"stargazers_count":67,"open_issues_count":7,"forks_count":11,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-28T13:06:52.393Z","etag":null,"topics":["eliot","log-viewer","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonathanj.png","metadata":{"files":{"readme":"README.rst","changelog":"NEWS.rst","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}},"created_at":"2015-03-04T15:52:37.000Z","updated_at":"2025-01-27T00:01:18.000Z","dependencies_parsed_at":"2024-11-16T20:03:08.828Z","dependency_job_id":"22d97fbe-042d-4c9a-82e4-8aa339facb7d","html_url":"https://github.com/jonathanj/eliottree","commit_stats":{"total_commits":166,"total_committers":6,"mean_commits":"27.666666666666668","dds":0.07831325301204817,"last_synced_commit":"0fa79d8a7dd526a642761c44bcf4acdae9afa289"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathanj%2Feliottree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathanj%2Feliottree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathanj%2Feliottree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathanj%2Feliottree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonathanj","download_url":"https://codeload.github.com/jonathanj/eliottree/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247190226,"owners_count":20898699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["eliot","log-viewer","python"],"created_at":"2024-10-12T10:42:13.557Z","updated_at":"2025-04-04T14:05:26.581Z","avatar_url":"https://github.com/jonathanj.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"=========\neliottree\n=========\n\n|build|_ |coverage|_\n\nRender `Eliot \u003chttps://github.com/scatterhq/eliot\u003e`_ logs as an ASCII tree.\n\nThis output:\n\n.. image:: https://github.com/jonathanj/eliottree/raw/master/doc/example_eliot_log.png\n\n(or as text)\n\n.. code-block:: bash\n\n   $ eliot-tree eliot.log\n   f3a32bb3-ea6b-457c-aa99-08a3d0491ab4\n   └── app:soap:client:request/1 ⇒ started 2015-03-03 04:28:56 ⧖ 1.238s\n       ├── dump: /home/user/dump_files/20150303/1425356936.28_Client_req.xml\n       ├── soapAction: a_soap_action\n       ├── uri: http://example.org/soap\n       ├── app:soap:client:success/2/1 ⇒ started 2015-03-03 04:28:57 ⧖ 0.000s\n       │   └── app:soap:client:success/2/2 ⇒ succeeded 2015-03-03 04:28:57\n       │       └── dump: /home/user/dump_files/20150303/1425356937.52_Client_res.xml\n       └── app:soap:client:request/3 ⇒ succeeded 2015-03-03 04:28:57\n           └── status: 200\n\n    89a56df5-d808-4a7c-8526-e603aae2e2f2\n    └── app:soap:service:request/1 ⇒ started 2015-03-03 04:31:08 ⧖ 3.482s\n        ├── dump: /home/user/dump_files/20150303/1425357068.03_Service_req.xml\n        ├── soapAction: method\n        ├── uri: /endpoints/soap/method\n        ├── app:soap:service:success/2/1 ⇒ started 2015-03-03 04:31:11 ⧖ 0.001s\n        │   └── app:soap:service:success/2/2 ⇒ succeeded 2015-03-03 04:31:11\n        │       └── dump: /home/user/dump_files/20150303/1425357071.51_Service_res.xml\n        └── app:soap:service:request/3 ⇒ succeeded 2015-03-03 04:31:11\n            └── status: 200\n\nwas generated from:\n\n.. code-block:: javascript\n\n   {\"dump\": \"/home/user/dump_files/20150303/1425356936.28_Client_req.xml\", \"timestamp\": 1425356936.278875, \"uri\": \"http://example.org/soap\", \"action_status\": \"started\", \"task_uuid\": \"f3a32bb3-ea6b-457c-aa99-08a3d0491ab4\", \"action_type\": \"app:soap:client:request\", \"soapAction\": \"a_soap_action\", \"task_level\": [1]}\n   {\"timestamp\": 1425356937.516579, \"task_uuid\": \"f3a32bb3-ea6b-457c-aa99-08a3d0491ab4\", \"action_type\": \"app:soap:client:success\", \"action_status\": \"started\", \"task_level\": [2, 1]}\n   {\"task_uuid\": \"f3a32bb3-ea6b-457c-aa99-08a3d0491ab4\", \"action_type\": \"app:soap:client:success\", \"dump\": \"/home/user/dump_files/20150303/1425356937.52_Client_res.xml\", \"timestamp\": 1425356937.517077, \"action_status\": \"succeeded\", \"task_level\": [2, 2]}\n   {\"status\": 200, \"task_uuid\": \"f3a32bb3-ea6b-457c-aa99-08a3d0491ab4\", \"task_level\": [3], \"action_type\": \"app:soap:client:request\", \"timestamp\": 1425356937.517161, \"action_status\": \"succeeded\"}\n   {\"dump\": \"/home/user/dump_files/20150303/1425357068.03_Service_req.xml\", \"timestamp\": 1425357068.032091, \"uri\": \"/endpoints/soap/method\", \"action_status\": \"started\", \"task_uuid\": \"89a56df5-d808-4a7c-8526-e603aae2e2f2\", \"action_type\": \"app:soap:service:request\", \"soapAction\": \"method\", \"task_level\": [1]}\n   {\"timestamp\": 1425357071.51233, \"task_uuid\": \"89a56df5-d808-4a7c-8526-e603aae2e2f2\", \"action_type\": \"app:soap:service:success\", \"action_status\": \"started\", \"task_level\": [2, 1]}\n   {\"task_uuid\": \"89a56df5-d808-4a7c-8526-e603aae2e2f2\", \"action_type\": \"app:soap:service:success\", \"dump\": \"/home/user/dump_files/20150303/1425357071.51_Service_res.xml\", \"timestamp\": 1425357071.513453, \"action_status\": \"succeeded\", \"task_level\": [2, 2]}\n   {\"status\": 200, \"task_uuid\": \"89a56df5-d808-4a7c-8526-e603aae2e2f2\", \"task_level\": [3], \"action_type\": \"app:soap:service:request\", \"timestamp\": 1425357071.513992, \"action_status\": \"succeeded\"}\n\nCommand-line options\n--------------------\n\nConsult the output of ``eliot-tree --help`` to see a complete list of command-line\noptions.\n\nStreaming\n---------\n\nIt's possible to pipe data into eliot-tree, from a tailed log for example, and\nhave it rendered incrementally. There is a caveat though: Trees are only\nrendered once an end message—a success or failure status—for the tree's root\naction appears in the data.\n\nSelecting / filtering tasks\n---------------------------\n\nBy task UUID\n~~~~~~~~~~~~\n\nEntire task trees can be selected by UUID with the ``--task-uuid`` (``-u``)\ncommand-line option.\n\nBy start / end date\n~~~~~~~~~~~~~~~~~~~\n\nIndividual tasks can be selected based on their timestamp, use ``--start`` to\nselect tasks after an ISO8601 date-time, and ``--end`` to select tasks before an\nISO8601 date-time.\n\nBy custom query\n~~~~~~~~~~~~~~~\n\nCustom task selection can be done with the ``--select`` command-line option, the\nsyntax of which is `JMESPath`_, and is applied to the original Eliot JSON\nstructures. Any data that appears within an Eliot task structure can be queried.\nOnly the matching tasks (and all of their children) will be displayed, the\nparents of the task structure (by ``task_uuid``) will be elided.\n\nAn important thing to note is that the query should be used as a *predicate* (it\nshould describe a boolean condition), not to narrow a JSON data structure, as\nmany of the examples on the JMESPath site illustrate. The reason for this is\nthat Eliot tasks are not stored as one large nested JSON structure, they are\ninstead many small structures that are linked together by metadata\n(``task_uuid``), which is not a structure than JMESPath is ideally equipped to\nquery.\n\nThe ``--select`` argument can be supplied multiple times to mimic logical AND,\nthat is all ``--select`` predicates must pass in order for a task or node to be\nselected.\n\n.. _JMESPath: http://jmespath.org/\n\nExamples\n^^^^^^^^\n\nSelect all tasks that contain a ``uri`` key, regardless of its value:\n\n.. code-block:: bash\n\n   --select 'uri'\n\nSelect all Eliot action tasks of type ``http_client:request``:\n\n.. code-block:: bash\n\n   --select 'action_type == `\"http_client:request\"`'\n\nBackquotes are used to represent raw JSON values in JMESPath, ```500``` is the\nnumber 500, ```\"500\"``` is the string \"500\".\n\nSelect all tasks that have an ``http_status`` of 401 or 500:\n\n.. code-block:: bash\n\n   --select 'contains(`[401, 500]`, status)'\n\nSelect all tasks that have an ``http_status`` of 401 that were also made to a\n``uri`` containing the text ``/criticalEndpoint``:\n\n.. code-block:: bash\n\n   --select 'http_status == `401`' \\\n   --select 'uri \u0026\u0026 contains(uri, `\"/criticalEndpoint\"`)'\n\nHere ``--select`` is passed twice to mimic a logical AND condition, it is also\npossible to use the JMESPath ``\u0026\u0026`` operator. There is also a test for the\nexistence of the ``uri`` key to guard against calling the ``contains()``\nfunction with a null subject.\n\nSee the `JMESPath specification`_ for more information.\n\n.. _JMESPath specification: http://jmespath.org/specification.html\n\n\nProgrammatic usage\n------------------\n\n.. code-block:: python\n\n   import json, sys\n   from eliottree import tasks_from_iterable, render_tasks\n   # Or `codecs.getwriter('utf-8')(sys.stdout).write` on Python 2.\n   render_tasks(sys.stdout.write, tasks, colorize=True)\n\nSee :code:`help(render_tasks)` and :code:`help(tasks_from_iterable)` from a\nPython REPL for more information.\n\nConfiguration\n-------------\n\nCommand-line options may have custom defaults specified by way of a config file.\nThe config file can be passed with the ``--config`` argument, or will be read from\n``~/.config/eliot-tree/config.json``. See `config.example.json`_ for an\nexample.\n\nUse the ``--show-default-config`` command-line option to display the default\nconfiguration, suitable for redirecting to a file. Use the\n``--show-current-config`` command-line option to display the current effective\nconfiguration.\n\n.. _\\_cli.py: https://github.com/jonathanj/eliottree/blob/master/src/eliottree/_cli.py\n.. _config.example.json: https://github.com/jonathanj/eliottree/blob/master/config.example.json\n\nTheme overrides\n~~~~~~~~~~~~~~~\n\nTheme colors can be overridden via the ``theme_overrides`` key in the config file.\nThe value of this key is itself a JSON object, each key is the name of a theme\ncolor and each value is a JSON list. This list should contain three values:\n\n1. Foreground color, terminal color name or code; or ``null`` for the default color.\n2. Background color, terminal color name or code; or ``null`` for the default color.\n3. An optional array of color attribute names or codes; or ``null`` for the\n   default attribute.\n\nFor example, to override the ``root`` theme color to be bold magenta, and the\n``prop`` theme color to be red:\n\n.. code-block:: json\n\n   {\n     \"theme_overrides\": {\n       \"root\": [\"magenta\", null, [\"bold\"]],\n       \"prop_key\": [\"red\"]\n     }\n   }\n\nSee `_theme.py`_ for theme color names and the `colored`_ Python package for\navailable color and attribute constants.\n\n.. _\\_theme.py: https://github.com/jonathanj/eliottree/blob/master/src/eliottree/_theme.py\n.. _colored: https://pypi.org/project/colored/\n\nContribute\n----------\n\nSee \u003chttps://github.com/jonathanj/eliottree\u003e for details.\n\n\n.. |build| image:: https://travis-ci.org/jonathanj/eliottree.svg?branch=master\n.. _build: https://travis-ci.org/jonathanj/eliottree\n\n.. |coverage| image:: https://coveralls.io/repos/jonathanj/eliottree/badge.svg\n.. _coverage: https://coveralls.io/r/jonathanj/eliottree\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathanj%2Feliottree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonathanj%2Feliottree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathanj%2Feliottree/lists"}