#pragma once #include "config.h" #include "callouts-gen.hpp" #include "elog_entry.hpp" #include #include #include #include #include #include namespace phosphor { namespace logging { namespace metadata { using Metadata = std::string; namespace associations { using Type = void(const std::string&, const std::vector&, AssociationList& list); /** @brief Pull out metadata name and value from the string * = * @param [in] data - metadata key=value entries * @param [out] metadata - map of metadata name:value */ inline void parse(const std::vector& data, std::map& metadata) { constexpr auto separator = '='; for (const auto& entryItem : data) { auto pos = entryItem.find(separator); if (std::string::npos != pos) { auto key = entryItem.substr(0, entryItem.find(separator)); auto value = entryItem.substr(entryItem.find(separator) + 1); metadata.emplace(std::move(key), std::move(value)); } } } /** @brief Combine the metadata keys and values from the map * into a vector of strings that look like: * "=" * @param [in] data - metadata key:value map * @param [out] metadata - vector of "key=value" strings */ inline void combine(const std::map& data, std::vector& metadata) { for (const auto& [key, value] : data) { std::string line{key}; line += "=" + value; metadata.push_back(std::move(line)); } } /** @brief Build error associations specific to metadata. Specialize this * template for handling a specific type of metadata. * @tparam M - type of metadata * @param [in] match - metadata to be handled * @param [in] data - metadata key=value entries * @param [out] list - list of error association objects */ template void build(const std::string& match, const std::vector& data, AssociationList& list) = delete; // Example template specialization - we don't want to do anything // for this metadata. using namespace example::xyz::openbmc_project::Example::Elog; template <> inline void build(const std::string& /*match*/, const std::vector& /*data*/, AssociationList& /*list*/) { } template <> inline void build(const std::string& match, const std::vector& data, AssociationList& list) { std::map metadata; parse(data, metadata); auto iter = metadata.find(match); if (metadata.end() != iter) { auto comp = [](const auto& first, const auto& second) { return (std::strcmp(std::get<0>(first), second) < 0); }; auto callout = std::lower_bound(callouts.begin(), callouts.end(), (iter->second).c_str(), comp); if ((callouts.end() != callout) && !std::strcmp((iter->second).c_str(), std::get<0>(*callout))) { constexpr auto ROOT = "/xyz/openbmc_project/inventory"; list.push_back(std::make_tuple( "callout", "fault", std::string(ROOT) + std::get<1>(*callout))); } } } // The PROCESS_META flag is needed to get out of tree builds working. Such // builds will have access only to internal error interfaces, hence handlers // for out dbus error interfaces won't compile. This flag is not set by default, // the phosphor-logging recipe enabled it. #if defined PROCESS_META template <> void build( const std::string& match, const std::vector& data, AssociationList& list); template <> void build< xyz::openbmc_project::Common::Callout::Inventory::CALLOUT_INVENTORY_PATH>( const std::string& match, const std::vector& data, AssociationList& list); #endif // PROCESS_META } // namespace associations } // namespace metadata } // namespace logging } // namespace phosphor