From 9a1225fb154bd985b2568a37a775f6735e3e5b46 Mon Sep 17 00:00:00 2001 From: cpiment <10828255+cpiment@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:17:11 +0200 Subject: [PATCH 1/6] Check if body exists before trying to convert it to JSON --- elasticapm/instrumentation/packages/azure.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/elasticapm/instrumentation/packages/azure.py b/elasticapm/instrumentation/packages/azure.py index 4200bb42b..055db3d63 100644 --- a/elasticapm/instrumentation/packages/azure.py +++ b/elasticapm/instrumentation/packages/azure.py @@ -300,9 +300,12 @@ def handle_azuretable(request, hostname, path, query_params, service, service_ty account_name = hostname.split(".")[0] method = request.method body = request.body - try: - body = json.loads(body) - except json.decoder.JSONDecodeError: # str not bytes + if body: + try: + body = json.loads(body) + except json.decoder.JSONDecodeError: # str not bytes + body = {} + else: body = {} # /tablename(PartitionKey='',RowKey='') resource_name = path.split("/", 1)[1] if "/" in path else path From a6c185fbd513b301c36be3f63a5c30c7cce23e3c Mon Sep 17 00:00:00 2001 From: cpiment <10828255+cpiment@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:30:54 +0200 Subject: [PATCH 2/6] Update in azure-data-tables uses PATCH instead of PUT --- elasticapm/instrumentation/packages/azure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elasticapm/instrumentation/packages/azure.py b/elasticapm/instrumentation/packages/azure.py index 055db3d63..934dbb17b 100644 --- a/elasticapm/instrumentation/packages/azure.py +++ b/elasticapm/instrumentation/packages/azure.py @@ -316,7 +316,7 @@ def handle_azuretable(request, hostname, path, query_params, service, service_ty } operation_name = "Unknown" - if method.lower() == "put": + if method.lower() == "put" or method.lower() == "patch": operation_name = "Update" if "properties" in query_params.get("comp", []): operation_name = "SetProperties" From bd06d256d9d216bd49f63d1a6941a1c1f6653eb6 Mon Sep 17 00:00:00 2001 From: cpiment <10828255+cpiment@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:31:21 +0200 Subject: [PATCH 3/6] Tests and requirements file for Azure Storage --- .../azurefunctions/azure_functions_tests.py | 2 +- tests/instrumentation/azure_tests.py | 65 +++++++++++++++++++ tests/requirements/reqs-azure-newest.txt | 5 ++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 tests/requirements/reqs-azure-newest.txt diff --git a/tests/contrib/serverless/azurefunctions/azure_functions_tests.py b/tests/contrib/serverless/azurefunctions/azure_functions_tests.py index 1db33758a..9f72278fb 100644 --- a/tests/contrib/serverless/azurefunctions/azure_functions_tests.py +++ b/tests/contrib/serverless/azurefunctions/azure_functions_tests.py @@ -29,7 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import pytest -azure = pytest.importorskip("azure") +azure = pytest.importorskip("azure-functions") import datetime import os diff --git a/tests/instrumentation/azure_tests.py b/tests/instrumentation/azure_tests.py index aeaab03c0..12ce2333d 100644 --- a/tests/instrumentation/azure_tests.py +++ b/tests/instrumentation/azure_tests.py @@ -39,9 +39,11 @@ azureblob = pytest.importorskip("azure.storage.blob") azurequeue = pytest.importorskip("azure.storage.queue") azuretable = pytest.importorskip("azure.cosmosdb.table") +azuredatatable = pytest.importorskip("azure.data.tables") azurefile = pytest.importorskip("azure.storage.fileshare") pytestmark = [pytest.mark.azurestorage] +from azure.data.tables import TableServiceClient as DataTableServiceClient from azure.cosmosdb.table.tableservice import TableService from azure.storage.blob import BlobServiceClient from azure.storage.fileshare import ShareClient @@ -82,6 +84,18 @@ def queue_client(): queue_client.delete_queue() +@pytest.fixture() +def data_table_service(): + table_name = "apmagentpythonci" + str(uuid.uuid4().hex) + data_table_service_client = DataTableServiceClient.from_connection_string(conn_str=CONNECTION_STRING) + data_table_service = data_table_service_client.get_table_client(table_name) + data_table_service.create_table() + data_table_service.table_name = table_name + + yield data_table_service + + data_table_service.delete_table() + @pytest.fixture() def table_service(): table_name = "apmagentpythonci" + str(uuid.uuid4().hex) @@ -182,6 +196,23 @@ def test_queue(instrument, elasticapm_client, queue_client): assert span["action"] == "delete" +def test_data_table_create(instrument, elasticapm_client): + table_name = "apmagentpythonci" + str(uuid.uuid4().hex) + data_table_service_client = DataTableServiceClient.from_connection_string(conn_str=CONNECTION_STRING) + data_table_service = data_table_service_client.get_table_client(table_name) + + elasticapm_client.begin_transaction("transaction.test") + data_table_service.create_table() + data_table_service.delete_table() + elasticapm_client.end_transaction("MyView") + + span = elasticapm_client.events[constants.SPAN][0] + + assert span["name"] == "AzureTable Create {}".format(table_name) + assert span["type"] == "storage" + assert span["subtype"] == "azuretable" + assert span["action"] == "Create" + def test_table_create(instrument, elasticapm_client): table_name = "apmagentpythonci" + str(uuid.uuid4().hex) table_service = TableService(connection_string=CONNECTION_STRING) @@ -198,6 +229,40 @@ def test_table_create(instrument, elasticapm_client): assert span["subtype"] == "azuretable" assert span["action"] == "Create" +def test_data_table(instrument, elasticapm_client, data_table_service): + table_name = data_table_service.table_name + elasticapm_client.begin_transaction("transaction.test") + task = {"PartitionKey": "tasksSeattle", "RowKey": "001", "description": "Take out the trash", "priority": 200} + data_table_service.create_entity(task) + task = {"PartitionKey": "tasksSeattle", "RowKey": "001", "description": "Take out the garbage", "priority": 250} + data_table_service.update_entity(task) + task = data_table_service.get_entity("tasksSeattle", "001") + data_table_service.delete_entity("tasksSeattle", "001") + elasticapm_client.end_transaction("MyView") + + span = elasticapm_client.events[constants.SPAN][0] + assert span["name"] == "AzureTable Insert {}".format(table_name) + assert span["type"] == "storage" + assert span["subtype"] == "azuretable" + assert span["action"] == "Insert" + + span = elasticapm_client.events[constants.SPAN][1] + assert span["name"] == "AzureTable Update {}(PartitionKey='tasksSeattle',RowKey='001')".format(table_name) + assert span["type"] == "storage" + assert span["subtype"] == "azuretable" + assert span["action"] == "Update" + + span = elasticapm_client.events[constants.SPAN][2] + assert span["name"] == "AzureTable Query {}(PartitionKey='tasksSeattle',RowKey='001')".format(table_name) + assert span["type"] == "storage" + assert span["subtype"] == "azuretable" + assert span["action"] == "Query" + + span = elasticapm_client.events[constants.SPAN][3] + assert span["name"] == "AzureTable Delete {}(PartitionKey='tasksSeattle',RowKey='001')".format(table_name) + assert span["type"] == "storage" + assert span["subtype"] == "azuretable" + assert span["action"] == "Delete" def test_table(instrument, elasticapm_client, table_service): table_name = table_service.table_name diff --git a/tests/requirements/reqs-azure-newest.txt b/tests/requirements/reqs-azure-newest.txt new file mode 100644 index 000000000..d21ec1f76 --- /dev/null +++ b/tests/requirements/reqs-azure-newest.txt @@ -0,0 +1,5 @@ +azure-storage-blob +azure-storage-queue +azure-data-tables +azure-storage-file-share +-r reqs-base.txt \ No newline at end of file From c80f62888f51c9ff97c3b879979d7764dacc8c02 Mon Sep 17 00:00:00 2001 From: cpiment <10828255+cpiment@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:45:36 +0200 Subject: [PATCH 4/6] Fixed typo in Azure Functions tests --- .../contrib/serverless/azurefunctions/azure_functions_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/contrib/serverless/azurefunctions/azure_functions_tests.py b/tests/contrib/serverless/azurefunctions/azure_functions_tests.py index 9f72278fb..16060aa41 100644 --- a/tests/contrib/serverless/azurefunctions/azure_functions_tests.py +++ b/tests/contrib/serverless/azurefunctions/azure_functions_tests.py @@ -29,7 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import pytest -azure = pytest.importorskip("azure-functions") +azure = pytest.importorskip("azure.functions") import datetime import os From 7cd6275949f1403485b523c2d3c1d40e73fff0db Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 24 Dec 2024 15:32:14 +0100 Subject: [PATCH 5/6] Apply suggestions from code review --- tests/instrumentation/azure_tests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/instrumentation/azure_tests.py b/tests/instrumentation/azure_tests.py index 12ce2333d..2650aa5cc 100644 --- a/tests/instrumentation/azure_tests.py +++ b/tests/instrumentation/azure_tests.py @@ -43,8 +43,8 @@ azurefile = pytest.importorskip("azure.storage.fileshare") pytestmark = [pytest.mark.azurestorage] -from azure.data.tables import TableServiceClient as DataTableServiceClient from azure.cosmosdb.table.tableservice import TableService +from azure.data.tables import TableServiceClient as DataTableServiceClient from azure.storage.blob import BlobServiceClient from azure.storage.fileshare import ShareClient from azure.storage.queue import QueueClient @@ -213,6 +213,7 @@ def test_data_table_create(instrument, elasticapm_client): assert span["subtype"] == "azuretable" assert span["action"] == "Create" + def test_table_create(instrument, elasticapm_client): table_name = "apmagentpythonci" + str(uuid.uuid4().hex) table_service = TableService(connection_string=CONNECTION_STRING) @@ -229,6 +230,7 @@ def test_table_create(instrument, elasticapm_client): assert span["subtype"] == "azuretable" assert span["action"] == "Create" + def test_data_table(instrument, elasticapm_client, data_table_service): table_name = data_table_service.table_name elasticapm_client.begin_transaction("transaction.test") @@ -263,6 +265,7 @@ def test_data_table(instrument, elasticapm_client, data_table_service): assert span["type"] == "storage" assert span["subtype"] == "azuretable" assert span["action"] == "Delete" + def test_table(instrument, elasticapm_client, table_service): table_name = table_service.table_name From a777741e18529c616e69daa47acdd971db78541d Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 24 Dec 2024 15:35:13 +0100 Subject: [PATCH 6/6] Update tests/instrumentation/azure_tests.py --- tests/instrumentation/azure_tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/instrumentation/azure_tests.py b/tests/instrumentation/azure_tests.py index 2650aa5cc..1567c5975 100644 --- a/tests/instrumentation/azure_tests.py +++ b/tests/instrumentation/azure_tests.py @@ -265,7 +265,6 @@ def test_data_table(instrument, elasticapm_client, data_table_service): assert span["type"] == "storage" assert span["subtype"] == "azuretable" assert span["action"] == "Delete" - def test_table(instrument, elasticapm_client, table_service): table_name = table_service.table_name