### Description

Add DagProcessor status including latest heartbeat to health endpoint similar to Triggerer status added recently. Related PRs.

https://github.com/apache/airflow/pull/31529
https://github.com/apache/airflow/pull/27755

### Use case/motivation

It helps in dag processor monitoring 

### Related issues

_No response_

### Are you willing to submit a PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

SchedulerJobRunner.most_recent_job = MagicMock(side_effect=Exception)
    TriggererJobRunner.most_recent_job = MagicMock(side_effect=Exception)
    health_status = get_airflow_health()
    expected_status = {
        "metadatabase": {"status": UNHEALTHY},
        "scheduler": {"status": UNHEALTHY, "latest_scheduler_heartbeat": None},
        "triggerer": {"status": UNHEALTHY, "latest_triggerer_heartbeat": None},
    }
    assert health_status == expected_status
def test_get_airflow_health_scheduler_healthy_no_triggerer():
    latest_scheduler_job_mock = MagicMock()
    latest_scheduler_job_mock.latest_heartbeat = datetime.now()
    latest_scheduler_job_mock.is_alive = MagicMock(return_value=True)
    SchedulerJobRunner.most_recent_job = MagicMock(return_value=latest_scheduler_job_mock)
    TriggererJobRunner.most_recent_job = MagicMock(return_value=None)
    health_status = get_airflow_health()
    expected_status = {
        "metadatabase": {"status": HEALTHY},
        "scheduler": {
            "status": HEALTHY,
            "latest_scheduler_heartbeat": latest_scheduler_job_mock.latest_heartbeat.isoformat(),
        },
        "triggerer": {"status": None, "latest_triggerer_heartbeat": None},
    }
    assert health_status == expected_status
def test_get_airflow_health_triggerer_healthy_no_scheduler_job_record():