We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[UI][FEATURE] Invalid worker or task keys should return 404 instead of 500 HTML status code
E.g. http://host:8787/info/task/foobared.html returns `500: Internal Server Error`.

Should instead return a friendlier 404 page.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `distributed/dashboard/scheduler_html.py`
Content:
```
1 from datetime import datetime
2 
3 from dask.utils import format_bytes
4 import toolz
5 from tornado import escape
6 
7 from ..utils import log_errors, format_time
8 from .proxy import GlobalProxyHandler
9 from .utils import RequestHandler, redirect
10 
11 ns = {
12     func.__name__: func for func in [format_bytes, format_time, datetime.fromtimestamp]
13 }
14 
15 
16 class Workers(RequestHandler):
17     def get(self):
18         with log_errors():
19             self.render(
20                 "workers.html",
21                 title="Workers",
22                 scheduler=self.server,
23                 **toolz.merge(self.server.__dict__, ns, self.extra)
24             )
25 
26 
27 class Worker(RequestHandler):
28     def get(self, worker):
29         worker = escape.url_unescape(worker)
30         with log_errors():
31             self.render(
32                 "worker.html",
33                 title="Worker: " + worker,
34                 scheduler=self.server,
35                 Worker=worker,
36                 **toolz.merge(self.server.__dict__, ns, self.extra)
37             )
38 
39 
40 class Task(RequestHandler):
41     def get(self, task):
42         task = escape.url_unescape(task)
43         with log_errors():
44             self.render(
45                 "task.html",
46                 title="Task: " + task,
47                 Task=task,
48                 scheduler=self.server,
49                 **toolz.merge(self.server.__dict__, ns, self.extra)
50             )
51 
52 
53 class Logs(RequestHandler):
54     def get(self):
55         with log_errors():
56             logs = self.server.get_logs()
57             self.render("logs.html", title="Logs", logs=logs, **self.extra)
58 
59 
60 class WorkerLogs(RequestHandler):
61     async def get(self, worker):
62         with log_errors():
63             worker = escape.url_unescape(worker)
64             logs = await self.server.get_worker_logs(workers=[worker])
65             logs = logs[worker]
66             self.render("logs.html", title="Logs: " + worker, logs=logs, **self.extra)
67 
68 
69 class WorkerCallStacks(RequestHandler):
70     async def get(self, worker):
71         with log_errors():
72             worker = escape.url_unescape(worker)
73             keys = self.server.processing[worker]
74             call_stack = await self.server.get_call_stack(keys=keys)
75             self.render(
76                 "call-stack.html",
77                 title="Call Stacks: " + worker,
78                 call_stack=call_stack,
79                 **self.extra
80             )
81 
82 
83 class TaskCallStack(RequestHandler):
84     async def get(self, key):
85         with log_errors():
86             key = escape.url_unescape(key)
87             call_stack = await self.server.get_call_stack(keys=[key])
88             if not call_stack:
89                 self.write(
90                     "<p>Task not actively running. "
91                     "It may be finished or not yet started</p>"
92                 )
93             else:
94                 self.render(
95                     "call-stack.html",
96                     title="Call Stack: " + key,
97                     call_stack=call_stack,
98                     **self.extra
99                 )
100 
101 
102 class CountsJSON(RequestHandler):
103     def get(self):
104         scheduler = self.server
105         erred = 0
106         nbytes = 0
107         nthreads = 0
108         memory = 0
109         processing = 0
110         released = 0
111         waiting = 0
112         waiting_data = 0
113 
114         for ts in scheduler.tasks.values():
115             if ts.exception_blame is not None:
116                 erred += 1
117             elif ts.state == "released":
118                 released += 1
119             if ts.waiting_on:
120                 waiting += 1
121             if ts.waiters:
122                 waiting_data += 1
123         for ws in scheduler.workers.values():
124             nthreads += ws.nthreads
125             memory += len(ws.has_what)
126             nbytes += ws.nbytes
127             processing += len(ws.processing)
128 
129         response = {
130             "bytes": nbytes,
131             "clients": len(scheduler.clients),
132             "cores": nthreads,
133             "erred": erred,
134             "hosts": len(scheduler.host_info),
135             "idle": len(scheduler.idle),
136             "memory": memory,
137             "processing": processing,
138             "released": released,
139             "saturated": len(scheduler.saturated),
140             "tasks": len(scheduler.tasks),
141             "unrunnable": len(scheduler.unrunnable),
142             "waiting": waiting,
143             "waiting_data": waiting_data,
144             "workers": len(scheduler.workers),
145         }
146         self.write(response)
147 
148 
149 class IdentityJSON(RequestHandler):
150     def get(self):
151         self.write(self.server.identity())
152 
153 
154 class IndexJSON(RequestHandler):
155     def get(self):
156         with log_errors():
157             r = [url for url, _ in routes if url.endswith(".json")]
158             self.render(
159                 "json-index.html", routes=r, title="Index of JSON routes", **self.extra
160             )
161 
162 
163 class IndividualPlots(RequestHandler):
164     def get(self):
165         bokeh_server = self.server.services["dashboard"]
166         result = {
167             uri.strip("/").replace("-", " ").title(): uri
168             for uri in bokeh_server.apps
169             if uri.lstrip("/").startswith("individual-") and not uri.endswith(".json")
170         }
171         self.write(result)
172 
173 
174 class _PrometheusCollector(object):
175     def __init__(self, server):
176         self.server = server
177 
178     def collect(self):
179         from prometheus_client.core import GaugeMetricFamily
180 
181         yield GaugeMetricFamily(
182             "dask_scheduler_workers",
183             "Number of workers connected.",
184             value=len(self.server.workers),
185         )
186         yield GaugeMetricFamily(
187             "dask_scheduler_clients",
188             "Number of clients connected.",
189             value=len(self.server.clients),
190         )
191         yield GaugeMetricFamily(
192             "dask_scheduler_received_tasks",
193             "Number of tasks received at scheduler",
194             value=len(self.server.tasks),
195         )
196         yield GaugeMetricFamily(
197             "dask_scheduler_unrunnable_tasks",
198             "Number of unrunnable tasks at scheduler",
199             value=len(self.server.unrunnable),
200         )
201 
202 
203 class PrometheusHandler(RequestHandler):
204     _initialized = False
205 
206     def __init__(self, *args, **kwargs):
207         import prometheus_client
208 
209         super(PrometheusHandler, self).__init__(*args, **kwargs)
210 
211         if PrometheusHandler._initialized:
212             return
213 
214         prometheus_client.REGISTRY.register(_PrometheusCollector(self.server))
215 
216         PrometheusHandler._initialized = True
217 
218     def get(self):
219         import prometheus_client
220 
221         self.write(prometheus_client.generate_latest())
222         self.set_header("Content-Type", "text/plain; version=0.0.4")
223 
224 
225 class HealthHandler(RequestHandler):
226     def get(self):
227         self.write("ok")
228         self.set_header("Content-Type", "text/plain")
229 
230 
231 routes = [
232     (r"info", redirect("info/main/workers.html")),
233     (r"info/main/workers.html", Workers),
234     (r"info/worker/(.*).html", Worker),
235     (r"info/task/(.*).html", Task),
236     (r"info/main/logs.html", Logs),
237     (r"info/call-stacks/(.*).html", WorkerCallStacks),
238     (r"info/call-stack/(.*).html", TaskCallStack),
239     (r"info/logs/(.*).html", WorkerLogs),
240     (r"json/counts.json", CountsJSON),
241     (r"json/identity.json", IdentityJSON),
242     (r"json/index.html", IndexJSON),
243     (r"individual-plots.json", IndividualPlots),
244     (r"metrics", PrometheusHandler),
245     (r"health", HealthHandler),
246     (r"proxy/(\d+)/(.*?)/(.*)", GlobalProxyHandler),
247 ]
248 
249 
250 def get_handlers(server):
251     return [(url, cls, {"server": server}) for url, cls in routes]
252
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/distributed/dashboard/scheduler_html.py b/distributed/dashboard/scheduler_html.py
--- a/distributed/dashboard/scheduler_html.py
+++ b/distributed/dashboard/scheduler_html.py
@@ -27,6 +27,9 @@
 class Worker(RequestHandler):
     def get(self, worker):
         worker = escape.url_unescape(worker)
+        if worker not in self.server.workers:
+            self.send_error(404)
+            return
         with log_errors():
             self.render(
                 "worker.html",
@@ -40,6 +43,9 @@
 class Task(RequestHandler):
     def get(self, task):
         task = escape.url_unescape(task)
+        if task not in self.server.tasks:
+            self.send_error(404)
+            return
         with log_errors():
             self.render(
                 "task.html",

{"golden_diff": "diff --git a/distributed/dashboard/scheduler_html.py b/distributed/dashboard/scheduler_html.py\n--- a/distributed/dashboard/scheduler_html.py\n+++ b/distributed/dashboard/scheduler_html.py\n@@ -27,6 +27,9 @@\n class Worker(RequestHandler):\n     def get(self, worker):\n         worker = escape.url_unescape(worker)\n+        if worker not in self.server.workers:\n+            self.send_error(404)\n+            return\n         with log_errors():\n             self.render(\n                 \"worker.html\",\n@@ -40,6 +43,9 @@\n class Task(RequestHandler):\n     def get(self, task):\n         task = escape.url_unescape(task)\n+        if task not in self.server.tasks:\n+            self.send_error(404)\n+            return\n         with log_errors():\n             self.render(\n                 \"task.html\",\n", "issue": "[UI][FEATURE] Invalid worker or task keys should return 404 instead of 500 HTML status code\nE.g. http://host:8787/info/task/foobared.html returns `500: Internal Server Error`.\r\n\r\nShould instead return a friendlier 404 page.\n", "before_files": [{"content": "from datetime import datetime\n\nfrom dask.utils import format_bytes\nimport toolz\nfrom tornado import escape\n\nfrom ..utils import log_errors, format_time\nfrom .proxy import GlobalProxyHandler\nfrom .utils import RequestHandler, redirect\n\nns = {\n    func.__name__: func for func in [format_bytes, format_time, datetime.fromtimestamp]\n}\n\n\nclass Workers(RequestHandler):\n    def get(self):\n        with log_errors():\n            self.render(\n                \"workers.html\",\n                title=\"Workers\",\n                scheduler=self.server,\n                **toolz.merge(self.server.__dict__, ns, self.extra)\n            )\n\n\nclass Worker(RequestHandler):\n    def get(self, worker):\n        worker = escape.url_unescape(worker)\n        with log_errors():\n            self.render(\n                \"worker.html\",\n                title=\"Worker: \" + worker,\n                scheduler=self.server,\n                Worker=worker,\n                **toolz.merge(self.server.__dict__, ns, self.extra)\n            )\n\n\nclass Task(RequestHandler):\n    def get(self, task):\n        task = escape.url_unescape(task)\n        with log_errors():\n            self.render(\n                \"task.html\",\n                title=\"Task: \" + task,\n                Task=task,\n                scheduler=self.server,\n                **toolz.merge(self.server.__dict__, ns, self.extra)\n            )\n\n\nclass Logs(RequestHandler):\n    def get(self):\n        with log_errors():\n            logs = self.server.get_logs()\n            self.render(\"logs.html\", title=\"Logs\", logs=logs, **self.extra)\n\n\nclass WorkerLogs(RequestHandler):\n    async def get(self, worker):\n        with log_errors():\n            worker = escape.url_unescape(worker)\n            logs = await self.server.get_worker_logs(workers=[worker])\n            logs = logs[worker]\n            self.render(\"logs.html\", title=\"Logs: \" + worker, logs=logs, **self.extra)\n\n\nclass WorkerCallStacks(RequestHandler):\n    async def get(self, worker):\n        with log_errors():\n            worker = escape.url_unescape(worker)\n            keys = self.server.processing[worker]\n            call_stack = await self.server.get_call_stack(keys=keys)\n            self.render(\n                \"call-stack.html\",\n                title=\"Call Stacks: \" + worker,\n                call_stack=call_stack,\n                **self.extra\n            )\n\n\nclass TaskCallStack(RequestHandler):\n    async def get(self, key):\n        with log_errors():\n            key = escape.url_unescape(key)\n            call_stack = await self.server.get_call_stack(keys=[key])\n            if not call_stack:\n                self.write(\n                    \"<p>Task not actively running. \"\n                    \"It may be finished or not yet started</p>\"\n                )\n            else:\n                self.render(\n                    \"call-stack.html\",\n                    title=\"Call Stack: \" + key,\n                    call_stack=call_stack,\n                    **self.extra\n                )\n\n\nclass CountsJSON(RequestHandler):\n    def get(self):\n        scheduler = self.server\n        erred = 0\n        nbytes = 0\n        nthreads = 0\n        memory = 0\n        processing = 0\n        released = 0\n        waiting = 0\n        waiting_data = 0\n\n        for ts in scheduler.tasks.values():\n            if ts.exception_blame is not None:\n                erred += 1\n            elif ts.state == \"released\":\n                released += 1\n            if ts.waiting_on:\n                waiting += 1\n            if ts.waiters:\n                waiting_data += 1\n        for ws in scheduler.workers.values():\n            nthreads += ws.nthreads\n            memory += len(ws.has_what)\n            nbytes += ws.nbytes\n            processing += len(ws.processing)\n\n        response = {\n            \"bytes\": nbytes,\n            \"clients\": len(scheduler.clients),\n            \"cores\": nthreads,\n            \"erred\": erred,\n            \"hosts\": len(scheduler.host_info),\n            \"idle\": len(scheduler.idle),\n            \"memory\": memory,\n            \"processing\": processing,\n            \"released\": released,\n            \"saturated\": len(scheduler.saturated),\n            \"tasks\": len(scheduler.tasks),\n            \"unrunnable\": len(scheduler.unrunnable),\n            \"waiting\": waiting,\n            \"waiting_data\": waiting_data,\n            \"workers\": len(scheduler.workers),\n        }\n        self.write(response)\n\n\nclass IdentityJSON(RequestHandler):\n    def get(self):\n        self.write(self.server.identity())\n\n\nclass IndexJSON(RequestHandler):\n    def get(self):\n        with log_errors():\n            r = [url for url, _ in routes if url.endswith(\".json\")]\n            self.render(\n                \"json-index.html\", routes=r, title=\"Index of JSON routes\", **self.extra\n            )\n\n\nclass IndividualPlots(RequestHandler):\n    def get(self):\n        bokeh_server = self.server.services[\"dashboard\"]\n        result = {\n            uri.strip(\"/\").replace(\"-\", \" \").title(): uri\n            for uri in bokeh_server.apps\n            if uri.lstrip(\"/\").startswith(\"individual-\") and not uri.endswith(\".json\")\n        }\n        self.write(result)\n\n\nclass _PrometheusCollector(object):\n    def __init__(self, server):\n        self.server = server\n\n    def collect(self):\n        from prometheus_client.core import GaugeMetricFamily\n\n        yield GaugeMetricFamily(\n            \"dask_scheduler_workers\",\n            \"Number of workers connected.\",\n            value=len(self.server.workers),\n        )\n        yield GaugeMetricFamily(\n            \"dask_scheduler_clients\",\n            \"Number of clients connected.\",\n            value=len(self.server.clients),\n        )\n        yield GaugeMetricFamily(\n            \"dask_scheduler_received_tasks\",\n            \"Number of tasks received at scheduler\",\n            value=len(self.server.tasks),\n        )\n        yield GaugeMetricFamily(\n            \"dask_scheduler_unrunnable_tasks\",\n            \"Number of unrunnable tasks at scheduler\",\n            value=len(self.server.unrunnable),\n        )\n\n\nclass PrometheusHandler(RequestHandler):\n    _initialized = False\n\n    def __init__(self, *args, **kwargs):\n        import prometheus_client\n\n        super(PrometheusHandler, self).__init__(*args, **kwargs)\n\n        if PrometheusHandler._initialized:\n            return\n\n        prometheus_client.REGISTRY.register(_PrometheusCollector(self.server))\n\n        PrometheusHandler._initialized = True\n\n    def get(self):\n        import prometheus_client\n\n        self.write(prometheus_client.generate_latest())\n        self.set_header(\"Content-Type\", \"text/plain; version=0.0.4\")\n\n\nclass HealthHandler(RequestHandler):\n    def get(self):\n        self.write(\"ok\")\n        self.set_header(\"Content-Type\", \"text/plain\")\n\n\nroutes = [\n    (r\"info\", redirect(\"info/main/workers.html\")),\n    (r\"info/main/workers.html\", Workers),\n    (r\"info/worker/(.*).html\", Worker),\n    (r\"info/task/(.*).html\", Task),\n    (r\"info/main/logs.html\", Logs),\n    (r\"info/call-stacks/(.*).html\", WorkerCallStacks),\n    (r\"info/call-stack/(.*).html\", TaskCallStack),\n    (r\"info/logs/(.*).html\", WorkerLogs),\n    (r\"json/counts.json\", CountsJSON),\n    (r\"json/identity.json\", IdentityJSON),\n    (r\"json/index.html\", IndexJSON),\n    (r\"individual-plots.json\", IndividualPlots),\n    (r\"metrics\", PrometheusHandler),\n    (r\"health\", HealthHandler),\n    (r\"proxy/(\\d+)/(.*?)/(.*)\", GlobalProxyHandler),\n]\n\n\ndef get_handlers(server):\n    return [(url, cls, {\"server\": server}) for url, cls in routes]\n", "path": "distributed/dashboard/scheduler_html.py"}], "after_files": [{"content": "from datetime import datetime\n\nfrom dask.utils import format_bytes\nimport toolz\nfrom tornado import escape\n\nfrom ..utils import log_errors, format_time\nfrom .proxy import GlobalProxyHandler\nfrom .utils import RequestHandler, redirect\n\nns = {\n    func.__name__: func for func in [format_bytes, format_time, datetime.fromtimestamp]\n}\n\n\nclass Workers(RequestHandler):\n    def get(self):\n        with log_errors():\n            self.render(\n                \"workers.html\",\n                title=\"Workers\",\n                scheduler=self.server,\n                **toolz.merge(self.server.__dict__, ns, self.extra)\n            )\n\n\nclass Worker(RequestHandler):\n    def get(self, worker):\n        worker = escape.url_unescape(worker)\n        if worker not in self.server.workers:\n            self.send_error(404)\n            return\n        with log_errors():\n            self.render(\n                \"worker.html\",\n                title=\"Worker: \" + worker,\n                scheduler=self.server,\n                Worker=worker,\n                **toolz.merge(self.server.__dict__, ns, self.extra)\n            )\n\n\nclass Task(RequestHandler):\n    def get(self, task):\n        task = escape.url_unescape(task)\n        if task not in self.server.tasks:\n            self.send_error(404)\n            return\n        with log_errors():\n            self.render(\n                \"task.html\",\n                title=\"Task: \" + task,\n                Task=task,\n                scheduler=self.server,\n                **toolz.merge(self.server.__dict__, ns, self.extra)\n            )\n\n\nclass Logs(RequestHandler):\n    def get(self):\n        with log_errors():\n            logs = self.server.get_logs()\n            self.render(\"logs.html\", title=\"Logs\", logs=logs, **self.extra)\n\n\nclass WorkerLogs(RequestHandler):\n    async def get(self, worker):\n        with log_errors():\n            worker = escape.url_unescape(worker)\n            logs = await self.server.get_worker_logs(workers=[worker])\n            logs = logs[worker]\n            self.render(\"logs.html\", title=\"Logs: \" + worker, logs=logs, **self.extra)\n\n\nclass WorkerCallStacks(RequestHandler):\n    async def get(self, worker):\n        with log_errors():\n            worker = escape.url_unescape(worker)\n            keys = self.server.processing[worker]\n            call_stack = await self.server.get_call_stack(keys=keys)\n            self.render(\n                \"call-stack.html\",\n                title=\"Call Stacks: \" + worker,\n                call_stack=call_stack,\n                **self.extra\n            )\n\n\nclass TaskCallStack(RequestHandler):\n    async def get(self, key):\n        with log_errors():\n            key = escape.url_unescape(key)\n            call_stack = await self.server.get_call_stack(keys=[key])\n            if not call_stack:\n                self.write(\n                    \"<p>Task not actively running. \"\n                    \"It may be finished or not yet started</p>\"\n                )\n            else:\n                self.render(\n                    \"call-stack.html\",\n                    title=\"Call Stack: \" + key,\n                    call_stack=call_stack,\n                    **self.extra\n                )\n\n\nclass CountsJSON(RequestHandler):\n    def get(self):\n        scheduler = self.server\n        erred = 0\n        nbytes = 0\n        nthreads = 0\n        memory = 0\n        processing = 0\n        released = 0\n        waiting = 0\n        waiting_data = 0\n\n        for ts in scheduler.tasks.values():\n            if ts.exception_blame is not None:\n                erred += 1\n            elif ts.state == \"released\":\n                released += 1\n            if ts.waiting_on:\n                waiting += 1\n            if ts.waiters:\n                waiting_data += 1\n        for ws in scheduler.workers.values():\n            nthreads += ws.nthreads\n            memory += len(ws.has_what)\n            nbytes += ws.nbytes\n            processing += len(ws.processing)\n\n        response = {\n            \"bytes\": nbytes,\n            \"clients\": len(scheduler.clients),\n            \"cores\": nthreads,\n            \"erred\": erred,\n            \"hosts\": len(scheduler.host_info),\n            \"idle\": len(scheduler.idle),\n            \"memory\": memory,\n            \"processing\": processing,\n            \"released\": released,\n            \"saturated\": len(scheduler.saturated),\n            \"tasks\": len(scheduler.tasks),\n            \"unrunnable\": len(scheduler.unrunnable),\n            \"waiting\": waiting,\n            \"waiting_data\": waiting_data,\n            \"workers\": len(scheduler.workers),\n        }\n        self.write(response)\n\n\nclass IdentityJSON(RequestHandler):\n    def get(self):\n        self.write(self.server.identity())\n\n\nclass IndexJSON(RequestHandler):\n    def get(self):\n        with log_errors():\n            r = [url for url, _ in routes if url.endswith(\".json\")]\n            self.render(\n                \"json-index.html\", routes=r, title=\"Index of JSON routes\", **self.extra\n            )\n\n\nclass IndividualPlots(RequestHandler):\n    def get(self):\n        bokeh_server = self.server.services[\"dashboard\"]\n        result = {\n            uri.strip(\"/\").replace(\"-\", \" \").title(): uri\n            for uri in bokeh_server.apps\n            if uri.lstrip(\"/\").startswith(\"individual-\") and not uri.endswith(\".json\")\n        }\n        self.write(result)\n\n\nclass _PrometheusCollector(object):\n    def __init__(self, server):\n        self.server = server\n\n    def collect(self):\n        from prometheus_client.core import GaugeMetricFamily\n\n        yield GaugeMetricFamily(\n            \"dask_scheduler_workers\",\n            \"Number of workers connected.\",\n            value=len(self.server.workers),\n        )\n        yield GaugeMetricFamily(\n            \"dask_scheduler_clients\",\n            \"Number of clients connected.\",\n            value=len(self.server.clients),\n        )\n        yield GaugeMetricFamily(\n            \"dask_scheduler_received_tasks\",\n            \"Number of tasks received at scheduler\",\n            value=len(self.server.tasks),\n        )\n        yield GaugeMetricFamily(\n            \"dask_scheduler_unrunnable_tasks\",\n            \"Number of unrunnable tasks at scheduler\",\n            value=len(self.server.unrunnable),\n        )\n\n\nclass PrometheusHandler(RequestHandler):\n    _initialized = False\n\n    def __init__(self, *args, **kwargs):\n        import prometheus_client\n\n        super(PrometheusHandler, self).__init__(*args, **kwargs)\n\n        if PrometheusHandler._initialized:\n            return\n\n        prometheus_client.REGISTRY.register(_PrometheusCollector(self.server))\n\n        PrometheusHandler._initialized = True\n\n    def get(self):\n        import prometheus_client\n\n        self.write(prometheus_client.generate_latest())\n        self.set_header(\"Content-Type\", \"text/plain; version=0.0.4\")\n\n\nclass HealthHandler(RequestHandler):\n    def get(self):\n        self.write(\"ok\")\n        self.set_header(\"Content-Type\", \"text/plain\")\n\n\nroutes = [\n    (r\"info\", redirect(\"info/main/workers.html\")),\n    (r\"info/main/workers.html\", Workers),\n    (r\"info/worker/(.*).html\", Worker),\n    (r\"info/task/(.*).html\", Task),\n    (r\"info/main/logs.html\", Logs),\n    (r\"info/call-stacks/(.*).html\", WorkerCallStacks),\n    (r\"info/call-stack/(.*).html\", TaskCallStack),\n    (r\"info/logs/(.*).html\", WorkerLogs),\n    (r\"json/counts.json\", CountsJSON),\n    (r\"json/identity.json\", IdentityJSON),\n    (r\"json/index.html\", IndexJSON),\n    (r\"individual-plots.json\", IndividualPlots),\n    (r\"metrics\", PrometheusHandler),\n    (r\"health\", HealthHandler),\n    (r\"proxy/(\\d+)/(.*?)/(.*)\", GlobalProxyHandler),\n]\n\n\ndef get_handlers(server):\n    return [(url, cls, {\"server\": server}) for url, cls in routes]\n", "path": "distributed/dashboard/scheduler_html.py"}]}