Include asyncio task information in /-/threads debug page

pages
Simon Willison 2019-12-04 22:46:39 -08:00
rodzic 2039e78e58
commit d6b6c9171f
5 zmienionych plików z 41 dodań i 4 usunięć

Wyświetl plik

@ -2,6 +2,7 @@ import asyncio
import collections
import hashlib
import os
import re
import sys
import threading
import traceback
@ -477,12 +478,19 @@ class Datasette:
def threads(self):
threads = list(threading.enumerate())
return {
d = {
"num_threads": len(threads),
"threads": [
{"name": t.name, "ident": t.ident, "daemon": t.daemon} for t in threads
],
}
# Only available in Python 3.7+
if hasattr(asyncio, "all_tasks"):
tasks = asyncio.all_tasks()
d.update(
{"num_tasks": len(tasks), "tasks": [_cleaner_task_str(t) for t in tasks]}
)
return d
def table_metadata(self, database, table):
"Fetch table-specific metadata."
@ -684,3 +692,14 @@ class DatasetteRouter(AsgiRouter):
await asgi_send_html(
send, await template.render_async(info), status=status, headers=headers
)
_cleaner_task_str_re = re.compile(r"\S*site-packages/")
def _cleaner_task_str(task):
s = str(task)
# This has something like the following in it:
# running at /Users/simonw/Dropbox/Development/datasette/venv-3.7.5/lib/python3.7/site-packages/uvicorn/main.py:361>
# Clean up everything up to and including site-packages
return _cleaner_task_str_re.sub("", s)

Wyświetl plik

@ -7,6 +7,6 @@
{% block content %}
<h1>{{ filename }}</h1>
<pre>{{ data|tojson(indent=4) }}</pre>
<pre>{{ data_json }}</pre>
{% endblock %}

Wyświetl plik

@ -27,5 +27,8 @@ class JsonDataView(BaseView):
return await self.render(
["show_json.html"],
request=request,
context={"filename": self.filename, "data": data},
context={
"filename": self.filename,
"data_json": json.dumps(data, indent=4),
},
)

Wyświetl plik

@ -113,7 +113,7 @@ Shows currently attached databases. `Databases example <https://latest.datasette
/-/threads
----------
Shows details of threads. `Threads example <https://latest.datasette.io/-/threads>`_::
Shows details of threads and ``asyncio`` tasks. `Threads example <https://latest.datasette.io/-/threads>`_::
{
"num_threads": 2,
@ -128,5 +128,11 @@ Shows details of threads. `Threads example <https://latest.datasette.io/-/thread
"ident": 123145319682048,
"name": "Thread-1"
},
],
"num_tasks": 3,
"tasks": [
"<Task pending coro=<RequestResponseCycle.run_asgi() running at uvicorn/protocols/http/httptools_impl.py:385> cb=[set.discard()]>",
"<Task pending coro=<Server.serve() running at uvicorn/main.py:361> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10365c3d0>()]> cb=[run_until_complete.<locals>.<lambda>()]>",
"<Task pending coro=<LifespanOn.main() running at uvicorn/lifespan/on.py:48> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x10364f050>()]>>"
]
}

Wyświetl plik

@ -18,6 +18,7 @@ from .fixtures import ( # noqa
)
import json
import pytest
import sys
import urllib
@ -1229,6 +1230,14 @@ def test_metadata_json(app_client):
assert METADATA == response.json
def test_threads_json(app_client):
response = app_client.get("/-/threads.json")
expected_keys = {"threads", "num_threads"}
if sys.version_info >= (3, 7, 0):
expected_keys.update({"tasks", "num_tasks"})
assert expected_keys == set(response.json.keys())
def test_plugins_json(app_client):
response = app_client.get("/-/plugins.json")
assert [