kopia lustrzana https://github.com/simonw/datasette
				
				
				
			Include asyncio task information in /-/threads debug page
							rodzic
							
								
									2039e78e58
								
							
						
					
					
						commit
						d6b6c9171f
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,6 @@
 | 
			
		|||
{% block content %}
 | 
			
		||||
<h1>{{ filename }}</h1>
 | 
			
		||||
 | 
			
		||||
<pre>{{ data|tojson(indent=4) }}</pre>
 | 
			
		||||
<pre>{{ data_json }}</pre>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>()]>>"
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue