apm-agent-python
apm-agent-python copied to clipboard
APM-Instrumented Azure Function crashes when querying to Azure Table
Describe the bug:
When using Azure Table Client (package azure-data-tables) inside an Azure Function instrumented with elasticapm.contrib.serverless.azure.ElasticAPMExtension and querying a data table using PartitionKey and RowKey, the underlying HTTP request to the table service sends the request parameters in the query string and the request has no body. When Azure Tables instrumentation from Elastic APM reaches this line:
https://github.com/elastic/apm-agent-python/blob/fc8ef22e3427f23d77d26cbb647eceafd9ec3f19/elasticapm/instrumentation/packages/azure.py#L302-L307
It crashes because the body is None
To Reproduce
- Create an Storage Account in Azure and create a Table named 'test' and insert an entity with PartitionKey 'KEY' and RowKey 'ROW'
- Get the Storage Account SAS_TOKEN to connect to the table service and query the test table
- Create an Azure Function with this code
import azure.functions as func
from elasticapm.contrib.serverless.azure import ElasticAPMExtension
from azure.data.tables import TableServiceClient
from azure.core.credentials import AzureSasCredential
ElasticAPMExtension.configure()
def main(req: func.HttpRequest) -> func.HttpResponse:
_table_service_client = TableServiceClient(endpoint=TABLE_ENDPOINT,credential=AzureSasCredential(TABLE_SAS_TOKEN))
_table_client = _table_service_client.get_table_client('test')
entity = _table_client.get_entity(
partition_key='KEY',
row_key='ROW'
)
- Run
func host startto start the local development environment - Connect to the URL of the function and see the exception in the
funclogs
Environment (please complete the following information)
- OS: Windows
- Python version: 3.10.11
- Framework and version [e.g. Django 2.1]: Azure Functions
- APM Server version: 7.17
- Agent version: 6.23.0
Additional context
Add any other context about the problem here.
-
requirements.txt:Click to expand
elasticapm azure-functions azure-data-tables
Thanks for reporting, I think if you are keen to contributing a possible patch would be to just skip the json decoding if body is falsy and set it to {}.
Thanks @xrmx , will do that. What would be the best way to check "falsyness"? Something in the line of this would be enough?
if not body:
body = {}
else:
try:
body = json.loads(body)
except json.decoder.JSONDecodeError: # str not bytes
body = {}
I would keep the happy path before (if body:) but yeah, something like that.