We have a check that enforces the total number of fields needs to be below a certain (configurable) threshold in each index. 

Runtime fields currently do not contribute to the count. There have been misunderstandings around this, caused by runtime fields not having a corresponding lucene field. Object fields and alias fields don't have corresponding lucene fields either yet they count towards the total fields limit.

The original goal of the total fields limit is to prevent a mappings explosion caused by a bogus document being indexed, as it would cause fields being dynamically added to the index mappings, which hinders stability due to the cluster state size of mappings as well as memory footprint of mappings in data nodes.

Runtime fields contribute to cluster state size and memory footprint of mappings like any other field, and they can be created dynamically when [`dynamic` is set to `runtime`](https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic.html#dynamic-parameters). Currently a bogus document can cause a mappings explosion when `dynamic` is set to `runtime` which is a bug. For this reason runtime fields should be counted towards the total fields count.
server/src/main/java/org/elasticsearch/index/mapper/DocumentParserContext.java
* Get a dynamic object mapper by name. Allows consumers to lookup objects that have been dynamically added as a result
     * of parsing an incoming document. Used to find the parent object for new fields that are being dynamically mapped whose parent is
     * also not mapped yet. Such new fields will need to be dynamically added to their parent according to its dynamic behaviour.
     * Holds a flat set of object mappers, meaning that an object field named <code>foo.bar</code> can be looked up directly with its
     * dotted name.
     */
    final ObjectMapper getDynamicObjectMapper(String name) {
        return dynamicObjectMappers.get(name);
    }
    /**
     * Add a new runtime field dynamically created while parsing.
     */
    public final void addDynamicRuntimeField(RuntimeField runtimeField) {
        dynamicRuntimeFields.add(runtimeField);
    }
    /**
     * Get dynamic runtime fields created while parsing. Holds a flat set of {@link RuntimeField}s.
     * Runtime fields get dynamically mapped when {@link org.elasticsearch.index.mapper.ObjectMapper.Dynamic#RUNTIME} is used,
     * or when dynamic templates specify a <code>runtime</code> section.
     */
    public final List<RuntimeField> getDynamicRuntimeFields() {
        return Collections.unmodifiableList(dynamicRuntimeFields);
    }
    /**
     * Returns an Iterable over all non-root documents. If there are no non-root documents
     * the iterable will return an empty iterator.
     */
    public abstract Iterable<LuceneDocument> nonRootDocuments();
    /**
     * @return a RootObjectMapper.Builder to be used to construct a dynamic mapping update