bool CMetricBucketGatherer::processFields()

in lib/model/CMetricBucketGatherer.cc [1119:1264]


bool CMetricBucketGatherer::processFields(const TStrCPtrVec& fieldValues,
                                          CEventData& result,
                                          CResourceMonitor& resourceMonitor) {
    using TOptionalStr = std::optional<std::string>;

    if (fieldValues.size() != m_FieldNames.size()) {
        LOG_ERROR(<< "Unexpected field values: " << fieldValues
                  << ", for field names: " << m_FieldNames);
        return false;
    }

    const std::string* person = (fieldValues[0] == nullptr && m_DataGatherer.useNull())
                                    ? &EMPTY_STRING
                                    : fieldValues[0];
    if (person == nullptr) {
        // Just ignore: the "person" field wasn't present in the
        // record. Since all models in an aggregate share this
        // field we can't process this record further. Note that
        // we don't warn here since we'll permit a small fraction
        // of records to having missing field values.
        return false;
    }

    // The code below just ignores missing/invalid values. This
    // doesn't necessarily stop us processing the record by other
    // models, so we don't return false.

    std::size_t i = m_BeginInfluencingFields;
    for (/**/; i < m_BeginValueFields; ++i) {
        result.addInfluence(fieldValues[i] ? TOptionalStr(*fieldValues[i]) : std::nullopt);
    }
    if (m_DataGatherer.summaryMode() != model_t::E_None) {
        CEventData::TDouble1VecArraySizePr statistics;
        statistics.first.fill(TDouble1Vec(1, 0.0));
        if (m_DataGatherer.extractCountFromField(m_FieldNames[i], fieldValues[i],
                                                 statistics.second) == false) {
            result.addValue();
            return true;
        }
        ++i;

        bool allOk = true;
        if (m_FieldNames.size() > statistics.first.size() + i) {
            LOG_ERROR(<< "Inconsistency - more statistic field names than allowed "
                      << m_FieldNames.size() - i << " > " << statistics.first.size());
            allOk = false;
        }
        if (m_FieldNames.size() > m_FieldMetricCategories.size() + i) {
            LOG_ERROR(<< "Inconsistency - more statistic field names than metric categories "
                      << m_FieldNames.size() - i << " > "
                      << m_FieldMetricCategories.size());
            allOk = false;
        }
        for (std::size_t j = 0; allOk && i < m_FieldNames.size(); ++i, ++j) {
            model_t::EMetricCategory category = m_FieldMetricCategories[j];
            if (fieldValues[i] == nullptr ||
                m_DataGatherer.extractMetricFromField(
                    m_FieldNames[i], *fieldValues[i], statistics.first[category]) == false) {
                allOk = false;
            }
        }
        if (allOk) {
            if (statistics.second == CDataGatherer::EXPLICIT_NULL_SUMMARY_COUNT) {
                result.setExplicitNull();
            } else {
                result.addStatistics(statistics);
            }
        } else {
            result.addValue();
        }
    } else {
        TDouble1Vec value;
        if (fieldValues[i] != nullptr &&
            m_DataGatherer.extractMetricFromField(m_FieldNames[i], *fieldValues[i],
                                                  value) == true) {
            result.addValue(value);
        } else {
            result.addValue();
        }
    }

    bool addedPerson = false;
    std::size_t pid = CDynamicStringIdRegistry::INVALID_ID;
    if (result.isExplicitNull()) {
        m_DataGatherer.personId(*person, pid);
    } else {
        pid = m_DataGatherer.addPerson(*person, resourceMonitor, addedPerson);
    }

    if (pid == CDynamicStringIdRegistry::INVALID_ID) {
        if (!result.isExplicitNull()) {
            LOG_TRACE(<< "Couldn't create a person, over memory limit");
        }
        return false;
    }
    if (addedPerson) {
        resourceMonitor.addExtraMemory(m_DataGatherer.isPopulation()
                                           ? CDataGatherer::ESTIMATED_MEM_USAGE_PER_OVER_FIELD
                                           : CDataGatherer::ESTIMATED_MEM_USAGE_PER_BY_FIELD);
        ++(m_DataGatherer.isPopulation()
               ? core::CProgramCounters::counter(counter_t::E_TSADNumberOverFields)
               : core::CProgramCounters::counter(counter_t::E_TSADNumberByFields));
    }

    if (!result.person(pid)) {
        LOG_ERROR(<< "Bad by field value: " << *person);
        return false;
    }

    const std::string* attribute =
        (fieldValues[1] == nullptr && m_DataGatherer.useNull()) ? &EMPTY_STRING
                                                                : fieldValues[1];

    if (m_DataGatherer.isPopulation()) {
        if (attribute == nullptr) {
            // Just ignore: the "by" field wasn't present in the
            // record. This doesn't necessarily stop us processing
            // the record by other models so we don't return false.
            // Note that we don't warn here since we'll permit a
            // small fraction of records to having missing field
            // values.
            result.addAttribute();
            result.addValue();
            return true;
        }

        bool addedAttribute = false;
        std::size_t cid = CDynamicStringIdRegistry::INVALID_ID;
        if (result.isExplicitNull()) {
            m_DataGatherer.attributeId(*attribute, cid);
        } else {
            cid = m_DataGatherer.addAttribute(*attribute, resourceMonitor, addedAttribute);
        }
        result.addAttribute(cid);

        if (addedAttribute) {
            resourceMonitor.addExtraMemory(CDataGatherer::ESTIMATED_MEM_USAGE_PER_BY_FIELD);
            ++core::CProgramCounters::counter(counter_t::E_TSADNumberByFields);
        }
    } else {
        // Add the unique attribute.
        result.addAttribute(std::size_t(0));
    }

    return true;
}