We use `totalMetrics` with a `startTimeInNanos` and a call to `postIngest` to track the 'total time' that ingest is running for a given document. You can imagine it's a little stopwatch that we start and stop. Unfortunately, I think we're stopping the stopwatch just a little too soon, on the start side, we include the time spent transforming the document into an `IngestDocument`, but we do not include the (non-negligible) time transforming from an `IngestDocument` after the pipeline logic has run.

That is, the call to `sourceAsMap` is included:

https://github.com/elastic/elasticsearch/blob/d03664f84f15dcfcb900cf2d43121ca9d89bdda8/server/src/main/java/org/elasticsearch/ingest/IngestService.java#L905

But the call to `source` is not:

https://github.com/elastic/elasticsearch/blob/d03664f84f15dcfcb900cf2d43121ca9d89bdda8/server/src/main/java/org/elasticsearch/ingest/IngestService.java#L948

The consequence of this is that the `total` ingest stats doesn't actually reflect the true time spent in ingest code:

```
GET _nodes/stats?filter_path=nodes.*.ingest
{
  "nodes" : {
    "Aysm6ztIRne2ES5ktyuqtw" : {
      "ingest" : {
        "total" : {
          "count" : 1,
          "time_in_millis" : 110, <--- this should be a little higher than it is
```
server/src/main/java/org/elasticsearch/ingest/IngestService.java
() -> format(
                            "failed to execute pipeline [%s] for document [%s/%s]",
                            pipelineId,
                            indexRequest.index(),
                            indexRequest.id()
                        ),
                        e
                    );
                    onFailure.accept(slot, e);
                }
                Iterator<String> newIt = it;
                boolean newHasFinalPipeline = hasFinalPipeline;
                String newIndex = indexRequest.indices()[0];
                if (Objects.equals(originalIndex, newIndex) == false) {
                    if (hasFinalPipeline && it.hasNext() == false) {
                        totalMetrics.ingestFailed();
                        onFailure.accept(
                            slot,
                            new IllegalStateException("final pipeline [" + pipelineId + "] can't change the target index")
                        );
                    } else {
                        indexRequest.isPipelineResolved(false);
                        resolvePipelines(null, indexRequest, state.metadata());
                        if (IngestService.NOOP_PIPELINE_NAME.equals(indexRequest.getFinalPipeline()) == false) {
                            newIt = Collections.singleton(indexRequest.getFinalPipeline()).iterator();
                            newHasFinalPipeline = true;
                        } else {
                            newIt = Collections.emptyIterator();
                        }
                    }