We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Report error requests on Pyramid
Currently if an error occurs in a Pyramid request, we don't report it. Error cases can be just as useful to see so we should try and do this. It looks like it's possible by rearranging the existing code.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/scout_apm/pyramid.py`
Content:
```
1 # coding=utf-8
2 from __future__ import absolute_import, division, print_function, unicode_literals
3 
4 import scout_apm.core
5 from scout_apm.core.config import ScoutConfig
6 from scout_apm.core.tracked_request import TrackedRequest
7 from scout_apm.core.web_requests import (
8     create_filtered_path,
9     ignore_path,
10     track_amazon_request_queue_time,
11     track_request_queue_time,
12 )
13 
14 
15 def includeme(config):
16     configs = {}
17     pyramid_config = config.get_settings()
18     for name in pyramid_config:
19         if name.startswith("SCOUT_"):
20             value = pyramid_config[name]
21             clean_name = name.replace("SCOUT_", "").lower()
22             configs[clean_name] = value
23     ScoutConfig.set(**configs)
24 
25     if scout_apm.core.install():
26         config.add_tween("scout_apm.pyramid.instruments")
27 
28 
29 def instruments(handler, registry):
30     def scout_tween(request):
31         tracked_request = TrackedRequest.instance()
32         span = tracked_request.start_span(operation="Controller/Pyramid")
33 
34         try:
35             path = request.path
36             # mixed() returns values as *either* single items or lists
37             url_params = [
38                 (k, v) for k, vs in request.GET.dict_of_lists().items() for v in vs
39             ]
40             tracked_request.tag("path", create_filtered_path(path, url_params))
41             if ignore_path(path):
42                 tracked_request.tag("ignore_transaction", True)
43 
44             try:
45                 # Determine a remote IP to associate with the request. The value is
46                 # spoofable by the requester so this is not suitable to use in any
47                 # security sensitive context.
48                 user_ip = (
49                     request.headers.get("x-forwarded-for", default="").split(",")[0]
50                     or request.headers.get("client-ip", default="").split(",")[0]
51                     or request.remote_addr
52                 )
53             except Exception:
54                 pass
55             else:
56                 tracked_request.tag("user_ip", user_ip)
57 
58             tracked_queue_time = False
59             try:
60                 queue_time = request.headers.get(
61                     "x-queue-start", default=""
62                 ) or request.headers.get("x-request-start", default="")
63             except Exception:
64                 pass
65             else:
66                 tracked_queue_time = track_request_queue_time(
67                     queue_time, tracked_request
68                 )
69             if not tracked_queue_time:
70                 try:
71                     amazon_queue_time = request.headers.get(
72                         "x-amzn-trace-id", default=""
73                     )
74                 except Exception:
75                     pass
76                 else:
77                     track_amazon_request_queue_time(amazon_queue_time, tracked_request)
78 
79             try:
80                 response = handler(request)
81             except Exception:
82                 tracked_request.tag("error", "true")
83                 raise
84 
85             # This happens further down the call chain. So time it starting
86             # above, but only name it if it gets to here.
87             if request.matched_route is not None:
88                 tracked_request.mark_real_request()
89                 span.operation = "Controller/" + request.matched_route.name
90 
91         finally:
92             tracked_request.stop_span()
93 
94         return response
95 
96     return scout_tween
97
```
--- 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/src/scout_apm/pyramid.py b/src/scout_apm/pyramid.py
--- a/src/scout_apm/pyramid.py
+++ b/src/scout_apm/pyramid.py
@@ -77,17 +77,18 @@
                     track_amazon_request_queue_time(amazon_queue_time, tracked_request)
 
             try:
-                response = handler(request)
+                try:
+                    response = handler(request)
+                finally:
+                    # Routing further down the call chain. So time it starting
+                    # above, but only name it if it gets a name
+                    if request.matched_route is not None:
+                        tracked_request.mark_real_request()
+                        span.operation = "Controller/" + request.matched_route.name
             except Exception:
                 tracked_request.tag("error", "true")
                 raise
 
-            # This happens further down the call chain. So time it starting
-            # above, but only name it if it gets to here.
-            if request.matched_route is not None:
-                tracked_request.mark_real_request()
-                span.operation = "Controller/" + request.matched_route.name
-
         finally:
             tracked_request.stop_span()

{"golden_diff": "diff --git a/src/scout_apm/pyramid.py b/src/scout_apm/pyramid.py\n--- a/src/scout_apm/pyramid.py\n+++ b/src/scout_apm/pyramid.py\n@@ -77,17 +77,18 @@\n                     track_amazon_request_queue_time(amazon_queue_time, tracked_request)\n \n             try:\n-                response = handler(request)\n+                try:\n+                    response = handler(request)\n+                finally:\n+                    # Routing further down the call chain. So time it starting\n+                    # above, but only name it if it gets a name\n+                    if request.matched_route is not None:\n+                        tracked_request.mark_real_request()\n+                        span.operation = \"Controller/\" + request.matched_route.name\n             except Exception:\n                 tracked_request.tag(\"error\", \"true\")\n                 raise\n \n-            # This happens further down the call chain. So time it starting\n-            # above, but only name it if it gets to here.\n-            if request.matched_route is not None:\n-                tracked_request.mark_real_request()\n-                span.operation = \"Controller/\" + request.matched_route.name\n-\n         finally:\n             tracked_request.stop_span()\n", "issue": "Report error requests on Pyramid\nCurrently if an error occurs in a Pyramid request, we don't report it. Error cases can be just as useful to see so we should try and do this. It looks like it's possible by rearranging the existing code.\n", "before_files": [{"content": "# coding=utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport scout_apm.core\nfrom scout_apm.core.config import ScoutConfig\nfrom scout_apm.core.tracked_request import TrackedRequest\nfrom scout_apm.core.web_requests import (\n    create_filtered_path,\n    ignore_path,\n    track_amazon_request_queue_time,\n    track_request_queue_time,\n)\n\n\ndef includeme(config):\n    configs = {}\n    pyramid_config = config.get_settings()\n    for name in pyramid_config:\n        if name.startswith(\"SCOUT_\"):\n            value = pyramid_config[name]\n            clean_name = name.replace(\"SCOUT_\", \"\").lower()\n            configs[clean_name] = value\n    ScoutConfig.set(**configs)\n\n    if scout_apm.core.install():\n        config.add_tween(\"scout_apm.pyramid.instruments\")\n\n\ndef instruments(handler, registry):\n    def scout_tween(request):\n        tracked_request = TrackedRequest.instance()\n        span = tracked_request.start_span(operation=\"Controller/Pyramid\")\n\n        try:\n            path = request.path\n            # mixed() returns values as *either* single items or lists\n            url_params = [\n                (k, v) for k, vs in request.GET.dict_of_lists().items() for v in vs\n            ]\n            tracked_request.tag(\"path\", create_filtered_path(path, url_params))\n            if ignore_path(path):\n                tracked_request.tag(\"ignore_transaction\", True)\n\n            try:\n                # Determine a remote IP to associate with the request. The value is\n                # spoofable by the requester so this is not suitable to use in any\n                # security sensitive context.\n                user_ip = (\n                    request.headers.get(\"x-forwarded-for\", default=\"\").split(\",\")[0]\n                    or request.headers.get(\"client-ip\", default=\"\").split(\",\")[0]\n                    or request.remote_addr\n                )\n            except Exception:\n                pass\n            else:\n                tracked_request.tag(\"user_ip\", user_ip)\n\n            tracked_queue_time = False\n            try:\n                queue_time = request.headers.get(\n                    \"x-queue-start\", default=\"\"\n                ) or request.headers.get(\"x-request-start\", default=\"\")\n            except Exception:\n                pass\n            else:\n                tracked_queue_time = track_request_queue_time(\n                    queue_time, tracked_request\n                )\n            if not tracked_queue_time:\n                try:\n                    amazon_queue_time = request.headers.get(\n                        \"x-amzn-trace-id\", default=\"\"\n                    )\n                except Exception:\n                    pass\n                else:\n                    track_amazon_request_queue_time(amazon_queue_time, tracked_request)\n\n            try:\n                response = handler(request)\n            except Exception:\n                tracked_request.tag(\"error\", \"true\")\n                raise\n\n            # This happens further down the call chain. So time it starting\n            # above, but only name it if it gets to here.\n            if request.matched_route is not None:\n                tracked_request.mark_real_request()\n                span.operation = \"Controller/\" + request.matched_route.name\n\n        finally:\n            tracked_request.stop_span()\n\n        return response\n\n    return scout_tween\n", "path": "src/scout_apm/pyramid.py"}], "after_files": [{"content": "# coding=utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport scout_apm.core\nfrom scout_apm.core.config import ScoutConfig\nfrom scout_apm.core.tracked_request import TrackedRequest\nfrom scout_apm.core.web_requests import (\n    create_filtered_path,\n    ignore_path,\n    track_amazon_request_queue_time,\n    track_request_queue_time,\n)\n\n\ndef includeme(config):\n    configs = {}\n    pyramid_config = config.get_settings()\n    for name in pyramid_config:\n        if name.startswith(\"SCOUT_\"):\n            value = pyramid_config[name]\n            clean_name = name.replace(\"SCOUT_\", \"\").lower()\n            configs[clean_name] = value\n    ScoutConfig.set(**configs)\n\n    if scout_apm.core.install():\n        config.add_tween(\"scout_apm.pyramid.instruments\")\n\n\ndef instruments(handler, registry):\n    def scout_tween(request):\n        tracked_request = TrackedRequest.instance()\n        span = tracked_request.start_span(operation=\"Controller/Pyramid\")\n\n        try:\n            path = request.path\n            # mixed() returns values as *either* single items or lists\n            url_params = [\n                (k, v) for k, vs in request.GET.dict_of_lists().items() for v in vs\n            ]\n            tracked_request.tag(\"path\", create_filtered_path(path, url_params))\n            if ignore_path(path):\n                tracked_request.tag(\"ignore_transaction\", True)\n\n            try:\n                # Determine a remote IP to associate with the request. The value is\n                # spoofable by the requester so this is not suitable to use in any\n                # security sensitive context.\n                user_ip = (\n                    request.headers.get(\"x-forwarded-for\", default=\"\").split(\",\")[0]\n                    or request.headers.get(\"client-ip\", default=\"\").split(\",\")[0]\n                    or request.remote_addr\n                )\n            except Exception:\n                pass\n            else:\n                tracked_request.tag(\"user_ip\", user_ip)\n\n            tracked_queue_time = False\n            try:\n                queue_time = request.headers.get(\n                    \"x-queue-start\", default=\"\"\n                ) or request.headers.get(\"x-request-start\", default=\"\")\n            except Exception:\n                pass\n            else:\n                tracked_queue_time = track_request_queue_time(\n                    queue_time, tracked_request\n                )\n            if not tracked_queue_time:\n                try:\n                    amazon_queue_time = request.headers.get(\n                        \"x-amzn-trace-id\", default=\"\"\n                    )\n                except Exception:\n                    pass\n                else:\n                    track_amazon_request_queue_time(amazon_queue_time, tracked_request)\n\n            try:\n                try:\n                    response = handler(request)\n                finally:\n                    # Routing further down the call chain. So time it starting\n                    # above, but only name it if it gets a name\n                    if request.matched_route is not None:\n                        tracked_request.mark_real_request()\n                        span.operation = \"Controller/\" + request.matched_route.name\n            except Exception:\n                tracked_request.tag(\"error\", \"true\")\n                raise\n\n        finally:\n            tracked_request.stop_span()\n\n        return response\n\n    return scout_tween\n", "path": "src/scout_apm/pyramid.py"}]}