Repository: scoutapp/scout_apm_python (python)

Issue:
PyMongo v4 removed collection methods
[PyMongo v4 removed a number of collection methods](https://pymongo.readthedocs.io/en/stable/migrate-to-pymongo4.html). While the agent still functions properly, it's logging failed instrumentation warnings and is breaking the build. 

Pull request description:
Avoid instrumenting PyMongo collection methods that were removed in v4.
Fixes #710 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index efc9321..01c2591 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
 ### Added
 
 ### Fixed
+- Avoid instrumenting PyMongo collection methods that were removed in v4.
+  ([Issue 710](https://github.com/scoutapp/scout_apm_python/issues/710))
 
 ## [2.23.4] 2021-11-12
 
diff --git a/src/scout_apm/instruments/pymongo.py b/src/scout_apm/instruments/pymongo.py
index 80474be..e0e26af 100644
--- a/src/scout_apm/instruments/pymongo.py
+++ b/src/scout_apm/instruments/pymongo.py
@@ -8,8 +8,10 @@ import wrapt
 from scout_apm.core.tracked_request import TrackedRequest
 
 try:
+    import pymongo
     from pymongo.collection import Collection
 except ImportError:
+    pymongo = None
     Collection = None
 
 logger = logging.getLogger(__name__)
@@ -25,7 +27,10 @@ def ensure_installed():
     if Collection is None:
         logger.debug("Couldn't import pymongo.Collection - probably not installed.")
     elif not have_patched_collection:
-        for name in COLLECTION_METHODS:
+        methods = COLLECTION_METHODS
+        if pymongo.version_tuple < (4, 0):
+            methods = COLLECTION_METHODS_V3
+        for name in methods:
             try:
                 setattr(
                     Collection, name, wrap_collection_method(getattr(Collection, name))
@@ -44,7 +49,6 @@ COLLECTION_METHODS = [
     "aggregate",
     "aggregate_raw_batches",
     "bulk_write",
-    "count",
     "count_documents",
     "create_index",
     "create_indexes",
@@ -54,32 +58,36 @@ COLLECTION_METHODS = [
     "drop",
     "drop_index",
     "drop_indexes",
-    "ensure_index",
     "estimated_document_count",
     "find",
-    "find_and_modify",
     "find_one",
     "find_one_and_delete",
     "find_one_and_replace",
     "find_one_and_update",
     "find_raw_batches",
-    "group",
     "index_information",
-    "inline_map_reduce",
-    "insert",
     "insert_many",
     "insert_one",
     "list_indexes",
+    "rename",
+    "replace_one",
+    "update_many",
+    "update_one",
+]
+
+COLLECTION_METHODS_V3 = COLLECTION_METHODS + [
+    "count",
+    "ensure_index",
+    "find_and_modify",
+    "group",
+    "inline_map_reduce",
+    "insert",
     "map_reduce",
     "parallel_scan",
     "reindex",
     "remove",
-    "rename",
-    "replace_one",
     "save",
     "update",
-    "update_many",
-    "update_one",
 ]
 
 


Test patch:
diff --git a/tests/integration/instruments/test_pymongo.py b/tests/integration/instruments/test_pymongo.py
index 54d7918..02e360f 100644
--- a/tests/integration/instruments/test_pymongo.py
+++ b/tests/integration/instruments/test_pymongo.py
@@ -7,7 +7,11 @@ import os
 import pymongo
 import pytest
 
-from scout_apm.instruments.pymongo import COLLECTION_METHODS, ensure_installed
+from scout_apm.instruments.pymongo import (
+    COLLECTION_METHODS,
+    COLLECTION_METHODS_V3,
+    ensure_installed,
+)
 from tests.compat import mock
 
 
@@ -43,9 +47,11 @@ def test_all_collection_attributes_accounted_for():
         # probably won't be used in web requests:
         "watch",
     }
-    assert (
-        all_methods - deliberately_ignored_methods - set(COLLECTION_METHODS)
-    ) == set()
+    if pymongo.version >= "4.0":
+        expected_methods = COLLECTION_METHODS
+    else:
+        expected_methods = COLLECTION_METHODS_V3
+    assert (all_methods - deliberately_ignored_methods - set(expected_methods)) == set()
 
 
 @pytest.mark.parametrize(["method_name"], [[x] for x in COLLECTION_METHODS])