If you can live with less fine-grained information - i.e. not down to the task level - then familiarize yourself with RETRY_FILES_ENABLED and RETRY_FILES_SAVE_PATH. See ansible-config list for details on those. These tell Ansible to list the hosts which failed a run in the designated file.
Another possibility that fits sort of in-between the first two is to insert a run_once: true task at select points in your playbook to compare the ansible_play_hosts_all and ansible_play_hosts lists to see how they differ. The difference will be the hosts which have failed at that point. The effectiveness of this method depends on the strategy your plays employ. In other words, all hosts’ task executions have to be in-sync at the time this run_once task runs. (I have not experimented with this. Nor with the other suggestions either.)