Repository: elastic/apm-agent-python

Issue:
ELASTIC_APM_SERVICE_NAME env var for Python Lambda not working
We have a test Python lambda function using the elastic-apm-extension-ver-0-0-4-arm64 layer and have set 'ELASTIC_APM_SERVICE_NAME' environment variable to 'python-apm-enabled'. 

However, within Elastic under APM we are seeing the original function name (as it is within AWS - we want change the service name in Elastic to remove the environment prefix by setting ELASTIC_APM_SERVICE_NAME), so we would expect the name of the service and service.name within the metadata of the transaction in APM to reflect the value set by the environment variable.

It is showing under APM as 'test1-python-apm-enabled' for the Service Name and for service.name in the transaction metadata.
So it still includes the environment prefix. As we have added 'ELASTIC_APM_SERVICE_NAME' to the environment variables to change the service name, I would expect the name and service.name metadata to be updated to the new value.

Could you please advise how we would go about changing the service name to achieve our desired outcome?

Thanks

Discussion:
apmmachine: 
## :broken_heart: Tests Failed


<!-- BUILD BADGES-->
> _the below badges are clickable and redirect to their specific view in the CI or DOCS_
[![Pipeline View](https://img.shields.io/badge/pipeline-pipeline%20-green)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//pipeline) [![Test View](https://img.shields.io/badge/test-test-green)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//tests) [![Changes](https://img.shields.io/badge/changes-changes-green)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//changes) [![Artifacts](https://img.shields.io/badge/artifacts-artifacts-yellow)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//artifacts) [![preview](https://img.shields.io/badge/docs-preview-yellowgreen)](http://apm-agent-python_1489.docs-preview.app.elstc.co/diff)  [![preview](https://img.shields.io/badge/elastic-observability-blue)](https://ci-stats.elastic.co/app/apm/services/apm-ci/transactions/view?rangeFrom=2022-03-15T18:42:44.534Z&rangeTo=2022-03-15T19:02:44.534Z&transactionName=apm-agent-python/apm-agent-python-mbp/PR-{number}&transactionType=job&latencyAggregationType=avg&traceId=fa51d7b60c3fed700bd69e8a85e90310&transactionId=db4f9e20f71ef4be)

<!-- BUILD SUMMARY-->
<details><summary>Expand to view the summary</summary>
<p>

#### Build stats




* Start Time: 2022-03-15T18:52:44.534+0000


* Duration: 17 min 53 sec




#### Test stats :test_tube:

| Test         | Results                         |
| ------------ | :-----------------------------: |
| Failed       | 30  |
| Passed       | 4637  |
| Skipped      | 2662 |
| Total        | 7329   |


</p>
</details>

<!-- TEST RESULTS IF ANY-->

  ### Test errors [![30](https://img.shields.io/badge/30%20-red)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//tests)
<details><summary>Expand to view the tests failures</summary><p>
    > Show only the first 10 test failures
    
##### `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_api = {'body': None, 'headers': {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Ac...ge': 'en-US,en;q=0.5', 'CloudFront-Forwarded-Proto': 'https', ...}, 'httpMethod': 'GET', 'isBase64Encoded': False, ...}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f3d0c1f5320>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f3d0c1f52b0>

    def test_capture_serverless_api_gateway(event_api, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return {"statusCode": 200, "headers": {"foo": "bar"}}
    
        test_func(event_api, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:150: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_api2 = {'headers': {'accept': '*/*', 'content-length': '0', 'host': '02plqthge2.execute-api.us-east-1.amazonaws.com', 'user-agent': 'curl/7.64.1', ...}, 'isBase64Encoded': False, 'rawPath': '/dev/fetch_all', 'rawQueryString': '', ...}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f3d0c092208>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f3d0c0921d0>

    def test_capture_serverless_api_gateway_v2(event_api2, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return {"statusCode": 200, "headers": {"foo": "bar"}}
    
        test_func(event_api2, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:173: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_s3 = {'Records': [{'awsRegion': 'us-east-1', 'eventName': 'ObjectCreated:Put', 'eventSource': 'aws:s3', 'eventTime': '2021-07-22T17:00:56.160Z', ...}]}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f3d0c263358>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f3d0c2637b8>

    def test_capture_serverless_s3(event_s3, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return
    
        test_func(event_s3, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:196: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_sns = {'Records': [{'EventSource': 'aws:sns', 'EventSubscriptionArn': 'arn:aws:sns:us-east-1:268121251715:basepiwstesttopic:...B0TRMe8sLsv7OfWLA3GBl3b14MOUZfvUz4Btb15ssCq++QVHoTQWZnbJ5dA7P3ljMauQCagub0Zefx7uUmWAlczxe/5kREJt8rEfl+pN7Mg==', ...}}]}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f3d0c0904e0>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f3d0c090a58>

    def test_capture_serverless_sns(event_sns, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return
    
        test_func(event_sns, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:215: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_sqs – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_sqs = {'Records': [{'attributes': {'ApproximateFirstReceiveTimestamp': '1626973700075', 'ApproximateReceiveCount': '1', 'Sen...', 'SentTimestamp': '1626973700071'}, 'awsRegion': 'us-east-1', 'body': 'hello world', 'eventSource': 'aws:sqs', ...}]}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f3d0c0562b0>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f3d0c056128>

    def test_capture_serverless_sqs(event_sqs, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return
    
        test_func(event_sqs, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:234: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_s3_batch – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_s3_batch = {'Records': [{'awsRegion': 'us-east-1', 'eventName': 'ObjectCreated:Put', 'eventSource': 'aws:s3', 'eventTime': '2021-...'us-east-1', 'eventName': 'ObjectCreated:Put', 'eventSource': 'aws:s3', 'eventTime': '2021-07-22T17:00:56.160Z', ...}]}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f3d0c110668>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f3d0c1102e8>

    def test_capture_serverless_s3_batch(event_s3_batch, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return
    
        test_func(event_s3_batch, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:253: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_api = {'body': None, 'headers': {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Ac...ge': 'en-US,en;q=0.5', 'CloudFront-Forwarded-Proto': 'https', ...}, 'httpMethod': 'GET', 'isBase64Encoded': False, ...}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f6bdc3a81c0>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f6bdc3a86a0>

    def test_capture_serverless_api_gateway(event_api, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return {"statusCode": 200, "headers": {"foo": "bar"}}
    
        test_func(event_api, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:150: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_api2 = {'headers': {'accept': '*/*', 'content-length': '0', 'host': '02plqthge2.execute-api.us-east-1.amazonaws.com', 'user-agent': 'curl/7.64.1', ...}, 'isBase64Encoded': False, 'rawPath': '/dev/fetch_all', 'rawQueryString': '', ...}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f6bdc232e90>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f6bdc232d40>

    def test_capture_serverless_api_gateway_v2(event_api2, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return {"statusCode": 200, "headers": {"foo": "bar"}}
    
        test_func(event_api2, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:173: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_s3 = {'Records': [{'awsRegion': 'us-east-1', 'eventName': 'ObjectCreated:Put', 'eventSource': 'aws:s3', 'eventTime': '2021-07-22T17:00:56.160Z', ...}]}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f6bdc24e5f0>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f6bdc24caf0>

    def test_capture_serverless_s3(event_s3, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return
    
        test_func(event_s3, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:196: AssertionError 
 ```
</p></details>
</ul>
    
##### `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`


<ul>
<details><summary>Expand to view the error details</summary><p>

```
 assert 0 == 1
  +0
  -1 
 ```
</p></details>
<details><summary>Expand to view the stacktrace</summary><p>

```
 event_sns = {'Records': [{'EventSource': 'aws:sns', 'EventSubscriptionArn': 'arn:aws:sns:us-east-1:268121251715:basepiwstesttopic:...B0TRMe8sLsv7OfWLA3GBl3b14MOUZfvUz4Btb15ssCq++QVHoTQWZnbJ5dA7P3ljMauQCagub0Zefx7uUmWAlczxe/5kREJt8rEfl+pN7Mg==', ...}}]}
context = <tests.contrib.serverless.aws_tests.SampleContext object at 0x7f6bdc117d30>
elasticapm_client = <tests.fixtures.TempStoreClient object at 0x7f6bdc117a90>

    def test_capture_serverless_sns(event_sns, context, elasticapm_client):
    
        os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
    
        @capture_serverless()
        def test_func(event, context):
            with capture_span("test_span"):
                time.sleep(0.01)
            return
    
        test_func(event_sns, context)
    
>       assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
E       assert 0 == 1
E         +0
E         -1

tests/contrib/serverless/aws_tests.py:215: AssertionError 
 ```
</p></details>
</ul>
    
</p></details>


<!-- STEPS ERRORS IF ANY -->












### Steps errors [![23](https://img.shields.io/badge/23%20-red)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//pipeline)
  <details><summary>Expand to view the steps failures</summary>
  <p>


> Show only the first 10 steps failures

  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3355/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.6-httplib2-newest</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3390/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-flask-1.1</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3415/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-twisted-18</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3440/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-boto3-newest</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3465/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-memcached-newest</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3490/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-cassandra-newest</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3515/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-mysqlclient-newest</code></l1>
</ul>
  
  
  
  
##### `Restore files previously stashed`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3540/log/?start=0">here</a></li>
<li>Description: <code>coverage-python-3.10-pymemcache-newest</code></l1>
</ul>
  
  
  
  
##### `Archive the artifacts`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/3589/log/?start=0">here</a></li>
<li>Description: <code>[2022-03-15T19:09:34.989Z] Archiving artifacts
Python-python-3.6-none tests failed : hudson.AbortEx</code></l1>
</ul>
  
  
  
  
##### `Error signal`
<ul>
<li>Took 0 min 0 sec . View more details <a href="https://apm-ci.elastic.co//blue/rest/organizations/jenkins/pipelines/apm-agent-python/pipelines/apm-agent-python-mbp/pipelines/PR-1489/runs/1/steps/1452/log/?start=0">here</a></li>
<li>Description: <code>Python-python-3.6-none tests failed : hudson.AbortException: script returned exit code 2</code></l1>
</ul>
  
  </p>
  </details>



## :bug: Flaky test report
:grey_exclamation: There are test failures but not known flaky tests.



<details><summary>Expand to view the summary</summary>
<p>

### Genuine test errors [![30](https://img.shields.io/badge/30%20-red)](https://apm-ci.elastic.co/blue/organizations/jenkins/apm-agent-python%2Fapm-agent-python-mbp%2FPR-1489/detail/PR-1489/1//tests)
:broken_heart: There are test failures but not known flaky tests, most likely a genuine test failure.

* **Name**: `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_sqs – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.6-1 / test_capture_serverless_s3_batch – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_sqs – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / Python-python-3.10-1 / test_capture_serverless_s3_batch – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.7-none / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.7-none / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.7-none / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.7-none / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.7-none / test_capture_serverless_sqs – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.7-none / test_capture_serverless_s3_batch – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.8-none / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.8-none / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.8-none / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.8-none / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.8-none / test_capture_serverless_sqs – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.8-none / test_capture_serverless_s3_batch – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.9-none / test_capture_serverless_api_gateway – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.9-none / test_capture_serverless_api_gateway_v2 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.9-none / test_capture_serverless_s3 – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.9-none / test_capture_serverless_sns – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.9-none / test_capture_serverless_sqs – tests.contrib.serverless.aws_tests`
* **Name**: `Initializing / Test / windows-3.9-none / test_capture_serverless_s3_batch – tests.contrib.serverless.aws_tests`

</p>
</details>



## :robot: GitHub comments

To re-run your PR in the CI, just comment with:



- `/test` : Re-trigger the build.


- `/test linters` : Run the Python linters only.


- `/test full` : Run the full matrix of tests.


- `/test benchmark` : Run the APM Agent Python benchmarks tests.


- `run` `elasticsearch-ci/docs` : Re-trigger the docs validation. (use unformatted text in the comment!)




<!--COMMENT_GENERATED_WITH_ID_comment.id-->

Patch:
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 80ddecd5..0ff16179 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -42,6 +42,7 @@ endif::[]
 ===== Bug fixes
 
 * Fix Sanic integration to properly respect the `capture_body` config {pull}1485[#1485]
+* Lambda fixes to align with the cross-agent spec {pull}1489[#1489]
 
 
 [[release-notes-6.x]]
diff --git a/elasticapm/contrib/serverless/aws.py b/elasticapm/contrib/serverless/aws.py
index 306928c5..6545c694 100644
--- a/elasticapm/contrib/serverless/aws.py
+++ b/elasticapm/contrib/serverless/aws.py
@@ -38,7 +38,7 @@ import time
 from typing import Optional
 
 import elasticapm
-from elasticapm.base import Client, get_client
+from elasticapm.base import Client
 from elasticapm.conf import constants
 from elasticapm.utils import encoding, get_name_from_func, nested_key
 from elasticapm.utils.disttracing import TraceParent
@@ -66,25 +66,25 @@ class capture_serverless(object):
             return {"statusCode": r.status_code, "body": "Success!"}
     """
 
-    def __init__(self, name: Optional[str] = None, **kwargs) -> None:
+    def __init__(self, name: Optional[str] = None, elasticapm_client: Optional[Client] = None, **kwargs) -> None:
         self.name = name
         self.event = {}
         self.context = {}
         self.response = None
+        self.instrumented = False
+        self.client = elasticapm_client  # elasticapm_client is intended for testing only
 
         # Disable all background threads except for transport
         kwargs["metrics_interval"] = "0ms"
         kwargs["central_config"] = False
         kwargs["cloud_provider"] = "none"
         kwargs["framework_name"] = "AWS Lambda"
-        if "service_name" not in kwargs:
+        if "service_name" not in kwargs and "ELASTIC_APM_SERVICE_NAME" not in os.environ:
             kwargs["service_name"] = os.environ["AWS_LAMBDA_FUNCTION_NAME"]
+        if "service_version" not in kwargs and "ELASTIC_APM_SERVICE_VERSION" not in os.environ:
+            kwargs["service_version"] = os.environ.get("AWS_LAMBDA_FUNCTION_VERSION")
 
-        self.client = get_client()
-        if not self.client:
-            self.client = Client(**kwargs)
-        if not self.client.config.debug and self.client.config.instrument and self.client.config.enabled:
-            elasticapm.instrument()
+        self.client_kwargs = kwargs
 
     def __call__(self, func):
         self.name = self.name or get_name_from_func(func)
@@ -96,6 +96,21 @@ class capture_serverless(object):
                 self.event, self.context = args
             else:
                 self.event, self.context = {}, {}
+            # We delay client creation until the function is called, so that
+            # multiple @capture_serverless instances in the same file don't create
+            # multiple clients
+            if not self.client:
+                # Don't use get_client() as we may have a config mismatch due to **kwargs
+                self.client = Client(**self.client_kwargs)
+            if (
+                not self.instrumented
+                and not self.client.config.debug
+                and self.client.config.instrument
+                and self.client.config.enabled
+            ):
+                elasticapm.instrument()
+                self.instrumented = True
+
             if not self.client.config.debug and self.client.config.instrument and self.client.config.enabled:
                 with self:
                     self.response = func(*args, **kwds)
@@ -124,10 +139,21 @@ class capture_serverless(object):
         )
         if self.httpmethod:  # API Gateway
             self.source = "api"
-            if os.environ.get("AWS_LAMBDA_FUNCTION_NAME"):
-                transaction_name = "{} {}".format(self.httpmethod, os.environ["AWS_LAMBDA_FUNCTION_NAME"])
+            if nested_key(self.event, "requestContext", "httpMethod"):
+                # API v1
+                resource = "/{}{}".format(
+                    nested_key(self.event, "requestContext", "stage"),
+                    nested_key(self.event, "requestContext", "resourcePath"),
+                )
             else:
-                transaction_name = self.name
+                # API v2
+                route_key = nested_key(self.event, "requestContext", "routeKey")
+                route_key = f"/{route_key}" if route_key.startswith("$") else route_key.split(" ", 1)[-1]
+                resource = "/{}{}".format(
+                    nested_key(self.event, "requestContext", "stage"),
+                    route_key,
+                )
+            transaction_name = "{} {}".format(self.httpmethod, resource)
         elif "Records" in self.event and len(self.event["Records"]) == 1:
             record = self.event["Records"][0]
             if record.get("eventSource") == "aws:s3":  # S3
@@ -203,21 +229,17 @@ class capture_serverless(object):
         faas["coldstart"] = coldstart
         faas["trigger"] = {"type": "other"}
         faas["execution"] = self.context.aws_request_id
+        arn = self.context.invoked_function_arn
+        if len(arn.split(":")) > 7:
+            arn = ":".join(arn.split(":")[:7])
+        faas["id"] = arn
+        faas["name"] = os.environ.get("AWS_LAMBDA_FUNCTION_NAME")
+        faas["version"] = os.environ.get("AWS_LAMBDA_FUNCTION_VERSION")
 
         if self.source == "api":
             faas["trigger"]["type"] = "http"
             faas["trigger"]["request_id"] = self.event["requestContext"]["requestId"]
-            path = (
-                self.event["requestContext"].get("resourcePath")
-                or self.event["requestContext"]["http"]["path"].split(self.event["requestContext"]["stage"])[-1]
-            )
-            service_context["origin"] = {
-                "name": "{} {}/{}".format(
-                    self.httpmethod,
-                    self.event["requestContext"]["stage"],
-                    path,
-                )
-            }
+            service_context["origin"] = {"name": self.event["requestContext"]["domainName"]}
             service_context["origin"]["id"] = self.event["requestContext"]["apiId"]
             service_context["origin"]["version"] = self.event.get("version", "1.0")
             cloud_context["origin"] = {}
@@ -236,13 +258,18 @@ class capture_serverless(object):
             cloud_context["origin"]["region"] = record["awsRegion"]
             cloud_context["origin"]["account"] = {"id": record["eventSourceARN"].split(":")[4]}
             cloud_context["origin"]["provider"] = "aws"
-            message_context["queue"] = service_context["origin"]["name"]
+            message_context["queue"] = {"name": service_context["origin"]["name"]}
             if "SentTimestamp" in record["attributes"]:
                 message_context["age"] = {"ms": int((time.time() * 1000) - int(record["attributes"]["SentTimestamp"]))}
             if self.client.config.capture_body in ("transactions", "all") and "body" in record:
                 message_context["body"] = record["body"]
             if self.client.config.capture_headers and record.get("messageAttributes"):
-                message_context["headers"] = record["messageAttributes"]
+                headers = {}
+                for k, v in record["messageAttributes"].items():
+                    if v and v.get("stringValue"):
+                        headers[k] = v.get("stringValue")
+                if headers:
+                    message_context["headers"] = headers
         elif self.source == "sns":
             record = self.event["Records"][0]
             faas["trigger"]["type"] = "pubsub"
@@ -256,7 +283,7 @@ class capture_serverless(object):
             cloud_context["origin"]["region"] = record["Sns"]["TopicArn"].split(":")[3]
             cloud_context["origin"]["account_id"] = record["Sns"]["TopicArn"].split(":")[4]
             cloud_context["origin"]["provider"] = "aws"
-            message_context["queue"] = service_context["origin"]["name"]
+            message_context["queue"] = {"name": service_context["origin"]["name"]}
             if "Timestamp" in record["Sns"]:
                 message_context["age"] = {
                     "ms": int(
@@ -270,7 +297,12 @@ class capture_serverless(object):
             if self.client.config.capture_body in ("transactions", "all") and "Message" in record["Sns"]:
                 message_context["body"] = record["Sns"]["Message"]
             if self.client.config.capture_headers and record["Sns"].get("MessageAttributes"):
-                message_context["headers"] = record["Sns"]["MessageAttributes"]
+                headers = {}
+                for k, v in record["Sns"]["MessageAttributes"].items():
+                    if v and v.get("Type") == "String":
+                        headers[k] = v.get("Value")
+                if headers:
+                    message_context["headers"] = headers
         elif self.source == "s3":
             record = self.event["Records"][0]
             faas["trigger"]["type"] = "datasource"
@@ -291,11 +323,7 @@ class capture_serverless(object):
             "name": os.environ.get("AWS_EXECUTION_ENV"),
             "version": platform.python_version(),
         }
-        arn = self.context.invoked_function_arn
-        if len(arn.split(":")) > 7:
-            arn = ":".join(arn.split(":")[:7])
-        metadata["service"]["id"] = arn
-        metadata["service"]["version"] = os.environ.get("AWS_LAMBDA_FUNCTION_VERSION")
+        metadata["service"]["version"] = self.client.config.service_version
         metadata["service"]["node"] = {"configured_name": os.environ.get("AWS_LAMBDA_LOG_STREAM_NAME")}
         # This is the one piece of metadata that requires deep merging. We add it manually
         # here to avoid having to deep merge in _transport.add_metadata()
@@ -315,7 +343,7 @@ class capture_serverless(object):
         # faas doesn't actually belong in context, but we handle this in to_dict
         elasticapm.set_context(faas, "faas")
         if message_context:
-            elasticapm.set_context(service_context, "message")
+            elasticapm.set_context(message_context, "message")
         self.client._transport.add_metadata(metadata)
 
 
diff --git a/elasticapm/transport/base.py b/elasticapm/transport/base.py
index eb017bf7..61d6ccb3 100644
--- a/elasticapm/transport/base.py
+++ b/elasticapm/transport/base.py
@@ -153,7 +153,8 @@ class Transport(ThreadManager):
 
             queue_size = 0 if buffer.fileobj is None else buffer.fileobj.tell()
 
-            if flush:
+            forced_flush = flush
+            if forced_flush:
                 logger.debug("forced flush")
             elif timed_out or timeout == 0:
                 # update last flush time, as we might have waited for a non trivial amount of time in
@@ -172,7 +173,12 @@ class Transport(ThreadManager):
                 flush = True
             if flush:
                 if buffer_written:
-                    self._flush(buffer)
+                    self._flush(buffer, forced_flush=forced_flush)
+                elif forced_flush and "/localhost:" in self.client.config.server_url:
+                    # No data on buffer, but due to manual flush we should send
+                    # an empty payload with flushed=true query param, but only
+                    # to a local APM server (or lambda extension)
+                    self.send(None, flushed=True)
                 self._last_flush = timeit.default_timer()
                 buffer = self._init_buffer()
                 buffer_written = False
@@ -248,7 +254,7 @@ class Transport(ThreadManager):
         else:
             return _queue.Queue(maxsize=10000)
 
-    def _flush(self, buffer):
+    def _flush(self, buffer, forced_flush=False):
         """
         Flush the queue. This method should only be called from the event processing queue
         :return: None
@@ -262,7 +268,7 @@ class Transport(ThreadManager):
             # StringIO on Python 2 does not have getbuffer, so we need to fall back to getvalue
             data = fileobj.getbuffer() if hasattr(fileobj, "getbuffer") else fileobj.getvalue()
             try:
-                self.send(data)
+                self.send(data, forced_flush=forced_flush)
                 self.handle_transport_success()
             except Exception as e:
                 self.handle_transport_fail(e)
@@ -279,7 +285,7 @@ class Transport(ThreadManager):
             except RuntimeError:
                 pass
 
-    def send(self, data):
+    def send(self, data, forced_flush=False):
         """
         You need to override this to do something with the actual
         data. Usually - this is sending to a server
diff --git a/elasticapm/transport/http.py b/elasticapm/transport/http.py
index 16f2c9d5..45ef99cb 100644
--- a/elasticapm/transport/http.py
+++ b/elasticapm/transport/http.py
@@ -70,13 +70,15 @@ class Transport(HTTPTransportBase):
         self._http = None
         self._url = url
 
-    def send(self, data):
+    def send(self, data, forced_flush=False):
         response = None
 
         headers = self._headers.copy() if self._headers else {}
         headers.update(self.auth_headers)
 
         url = self._url
+        if forced_flush:
+            url = f"{url}?flushed=true"
         try:
             try:
                 response = self.http.urlopen(
diff --git a/elasticapm/transport/http_base.py b/elasticapm/transport/http_base.py
index c40bc97f..ac439bba 100644
--- a/elasticapm/transport/http_base.py
+++ b/elasticapm/transport/http_base.py
@@ -59,7 +59,7 @@ class HTTPTransportBase(Transport):
         self._server_info_url = "".join((base, constants.SERVER_INFO_PATH, tail))
         super(HTTPTransportBase, self).__init__(client, compress_level=compress_level, **kwargs)
 
-    def send(self, data):
+    def send(self, data, forced_flush=False):
         """
         Sends a request to a remote APM Server using HTTP POST.
 


Test patch:
diff --git a/tests/contrib/serverless/aws_sns_test_data.json b/tests/contrib/serverless/aws_sns_test_data.json
index 162cd6ed..e6c7a89e 100644
--- a/tests/contrib/serverless/aws_sns_test_data.json
+++ b/tests/contrib/serverless/aws_sns_test_data.json
@@ -15,7 +15,20 @@
                 "Signature": "YBGjMCe1m0QQ0DIWq4gZLy3/0bEyXhLPZJzeo4JYMa2P9ercshfn9s+x9nqd6HSYfO3RG0ebCmzxddgO8UCmaddXbhhMRWYjsIDv3+OvUitG8+bFqvpH/rQVHdCEWla5l+NDcye6d2cl9zuYFliTIFUsBmFcqbiroyZbIIHOczUpxNKK9oQcAXU6RgIl6y30DBgxYmzdMm4FMXPpden84v0LwVOyfqVm2gmeMnlccEOB0TRMe8sLsv7OfWLA3GBl3b14MOUZfvUz4Btb15ssCq++QVHoTQWZnbJ5dA7P3ljMauQCagub0Zefx7uUmWAlczxe/5kREJt8rEfl+pN7Mg==",
                 "SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem",
                 "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:268121251715:basepiwstesttopic:4763d52a-56d1-4dc5-99eb-ffb4315587af",
-                "MessageAttributes": {}
+                "MessageAttributes": {
+                    "Greeting": {
+                        "Type": "Binary",
+                        "Value": "SGVsbG8sIFdvcmxkIQ=="
+                    },
+                    "Population": {
+                        "Type": "String",
+                        "Value": "1250800"
+                    },
+                    "City": {
+                        "Type": "String",
+                        "Value": "Any City"
+                    }
+                }
             }
         }
     ]
diff --git a/tests/contrib/serverless/aws_sqs_test_data.json b/tests/contrib/serverless/aws_sqs_test_data.json
index cd92f89f..d78db5c1 100644
--- a/tests/contrib/serverless/aws_sqs_test_data.json
+++ b/tests/contrib/serverless/aws_sqs_test_data.json
@@ -10,7 +10,26 @@
                 "SenderId": "268121251715",
                 "ApproximateFirstReceiveTimestamp": "1626973700075"
             },
-            "messageAttributes": {},
+            "messageAttributes": {
+                "Greeting": {
+                    "binaryValue": "SGVsbG8sIFdvcmxkIQ==",
+                    "stringListValues": [],
+                    "binaryListValues": [],
+                    "dataType": "Binary"
+                },
+                "Population": {
+                    "stringValue": "1250800",
+                    "stringListValues": [],
+                    "binaryListValues": [],
+                    "dataType": "Number"
+                },
+                "City": {
+                    "stringValue": "Any City",
+                    "stringListValues": [],
+                    "binaryListValues": [],
+                    "dataType": "String"
+                }
+            },
             "md5OfBody": "5eb63bbbe01eeed093cb22bb8f5acdc3",
             "eventSource": "aws:sqs",
             "eventSourceARN": "arn:aws:sqs:us-east-1:268121251715:testqueue",
diff --git a/tests/contrib/serverless/aws_tests.py b/tests/contrib/serverless/aws_tests.py
index 79a7027b..0e018352 100644
--- a/tests/contrib/serverless/aws_tests.py
+++ b/tests/contrib/serverless/aws_tests.py
@@ -139,7 +139,7 @@ def test_capture_serverless_api_gateway(event_api, context, elasticapm_client):
 
     os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
 
-    @capture_serverless()
+    @capture_serverless(elasticapm_client=elasticapm_client)
     def test_func(event, context):
         with capture_span("test_span"):
             time.sleep(0.01)
@@ -150,7 +150,7 @@ def test_capture_serverless_api_gateway(event_api, context, elasticapm_client):
     assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
     transaction = elasticapm_client.events[constants.TRANSACTION][0]
 
-    assert transaction["name"] == "GET test_func"
+    assert transaction["name"] == "GET /dev/fetch_all"
     assert transaction["result"] == "HTTP 2xx"
     assert transaction["span_count"]["started"] == 1
     assert transaction["context"]["request"]["method"] == "GET"
@@ -162,7 +162,7 @@ def test_capture_serverless_api_gateway_v2(event_api2, context, elasticapm_clien
 
     os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
 
-    @capture_serverless()
+    @capture_serverless(elasticapm_client=elasticapm_client)
     def test_func(event, context):
         with capture_span("test_span"):
             time.sleep(0.01)
@@ -173,7 +173,7 @@ def test_capture_serverless_api_gateway_v2(event_api2, context, elasticapm_clien
     assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
     transaction = elasticapm_client.events[constants.TRANSACTION][0]
 
-    assert transaction["name"] == "GET test_func"
+    assert transaction["name"] == "GET /dev/fetch_all"
     assert transaction["result"] == "HTTP 2xx"
     assert transaction["span_count"]["started"] == 1
     assert transaction["context"]["request"]["method"] == "GET"
@@ -185,7 +185,7 @@ def test_capture_serverless_s3(event_s3, context, elasticapm_client):
 
     os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
 
-    @capture_serverless()
+    @capture_serverless(elasticapm_client=elasticapm_client)
     def test_func(event, context):
         with capture_span("test_span"):
             time.sleep(0.01)
@@ -204,7 +204,7 @@ def test_capture_serverless_sns(event_sns, context, elasticapm_client):
 
     os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
 
-    @capture_serverless()
+    @capture_serverless(elasticapm_client=elasticapm_client)
     def test_func(event, context):
         with capture_span("test_span"):
             time.sleep(0.01)
@@ -217,13 +217,15 @@ def test_capture_serverless_sns(event_sns, context, elasticapm_client):
 
     assert transaction["name"] == "RECEIVE basepiwstesttopic"
     assert transaction["span_count"]["started"] == 1
+    assert transaction["context"]["message"]["headers"]["Population"] == "1250800"
+    assert transaction["context"]["message"]["headers"]["City"] == "Any City"
 
 
 def test_capture_serverless_sqs(event_sqs, context, elasticapm_client):
 
     os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
 
-    @capture_serverless()
+    @capture_serverless(elasticapm_client=elasticapm_client)
     def test_func(event, context):
         with capture_span("test_span"):
             time.sleep(0.01)
@@ -236,13 +238,15 @@ def test_capture_serverless_sqs(event_sqs, context, elasticapm_client):
 
     assert transaction["name"] == "RECEIVE testqueue"
     assert transaction["span_count"]["started"] == 1
+    assert transaction["context"]["message"]["headers"]["Population"] == "1250800"
+    assert transaction["context"]["message"]["headers"]["City"] == "Any City"
 
 
 def test_capture_serverless_s3_batch(event_s3_batch, context, elasticapm_client):
 
     os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "test_func"
 
-    @capture_serverless()
+    @capture_serverless(elasticapm_client=elasticapm_client)
     def test_func(event, context):
         with capture_span("test_span"):
             time.sleep(0.01)
diff --git a/tests/transports/test_base.py b/tests/transports/test_base.py
index e1fe5de9..e1fd7906 100644
--- a/tests/transports/test_base.py
+++ b/tests/transports/test_base.py
@@ -84,13 +84,23 @@ def test_transport_state_set_success():
 
 
 @mock.patch("elasticapm.transport.base.Transport.send")
-@pytest.mark.parametrize("elasticapm_client", [{"api_request_time": "5s"}], indirect=True)
-def test_empty_queue_flush_is_not_sent(mock_send, elasticapm_client):
+@pytest.mark.parametrize(
+    "elasticapm_client",
+    [
+        {"api_request_time": "5s", "server_url": "http://localhost:8200"},
+        {"api_request_time": "5s", "server_url": "http://remotehost:8200"},
+    ],
+    indirect=True,
+)
+def test_empty_queue_flush(mock_send, elasticapm_client):
     transport = Transport(client=elasticapm_client)
     try:
         transport.start_thread()
         transport.flush()
-        assert mock_send.call_count == 0
+        if "localhost:" in elasticapm_client.config.server_url:
+            assert mock_send.call_count == 1
+        else:
+            assert mock_send.call_count == 0
     finally:
         transport.close()
 
@@ -246,3 +256,11 @@ def test_transport_metadata_pid_change(mock_send, elasticapm_client):
     time.sleep(0.2)
     assert transport._metadata
     transport.close()
+
+
+def test_flushed_arg(sending_elasticapm_client):
+    sending_elasticapm_client.begin_transaction("test_type")
+    sending_elasticapm_client.end_transaction("test")
+    sending_elasticapm_client._transport.flush()
+
+    assert sending_elasticapm_client.httpserver.requests[0].args["flushed"] == "true"