Repository: scoutapp/scout_apm_python (python)

Issue:
Add ARM support
We've added **linux** ARM support (aarch64) for the core agent binary in version 1.3.1. We need to add ARM architecture detection on linux for the Python agent.

On AWS graviton instance:

```
ubuntu@ip-172-31-58-208:~$ uname -a
Linux ip-172-31-58-208 5.4.0-1045-aws #47-Ubuntu SMP Tue Apr 13 07:04:23 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux
```

Note: I didn't try 3.9
Python 3.8
```
ubuntu@ip-172-31-58-208:~$ python3 --version
Python 3.8.10
ubuntu@ip-172-31-58-208:~$ python3
Python 3.8.10 (default, Jun  2 2021, 10:49:15)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform;
>>> platform.machine()
'aarch64'
>>>
```

Python 2.7:
```
ubuntu@ip-172-31-58-208:~$ python --version
Python 2.7.18

ubuntu@ip-172-31-58-208:~$ python
Python 2.7.18 (default, Mar  8 2021, 13:02:45)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform;
>>> platform.machine()
'aarch64'
>>>
```

The core agent 1.3.1 builds available:
```
core-agent-v1.3.1-aarch64-unknown-linux-gnu
core-agent-v1.3.1-aarch64-unknown-linux-musl
core-agent-v1.3.1-i686-unknown-linux-gnu
core-agent-v1.3.1-i686-unknown-linux-musl
core-agent-v1.3.1-x86_64-apple-darwin
core-agent-v1.3.1-x86_64-unknown-linux-gnu
core-agent-v1.3.1-x86_64-unknown-linux-musl

```

Pull request:
Support ARM 64 architecture for core agent.
Default to latest v1.3.1 core agent version.
Closes #683

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51ee1dc..732b8a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
 ### Added
 - Rework release Github action to utilize newer versions of cibuildwheel when available.
 - Added `search_mvt` instrumentation for ElasticSearch 7.15.0.
+- Default core agent version to v1.3.1. Support ARM64 core agent architecture.
+  ([Issue #683](https://github.com/scoutapp/scout_apm_python/issues/683))
 
 ### Fixed
 
diff --git a/src/scout_apm/core/config.py b/src/scout_apm/core/config.py
index 3c9d97f..939db86 100644
--- a/src/scout_apm/core/config.py
+++ b/src/scout_apm/core/config.py
@@ -220,7 +220,7 @@ class Defaults(object):
             "core_agent_log_level": "info",
             "core_agent_permissions": 700,
             "core_agent_socket_path": "tcp://127.0.0.1:6590",
-            "core_agent_version": "v1.3.0",  # can be an exact tag name, or 'latest'
+            "core_agent_version": "v1.3.1",  # can be an exact tag name, or 'latest'
             "disabled_instruments": [],
             "download_url": "https://s3-us-west-1.amazonaws.com/scout-public-downloads/apm_core_agent/release",  # noqa: B950
             "errors_batch_size": 5,
diff --git a/src/scout_apm/core/platform_detection.py b/src/scout_apm/core/platform_detection.py
index fea8a6c..8cc1533 100644
--- a/src/scout_apm/core/platform_detection.py
+++ b/src/scout_apm/core/platform_detection.py
@@ -8,14 +8,28 @@ def is_valid_triple(triple):
     values = triple.split("-", 1)
     return (
         len(values) == 2
-        and values[0] in ("i686", "x86_64", "unknown")
+        and values[0] in ("i686", "x86_64", "aarch64", "unknown")
         and values[1]
         in ("unknown-linux-gnu", "unknown-linux-musl", "apple-darwin", "unknown")
+        # Validate _apple_darwin_aarch64_override was applied.
+        and triple != "aarch64-apple-darwin"
     )
 
 
+def _apple_darwin_aarch64_override(triple):
+    """
+    If using M1 ARM64 machine, still use x86_64.
+    See https://github.com/scoutapp/scout_apm_python/issues/683
+    """
+    if triple == "aarch64-apple-darwin":
+        return "x86_64-apple-darwin"
+    return triple
+
+
 def get_triple():
-    return "{arch}-{platform}".format(arch=get_arch(), platform=get_platform())
+    return _apple_darwin_aarch64_override(
+        "{arch}-{platform}".format(arch=get_arch(), platform=get_platform())
+    )
 
 
 def get_arch():
@@ -27,6 +41,8 @@ def get_arch():
         return "i686"
     elif arch == "x86_64":
         return "x86_64"
+    elif arch == "aarch64":
+        return "aarch64"
     else:
         return "unknown"
 


Test patch:
diff --git a/tests/unit/core/test_platform_detection.py b/tests/unit/core/test_platform_detection.py
index 141a825..37808bc 100644
--- a/tests/unit/core/test_platform_detection.py
+++ b/tests/unit/core/test_platform_detection.py
@@ -15,15 +15,39 @@ def test_get_triple():
     assert platform_detection.is_valid_triple(triple)
 
 
+@pytest.mark.parametrize(
+    "machine, system, result",
+    [
+        ("x86_64", "Darwin", "x86_64-apple-darwin"),
+        ("aarch64", "Darwin", "x86_64-apple-darwin"),
+        ("x86_64", "Linux", "x86_64-unknown-linux-musl"),
+        ("aarch64", "Linux", "aarch64-unknown-linux-musl"),
+    ],
+)
+@mock.patch("platform.machine")
+@mock.patch("platform.system")
+def test_aarch64_apple_darwin_override(
+    platform_system, platform_machine, machine, system, result
+):
+    platform_machine.return_value = machine
+    platform_system.return_value = system
+    assert platform_detection.get_triple() == result
+
+
 @pytest.mark.parametrize(
     "triple, validity",
     [
         ("x86_64-apple-darwin", True),
         ("i686-unknown-linux-gnu", True),
+        ("aarch64-unknown-linux-gnu", True),
+        ("aarch64-unknown-linux-musl", True),
+        ("x86_64-apple-darwin", True),
         ("unknown-unknown-linux-musl", True),
         ("", False),
         ("unknown", False),
         ("---", False),
+        ("i686-apple-darwin", True),
+        ("aarch64-apple-darwin", False),
     ],
 )
 def test_is_valid_triple(triple, validity):
@@ -35,6 +59,7 @@ def test_is_valid_triple(triple, validity):
     [
         ("i686", "i686"),
         ("x86_64", "x86_64"),
+        ("aarch64", "aarch64"),
         ("i386", "unknown"),
         ("arm", "unknown"),
         ("", "unknown"),