{"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513652597", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513652597, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzY1MjU5Nw==", "user": {"value": 14834132, "label": "SteadBytes"}, "created_at": "2019-07-22T06:03:18Z", "updated_at": "2019-07-22T06:03:18Z", "author_association": "NONE", "body": "@simonw do you think it is still worth populating the `endpoint` key in the scope as originally intended by this issue, or should we hold off until a decision about possibly using an `X-Endpoint` header instead? :smile: ", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513446227", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513446227, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzQ0NjIyNw==", "user": {"value": 14834132, "label": "SteadBytes"}, "created_at": "2019-07-20T07:50:44Z", "updated_at": "2019-07-20T07:50:44Z", "author_association": "NONE", "body": "Oh yes well spotted thank you \ud83d\ude01 \r\n\r\nI agree that the strictness would be nice as it could help to avoid different middleware altering the scope in incompatible ways. However I do also agree that it's likely for not all implementations to follow \ud83e\udd14", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513442743", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513442743, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzQ0Mjc0Mw==", "user": {"value": 647359, "label": "tomchristie"}, "created_at": "2019-07-20T06:50:47Z", "updated_at": "2019-07-20T06:50:47Z", "author_association": "NONE", "body": "Right now the spec does say \u201ccopy the scope, rather than mutate it\u201d https://asgi.readthedocs.io/en/latest/specs/main.html#middleware \r\n\r\nI wouldn\u2019t be surprised if that there\u2019s room for discussion on evolving the exact language there.\r\n\r\nThere\u2019s obvs a nice element to the strictness there, tho practically I\u2019m not sure it\u2019s something that implementations will follow, and its not something that Starlette chooses to abide by.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513439736", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513439736, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzQzOTczNg==", "user": {"value": 14834132, "label": "SteadBytes"}, "created_at": "2019-07-20T06:05:01Z", "updated_at": "2019-07-20T06:05:01Z", "author_association": "NONE", "body": "The asgi spec doesn't explicitly specify (at least as far as I can tell) whether the scope is immutable/mutable https://asgi.readthedocs.io/en/latest/specs/lifespan.html#scope . @simonw using a header for this would be a nice approach. It would also potentially increase the portability of any middleware/plugins/clients across different applications/frameworks as it's not tied directly to an asgi implementation", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513317952", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513317952, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzMxNzk1Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-07-19T17:49:06Z", "updated_at": "2019-07-19T17:49:06Z", "author_association": "OWNER", "body": "It strikes me that if scope is indeed meant to stay immutable the alternative way of solving this would be to add an outbound custom request header with the endpoint - `X-Endpoint: datasette.views.table.TableView` for example - and teach the Sentry plugin to optionally read that.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513307487", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513307487, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzMwNzQ4Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-07-19T17:17:43Z", "updated_at": "2019-07-19T17:17:43Z", "author_association": "OWNER", "body": "Huh, interesting. I'd got it into my head that scope should not be mutated under any circumstances - if that's not true and it's mutable there's all kinds of useful things we could do with it.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513279397", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513279397, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzI3OTM5Nw==", "user": {"value": 647359, "label": "tomchristie"}, "created_at": "2019-07-19T15:47:57Z", "updated_at": "2019-07-19T15:48:09Z", "author_association": "NONE", "body": "The middleware implementation there works okay with a router nested inside if the scope is *mutated*. (Ie. \"endpoint\" doesn't need to exist at the point that the middleware starts running, but if it *has* been made available by the time an exception is thrown, then it can be used.)\r\n\r\nStarlette's usage of \"endpoint\" there is unilateral, rather than something I've discussed against the ASGI spec - certainly it's important for any monitoring ASGI middleware to be able to have some kind of visibility onto some limited subset of routing information, and `\"endpoint\"` in the scope referencing some routed-to callable seemed general enough to be useful.\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513273003", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513273003, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzI3MzAwMw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-07-19T15:28:42Z", "updated_at": "2019-07-19T15:28:42Z", "author_association": "OWNER", "body": "Asked about this on Twitter: https://twitter.com/simonw/status/1152238730259791877", "reactions": "{\"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 1, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-513272392", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 513272392, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMzI3MjM5Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-07-19T15:27:03Z", "updated_at": "2019-07-19T15:27:03Z", "author_association": "OWNER", "body": "Yeah that's a good call: the Datasette plugin mechanism where middleware is wrapped around the outside doesn't appear to be compatible with the Sentry mechanism of expecting that `scope` has been populated before it gets to their error handler.\r\n\r\n@tomchristie is this something you've thought about?", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-512930353", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 512930353, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMjkzMDM1Mw==", "user": {"value": 14834132, "label": "SteadBytes"}, "created_at": "2019-07-18T18:20:53Z", "updated_at": "2019-07-18T18:34:03Z", "author_association": "NONE", "body": "Ok great, getting the `__qualname__` to be `TableView` and adding `endpoint` to the `scope` in `AsgiRouter` is simple enough (already done). However, (unless I'm missing a plugin hook or something) the suggestion of utilising it within a `datasette-sentry` plugin may not work. The only hook that would have access to the `scope` is the `asgi_wrapper` hook. But as this _wraps_ the existing `asgi` app, the `endpoint` won't yet have been added to the `scope` received by the hook https://github.com/SteadBytes/datasette/blob/107d47567dedd472eebec7f35bc34f5b58285ba8/datasette/app.py#L672 . However, I'm not sure where else the `endpoint` could be added to the asgi scope :thinking: \r\n\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-512664216", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 512664216, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMjY2NDIxNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2019-07-18T04:53:18Z", "updated_at": "2019-07-18T04:53:18Z", "author_association": "OWNER", "body": "Yes, `TableView` is desirable here I think. Maybe `datasette.views.table.TableView` if we can get that somehow. Thanks for taking a look!", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/537#issuecomment-512126748", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/537", "id": 512126748, "node_id": "MDEyOklzc3VlQ29tbWVudDUxMjEyNjc0OA==", "user": {"value": 14834132, "label": "SteadBytes"}, "created_at": "2019-07-17T06:48:35Z", "updated_at": "2019-07-17T06:48:35Z", "author_association": "NONE", "body": "It looks as if the `datasette.utils.AsgiRouter.__call__` is the place to add this https://github.com/simonw/datasette/blob/90d4f497f9b3f6a5882937c91fddb496ac3e7368/datasette/utils/asgi.py#L101 .\r\n\r\nThe sentry_asgi middleware uses the `__qualname__` or `__name__` attributes of the `endpoint` https://github.com/encode/sentry-asgi/blob/c6a42d44d31f85885b79e4ee898683ecf8104971/sentry_asgi/middleware.py#L84\r\n\r\nLooking at the Starlette implementation `endpoint` is a `Callable` https://github.com/encode/starlette/commit/34d0097feb6f057bd050d5057df5a2f96b97384e#diff-34fba745b50527bfb4245d02afd59246R100 which as far as I can tell is analogous to the `view` function which is matched here https://github.com/simonw/datasette/blob/90d4f497f9b3f6a5882937c91fddb496ac3e7368/datasette/utils/asgi.py#L96 .\r\n\r\nA slight issue is that `__qualname__` is matched *first* in the sentry_asgi middleware, and `__name__` is used if that doesn't exist. I think (please correct me if I am wrong) that for datasette, the `__name__` is what should be used. For example, when using the development fixtures and hitting `http://127.0.0.1:8001/fixtures/compound_three_primary_keys` the `view` function that is matched gives:\r\n\r\n```python\r\n>>> view.__qualname__\r\n'AsgiView.as_asgi..view'\r\n>>> view.__name__\r\n'TableView'\r\n```\r\n\r\nWould `TableView` be the desired value here? Or am I looking in entirely the wrong place? :smile: \r\n\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 463544206, "label": "Populate \"endpoint\" key in ASGI scope"}, "performed_via_github_app": null}