Repository: elastic/apm-agent-python

Issue:
Missing HTTP status code since version 6.3.1 using Starlette
**Describe the bug**:  HTTP status code is missing when using agent versions > 6.2.3 and Starlette

**To Reproduce**

1. Create a hello world REST service with FastAPI and agent 6.7.2. 
2. Send requests
2. APM transactions are uploaded to ES but are missing HTTP status code

**Environment (please complete the following information)**
- OS: Indifferent. Happens on Mac OS X and Docker containers
- Python version: 3.9.7
- Framework and version: Starlette 0.17.1
- APM Server version: 7.12.0
- Agent version: 6.3.1 - 6.7.2


**Additional context**

Add any other context about the problem here.

- Agent config options <!-- be careful not to post sensitive information -->
  <details>
    <summary>Click to expand</summary>

    ```
   # Nothing special here, app is just the FastAPI instance
   def configure_apm(app):
          apm_config = {
              "SERVICE_NAME": APPLICATION_NAME,
              "SERVER_URL": os.environ.get("ELASTIC_APM_SERVER_HOST"),
              "SECRET_TOKEN": os.environ.get("ELASTIC_APM_SECRET_TOKEN"),
              "ENVIRONMENT": os.environ.get("ENVIRONMENT", "staging").lower(),
          }
          apm = make_apm_client(apm_config)
          app.add_middleware(ElasticAPM, client=apm)
    ```
  </details>
- `requirements.txt`:
  <details>
    <summary>Click to expand</summary>

    ```
    elastic-apm==6.7.2
    starlette==0.17.1
    uvicorn==0.17.1
    fastapi==0.73.0

    ```
  </details>

- Example APM JSON document using agent 6.7.2:
  <details>

  ```

    {
    "_index": "apm-7.12.0-transaction-000010",
    "_type": "_doc",
    "_id": "H-xCBn8BoEtMrRa0MKNx",
    "_version": 1,
    "_score": null,
    "fields": {
      "transaction.name.text": [
        "GET /test/fran"
      ],
      "user_agent.original.text": [
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"
      ],
      "host.hostname": [
        "MacBook-Pro-de-Fran.local"
      ],
      "process.pid": [
        70040
      ],
      "service.language.name": [
        "python"
      ],
      "transaction.result": [
        "HTTP 2xx"
      ],
      "user_agent.os.version": [
        "10.15.7"
      ],
      "transaction.id": [
        "d01f7447213a4374"
      ],
      "http.request.method": [
        "GET"
      ],
      "processor.event": [
        "transaction"
      ],
      "agent.name": [
        "python"
      ],
      "host.name": [
        "MacBook-Pro-de-Fran.local"
      ],
      "user_agent.version": [
        "98.0.4758.80"
      ],
      "event.outcome": [
        "success"
      ],
      "user_agent.original": [
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"
      ],
      "process.ppid": [
        70038
      ],
      "processor.name": [
        "transaction"
      ],
      "transaction.duration.us": [
        642
      ],
      "service.runtime.version": [
        "3.9.7"
      ],
      "user_agent.name": [
        "Chrome"
      ],
      "host.architecture": [
        "arm64"
      ],
      "timestamp.us": [
        1645077472362757
      ],
      "url.path": [
        "/test/fran"
      ],
      "ecs.version": [
        "1.8.0"
      ],
      "observer.type": [
        "apm-server"
      ],
      "observer.version": [
        "7.12.0"
      ],
      "agent.version": [
        "6.7.2"
      ],
      "transaction.name": [
        "GET /test/fran"
      ],
      "service.framework.version": [
        "0.17.1"
      ],
      "observer.name": [
        "instance-0000000001"
      ],
      "user_agent.os.full": [
        "Mac OS X 10.15.7"
      ],
      "service.node.name": [
        "MacBook-Pro-de-Fran.local"
      ],
      "url.scheme": [
        "http"
      ],
      "transaction.sampled": [
        true
      ],
      "user_agent.os.name": [
        "Mac OS X"
      ],
      "host.ip": [
        "-"
      ],
      "trace.id": [
        "0c161d26c928799b770ccddcf4cfe3c4"
      ],
      "transaction.span_count.dropped": [
        0
      ],
      "url.port": [
        8000
      ],
      "url.full": [
        "http://localhost:8000/test/fran"
      ],
      "service.environment": [
        "staging"
      ],
      "service.name": [
        "test"
      ],
      "service.framework.name": [
        "starlette"
      ],
      "service.runtime.name": [
        "CPython"
      ],
      "process.args": [
        "/Users/fgarcia/miniconda3/envs/test-rest/lib/python3.9/site-packages/uvicorn/__main__.py",
        "app.main:app",
        "--reload"
      ],
      "observer.version_major": [
        7
      ],
      "observer.hostname": [
        "c2c026e5b645"
      ],
      "transaction.type": [
        "request"
      ],
      "event.ingested": [
        "2022-02-17T05:57:55.440Z"
      ],
      "@timestamp": [
        "2022-02-17T05:57:52.362Z"
      ],
      "host.os.platform": [
        "darwin"
      ],
      "service.language.version": [
        "3.9.7"
      ],
      "url.domain": [
        "localhost"
      ],
      "user_agent.device.name": [
        "Mac"
      ]
    },
    "highlight": {
      "host.architecture": [
        "@kibana-highlighted-field@arm64@/kibana-highlighted-field@"
      ],
      "service.name": [
        "@kibana-highlighted-field@test@/kibana-highlighted-field@"
      ],
      "service.framework.name": [
        "@kibana-highlighted-field@starlette@/kibana-highlighted-field@"
      ],
      "processor.name": [
        "@kibana-highlighted-field@transaction@/kibana-highlighted-field@"
      ],
      "agent.version": [
        "@kibana-highlighted-field@6.7.2@/kibana-highlighted-field@"
      ]
    },
    "sort": [
      1645077472362
    ]
  }
  ```

 </details>

