We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add a configuration of collections that the history plugin needs to keep track on
Today the history plugin applies to all the collection but most of them don't need it.
For instance with the kinto-signer plugin we don't want to track history of changes in the preview and signed collection.
The same goes with the kinto-changes plugin when we don't want to track monitor changes modifications.

The same way we can configure the kinto-signer resources we want to track, we should be able to configure the list of collections we want the history plugin to track.
Add a configuration of collections that the history plugin needs to keep track on
Today the history plugin applies to all the collection but most of them don't need it.
For instance with the kinto-signer plugin we don't want to track history of changes in the preview and signed collection.
The same goes with the kinto-changes plugin when we don't want to track monitor changes modifications.

The same way we can configure the kinto-signer resources we want to track, we should be able to configure the list of collections we want the history plugin to track.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kinto/plugins/history/listener.py`
Content:
```
1 from kinto.core.utils import instance_uri
2 from datetime import datetime
3 
4 
5 def on_resource_changed(event):
6     """
7     Everytime an object is created/changed/deleted, we create an entry in the
8     ``history`` resource. The entries are served as read-only in the
9     :mod:`kinto.plugins.history.views` module.
10     """
11     payload = event.payload
12     resource_name = payload['resource_name']
13     event_uri = payload['uri']
14 
15     bucket_id = None
16     bucket_uri = None
17     collection_uri = None
18 
19     storage = event.request.registry.storage
20     permission = event.request.registry.permission
21 
22     targets = []
23     for impacted in event.impacted_records:
24         target = impacted['new']
25         obj_id = target['id']
26 
27         try:
28             bucket_id = payload['bucket_id']
29         except KeyError:
30             # e.g. DELETE /buckets
31             bucket_id = obj_id
32         bucket_uri = instance_uri(event.request, 'bucket', id=bucket_id)
33 
34         if 'collection_id' in payload:
35             collection_id = payload['collection_id']
36             collection_uri = instance_uri(event.request,
37                                           'collection',
38                                           bucket_id=bucket_id,
39                                           id=collection_id)
40 
41         # On POST .../records, the URI does not contain the newly created
42         # record id.
43         parts = event_uri.split('/')
44         if resource_name in parts[-1]:
45             parts.append(obj_id)
46         else:
47             # Make sure the id is correct on grouped events.
48             parts[-1] = obj_id
49         uri = '/'.join(parts)
50         targets.append((uri, target))
51 
52     # Prepare a list of object ids to be fetched from permission backend,
53     # and fetch them all at once. Use a mapping for later convenience.
54     all_perms_objects_ids = [oid for (oid, _) in targets]
55     all_perms_objects_ids.append(bucket_uri)
56     if collection_uri is not None:
57         all_perms_objects_ids.append(collection_uri)
58     all_perms_objects_ids = list(set(all_perms_objects_ids))
59     all_permissions = permission.get_objects_permissions(all_perms_objects_ids)
60     perms_by_object_id = dict(zip(all_perms_objects_ids, all_permissions))
61 
62     bucket_perms = perms_by_object_id[bucket_uri]
63     collection_perms = {}
64     if collection_uri is not None:
65         collection_perms = perms_by_object_id[collection_uri]
66 
67     # The principals allowed to read the bucket and collection.
68     # (Note: ``write`` means ``read``)
69     read_principals = set(bucket_perms.get('read', []))
70     read_principals.update(bucket_perms.get('write', []))
71     read_principals.update(collection_perms.get('read', []))
72     read_principals.update(collection_perms.get('write', []))
73 
74     # Create a history entry for each impacted record.
75     for (uri, target) in targets:
76         obj_id = target['id']
77         # Prepare the history entry attributes.
78         perms = {k: list(v) for k, v in perms_by_object_id[uri].items()}
79         eventattrs = dict(**payload)
80         eventattrs.pop('timestamp', None)  # Already in target `last_modified`.
81         eventattrs.pop('bucket_id', None)
82         eventattrs['%s_id' % resource_name] = obj_id
83         eventattrs['uri'] = uri
84         attrs = dict(date=datetime.now().isoformat(),
85                      target={'data': target, 'permissions': perms},
86                      **eventattrs)
87 
88         # Create a record for the 'history' resource, whose parent_id is
89         # the bucket URI (c.f. views.py).
90         # Note: this will be rolledback if the transaction is rolledback.
91         entry = storage.create(parent_id=bucket_uri,
92                                collection_id='history',
93                                record=attrs)
94 
95         # The read permission on the newly created history entry is the union
96         # of the record permissions with the one from bucket and collection.
97         entry_principals = set(read_principals)
98         entry_principals.update(perms.get('read', []))
99         entry_principals.update(perms.get('write', []))
100         entry_perms = {'read': list(entry_principals)}
101         # /buckets/{id}/history is the URI for the list of history entries.
102         entry_perm_id = '/buckets/%s/history/%s' % (bucket_id, entry['id'])
103         permission.replace_object_permissions(entry_perm_id, entry_perms)
104
```
--- 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/kinto/plugins/history/listener.py b/kinto/plugins/history/listener.py
--- a/kinto/plugins/history/listener.py
+++ b/kinto/plugins/history/listener.py
@@ -1,3 +1,5 @@
+from pyramid.settings import aslist
+
 from kinto.core.utils import instance_uri
 from datetime import datetime
 
@@ -18,6 +20,9 @@
 
     storage = event.request.registry.storage
     permission = event.request.registry.permission
+    settings = event.request.registry.settings
+
+    excluded_resources = aslist(settings.get('history.exclude_resources', ''))
 
     targets = []
     for impacted in event.impacted_records:
@@ -31,12 +36,17 @@
             bucket_id = obj_id
         bucket_uri = instance_uri(event.request, 'bucket', id=bucket_id)
 
+        if bucket_uri in excluded_resources:
+            continue
+
         if 'collection_id' in payload:
             collection_id = payload['collection_id']
             collection_uri = instance_uri(event.request,
                                           'collection',
                                           bucket_id=bucket_id,
                                           id=collection_id)
+            if collection_uri in excluded_resources:
+                continue
 
         # On POST .../records, the URI does not contain the newly created
         # record id.
@@ -47,8 +57,15 @@
             # Make sure the id is correct on grouped events.
             parts[-1] = obj_id
         uri = '/'.join(parts)
+
+        if uri in excluded_resources:
+            continue
+
         targets.append((uri, target))
 
+    if not targets:
+        return  # Nothing to do.
+
     # Prepare a list of object ids to be fetched from permission backend,
     # and fetch them all at once. Use a mapping for later convenience.
     all_perms_objects_ids = [oid for (oid, _) in targets]

{"golden_diff": "diff --git a/kinto/plugins/history/listener.py b/kinto/plugins/history/listener.py\n--- a/kinto/plugins/history/listener.py\n+++ b/kinto/plugins/history/listener.py\n@@ -1,3 +1,5 @@\n+from pyramid.settings import aslist\n+\n from kinto.core.utils import instance_uri\n from datetime import datetime\n \n@@ -18,6 +20,9 @@\n \n     storage = event.request.registry.storage\n     permission = event.request.registry.permission\n+    settings = event.request.registry.settings\n+\n+    excluded_resources = aslist(settings.get('history.exclude_resources', ''))\n \n     targets = []\n     for impacted in event.impacted_records:\n@@ -31,12 +36,17 @@\n             bucket_id = obj_id\n         bucket_uri = instance_uri(event.request, 'bucket', id=bucket_id)\n \n+        if bucket_uri in excluded_resources:\n+            continue\n+\n         if 'collection_id' in payload:\n             collection_id = payload['collection_id']\n             collection_uri = instance_uri(event.request,\n                                           'collection',\n                                           bucket_id=bucket_id,\n                                           id=collection_id)\n+            if collection_uri in excluded_resources:\n+                continue\n \n         # On POST .../records, the URI does not contain the newly created\n         # record id.\n@@ -47,8 +57,15 @@\n             # Make sure the id is correct on grouped events.\n             parts[-1] = obj_id\n         uri = '/'.join(parts)\n+\n+        if uri in excluded_resources:\n+            continue\n+\n         targets.append((uri, target))\n \n+    if not targets:\n+        return  # Nothing to do.\n+\n     # Prepare a list of object ids to be fetched from permission backend,\n     # and fetch them all at once. Use a mapping for later convenience.\n     all_perms_objects_ids = [oid for (oid, _) in targets]\n", "issue": "Add a configuration of collections that the history plugin needs to keep track on\nToday the history plugin applies to all the collection but most of them don't need it.\r\nFor instance with the kinto-signer plugin we don't want to track history of changes in the preview and signed collection.\r\nThe same goes with the kinto-changes plugin when we don't want to track monitor changes modifications.\r\n\r\nThe same way we can configure the kinto-signer resources we want to track, we should be able to configure the list of collections we want the history plugin to track.\nAdd a configuration of collections that the history plugin needs to keep track on\nToday the history plugin applies to all the collection but most of them don't need it.\r\nFor instance with the kinto-signer plugin we don't want to track history of changes in the preview and signed collection.\r\nThe same goes with the kinto-changes plugin when we don't want to track monitor changes modifications.\r\n\r\nThe same way we can configure the kinto-signer resources we want to track, we should be able to configure the list of collections we want the history plugin to track.\n", "before_files": [{"content": "from kinto.core.utils import instance_uri\nfrom datetime import datetime\n\n\ndef on_resource_changed(event):\n    \"\"\"\n    Everytime an object is created/changed/deleted, we create an entry in the\n    ``history`` resource. The entries are served as read-only in the\n    :mod:`kinto.plugins.history.views` module.\n    \"\"\"\n    payload = event.payload\n    resource_name = payload['resource_name']\n    event_uri = payload['uri']\n\n    bucket_id = None\n    bucket_uri = None\n    collection_uri = None\n\n    storage = event.request.registry.storage\n    permission = event.request.registry.permission\n\n    targets = []\n    for impacted in event.impacted_records:\n        target = impacted['new']\n        obj_id = target['id']\n\n        try:\n            bucket_id = payload['bucket_id']\n        except KeyError:\n            # e.g. DELETE /buckets\n            bucket_id = obj_id\n        bucket_uri = instance_uri(event.request, 'bucket', id=bucket_id)\n\n        if 'collection_id' in payload:\n            collection_id = payload['collection_id']\n            collection_uri = instance_uri(event.request,\n                                          'collection',\n                                          bucket_id=bucket_id,\n                                          id=collection_id)\n\n        # On POST .../records, the URI does not contain the newly created\n        # record id.\n        parts = event_uri.split('/')\n        if resource_name in parts[-1]:\n            parts.append(obj_id)\n        else:\n            # Make sure the id is correct on grouped events.\n            parts[-1] = obj_id\n        uri = '/'.join(parts)\n        targets.append((uri, target))\n\n    # Prepare a list of object ids to be fetched from permission backend,\n    # and fetch them all at once. Use a mapping for later convenience.\n    all_perms_objects_ids = [oid for (oid, _) in targets]\n    all_perms_objects_ids.append(bucket_uri)\n    if collection_uri is not None:\n        all_perms_objects_ids.append(collection_uri)\n    all_perms_objects_ids = list(set(all_perms_objects_ids))\n    all_permissions = permission.get_objects_permissions(all_perms_objects_ids)\n    perms_by_object_id = dict(zip(all_perms_objects_ids, all_permissions))\n\n    bucket_perms = perms_by_object_id[bucket_uri]\n    collection_perms = {}\n    if collection_uri is not None:\n        collection_perms = perms_by_object_id[collection_uri]\n\n    # The principals allowed to read the bucket and collection.\n    # (Note: ``write`` means ``read``)\n    read_principals = set(bucket_perms.get('read', []))\n    read_principals.update(bucket_perms.get('write', []))\n    read_principals.update(collection_perms.get('read', []))\n    read_principals.update(collection_perms.get('write', []))\n\n    # Create a history entry for each impacted record.\n    for (uri, target) in targets:\n        obj_id = target['id']\n        # Prepare the history entry attributes.\n        perms = {k: list(v) for k, v in perms_by_object_id[uri].items()}\n        eventattrs = dict(**payload)\n        eventattrs.pop('timestamp', None)  # Already in target `last_modified`.\n        eventattrs.pop('bucket_id', None)\n        eventattrs['%s_id' % resource_name] = obj_id\n        eventattrs['uri'] = uri\n        attrs = dict(date=datetime.now().isoformat(),\n                     target={'data': target, 'permissions': perms},\n                     **eventattrs)\n\n        # Create a record for the 'history' resource, whose parent_id is\n        # the bucket URI (c.f. views.py).\n        # Note: this will be rolledback if the transaction is rolledback.\n        entry = storage.create(parent_id=bucket_uri,\n                               collection_id='history',\n                               record=attrs)\n\n        # The read permission on the newly created history entry is the union\n        # of the record permissions with the one from bucket and collection.\n        entry_principals = set(read_principals)\n        entry_principals.update(perms.get('read', []))\n        entry_principals.update(perms.get('write', []))\n        entry_perms = {'read': list(entry_principals)}\n        # /buckets/{id}/history is the URI for the list of history entries.\n        entry_perm_id = '/buckets/%s/history/%s' % (bucket_id, entry['id'])\n        permission.replace_object_permissions(entry_perm_id, entry_perms)\n", "path": "kinto/plugins/history/listener.py"}], "after_files": [{"content": "from pyramid.settings import aslist\n\nfrom kinto.core.utils import instance_uri\nfrom datetime import datetime\n\n\ndef on_resource_changed(event):\n    \"\"\"\n    Everytime an object is created/changed/deleted, we create an entry in the\n    ``history`` resource. The entries are served as read-only in the\n    :mod:`kinto.plugins.history.views` module.\n    \"\"\"\n    payload = event.payload\n    resource_name = payload['resource_name']\n    event_uri = payload['uri']\n\n    bucket_id = None\n    bucket_uri = None\n    collection_uri = None\n\n    storage = event.request.registry.storage\n    permission = event.request.registry.permission\n    settings = event.request.registry.settings\n\n    excluded_resources = aslist(settings.get('history.exclude_resources', ''))\n\n    targets = []\n    for impacted in event.impacted_records:\n        target = impacted['new']\n        obj_id = target['id']\n\n        try:\n            bucket_id = payload['bucket_id']\n        except KeyError:\n            # e.g. DELETE /buckets\n            bucket_id = obj_id\n        bucket_uri = instance_uri(event.request, 'bucket', id=bucket_id)\n\n        if bucket_uri in excluded_resources:\n            continue\n\n        if 'collection_id' in payload:\n            collection_id = payload['collection_id']\n            collection_uri = instance_uri(event.request,\n                                          'collection',\n                                          bucket_id=bucket_id,\n                                          id=collection_id)\n            if collection_uri in excluded_resources:\n                continue\n\n        # On POST .../records, the URI does not contain the newly created\n        # record id.\n        parts = event_uri.split('/')\n        if resource_name in parts[-1]:\n            parts.append(obj_id)\n        else:\n            # Make sure the id is correct on grouped events.\n            parts[-1] = obj_id\n        uri = '/'.join(parts)\n\n        if uri in excluded_resources:\n            continue\n\n        targets.append((uri, target))\n\n    if not targets:\n        return  # Nothing to do.\n\n    # Prepare a list of object ids to be fetched from permission backend,\n    # and fetch them all at once. Use a mapping for later convenience.\n    all_perms_objects_ids = [oid for (oid, _) in targets]\n    all_perms_objects_ids.append(bucket_uri)\n    if collection_uri is not None:\n        all_perms_objects_ids.append(collection_uri)\n    all_perms_objects_ids = list(set(all_perms_objects_ids))\n    all_permissions = permission.get_objects_permissions(all_perms_objects_ids)\n    perms_by_object_id = dict(zip(all_perms_objects_ids, all_permissions))\n\n    bucket_perms = perms_by_object_id[bucket_uri]\n    collection_perms = {}\n    if collection_uri is not None:\n        collection_perms = perms_by_object_id[collection_uri]\n\n    # The principals allowed to read the bucket and collection.\n    # (Note: ``write`` means ``read``)\n    read_principals = set(bucket_perms.get('read', []))\n    read_principals.update(bucket_perms.get('write', []))\n    read_principals.update(collection_perms.get('read', []))\n    read_principals.update(collection_perms.get('write', []))\n\n    # Create a history entry for each impacted record.\n    for (uri, target) in targets:\n        obj_id = target['id']\n        # Prepare the history entry attributes.\n        perms = {k: list(v) for k, v in perms_by_object_id[uri].items()}\n        eventattrs = dict(**payload)\n        eventattrs.pop('timestamp', None)  # Already in target `last_modified`.\n        eventattrs.pop('bucket_id', None)\n        eventattrs['%s_id' % resource_name] = obj_id\n        eventattrs['uri'] = uri\n        attrs = dict(date=datetime.now().isoformat(),\n                     target={'data': target, 'permissions': perms},\n                     **eventattrs)\n\n        # Create a record for the 'history' resource, whose parent_id is\n        # the bucket URI (c.f. views.py).\n        # Note: this will be rolledback if the transaction is rolledback.\n        entry = storage.create(parent_id=bucket_uri,\n                               collection_id='history',\n                               record=attrs)\n\n        # The read permission on the newly created history entry is the union\n        # of the record permissions with the one from bucket and collection.\n        entry_principals = set(read_principals)\n        entry_principals.update(perms.get('read', []))\n        entry_principals.update(perms.get('write', []))\n        entry_perms = {'read': list(entry_principals)}\n        # /buckets/{id}/history is the URI for the list of history entries.\n        entry_perm_id = '/buckets/%s/history/%s' % (bucket_id, entry['id'])\n        permission.replace_object_permissions(entry_perm_id, entry_perms)\n", "path": "kinto/plugins/history/listener.py"}]}