- Example APM JSON document using agent 6.2.3:
  <details>

  ```
  {
    "_index": "apm-7.12.0-transaction-000010",
    "_type": "_doc",
    "_id": "oOw-Bn8BoEtMrRa0M5-0",
    "_version": 1,
    "_score": null,
    "fields": {
      "transaction.name.text": [
        "GET /test/fran"
      ],
      "user_agent.original.text": [
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"
      ],
      "host.hostname": [
        "MacBook-Pro-de-Fran.local"
      ],
      "process.pid": [
        69858
      ],
      "service.language.name": [
        "python"
      ],
      "transaction.result": [
        "HTTP 2xx"
      ],
      "user_agent.os.version": [
        "10.15.7"
      ],
      "transaction.id": [
        "ab3e2d9c98d72380"
      ],
      "http.request.method": [
        "GET"
      ],
      "processor.event": [
        "transaction"
      ],
      "agent.name": [
        "python"
      ],
      "host.name": [
        "MacBook-Pro-de-Fran.local"
      ],
      "user_agent.version": [
        "-"
      ],
      "http.response.status_code": [
        200
      ],
      "event.outcome": [
        "success"
      ],
      "user_agent.original": [
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36"
      ],
      "process.ppid": [
        69856
      ],
      "processor.name": [
        "transaction"
      ],
      "transaction.duration.us": [
        656
      ],
      "service.runtime.version": [
        "3.9.7"
      ],
      "user_agent.name": [
        "Chrome"
      ],
      "host.architecture": [
        "arm64"
      ],
      "timestamp.us": [
        1645077212632517
      ],
      "url.path": [
        "/test/fran"
      ],
      "ecs.version": [
        "1.8.0"
      ],
      "observer.type": [
        "apm-server"
      ],
      "observer.version": [
        "7.12.0"
      ],
      "agent.version": [
        "6.2.3"
      ],
      "transaction.name": [
        "GET /test/fran"
      ],
      "service.framework.version": [
        "0.17.1"
      ],
      "observer.name": [
        "instance-0000000001"
      ],
      "user_agent.os.full": [
        "Mac OS X 10.15.7"
      ],
      "service.node.name": [
        "MacBook-Pro-de-Fran.local"
      ],
      "url.scheme": [
        "http"
      ],
      "transaction.sampled": [
        true
      ],
      "user_agent.os.name": [
        "Mac OS X"
      ],
      "host.ip": [
        "-"
      ],
      "trace.id": [
        "527836b27e7cfbe629eedca1f073ad38"
      ],
      "transaction.span_count.dropped": [
        0
      ],
      "url.port": [
        8000
      ],
      "url.full": [
        "http://localhost:8000/test/fran"
      ],
      "service.environment": [
        "staging"
      ],
      "service.name": [
        "test"
      ],
      "service.framework.name": [
        "starlette"
      ],
      "service.runtime.name": [
        "CPython"
      ],
      "process.args": [
        "/Users/fgarcia/miniconda3/envs/test-rest/lib/python3.9/site-packages/uvicorn/__main__.py",
        "app.main:app",
        "--reload"
      ],
      "observer.version_major": [
        7
      ],
      "observer.hostname": [
        "c2c026e5b645"
      ],
      "transaction.type": [
        "request"
      ],
      "event.ingested": [
        "2022-02-17T05:53:34.130Z"
      ],
      "@timestamp": [
        "2022-02-17T05:53:32.632Z"
      ],
      "host.os.platform": [
        "darwin"
      ],
      "service.language.version": [
        "3.9.7"
      ],
      "url.domain": [
        "localhost"
      ],
      "user_agent.device.name": [
        "Mac"
      ]
    },
    "highlight": {
      "service.name": [
        "@kibana-highlighted-field@test@/kibana-highlighted-field@"
      ],
      "service.framework.name": [
        "@kibana-highlighted-field@starlette@/kibana-highlighted-field@"
      ]
    },
    "sort": [
      1645077212632
    ]
  }
  ```

  </details>



Discussion:
Hey @fgsalomon. The example document you provided for 6.7.2 is a `metric` document (as can be seen in the `processor.name` field). Could you provide an example document of type `transaction`?
> Hey @fgsalomon. The example document you provided for 6.7.2 is a `metric` document (as can be seen in the `processor.name` field). Could you provide an example document of type `transaction`?

Sorry about that. I've updated the original message and think now is correct.

Resolving patch:
diff --git a/elasticapm/contrib/starlette/utils.py b/elasticapm/contrib/starlette/utils.py
--- a/elasticapm/contrib/starlette/utils.py
+++ b/elasticapm/contrib/starlette/utils.py
@@ -86,7 +86,7 @@ async def get_data_from_response(message: dict, config: Config, event_type: str)
     """
     result = {}
 
-    if "status_code" in message:
+    if "status" in message:
         result["status_code"] = message["status"]
 
     if config.capture_headers and "headers" in message:


Test patch:
diff --git a/tests/contrib/asyncio/starlette_tests.py b/tests/contrib/asyncio/starlette_tests.py
--- a/tests/contrib/asyncio/starlette_tests.py
+++ b/tests/contrib/asyncio/starlette_tests.py
@@ -146,6 +146,10 @@ def test_get(app, elasticapm_client):
     assert request["method"] == "GET"
     assert request["socket"] == {"remote_address": "127.0.0.1"}
 
+    response = transaction["context"]["response"]
+    assert response["status_code"] == 200
+    assert response["headers"]["content-type"] == "text/plain; charset=utf-8"
+
     assert span["name"] == "test"