diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/elog.hpp | 116 | ||||
-rw-r--r-- | src/example/example.yaml | 24 | ||||
-rw-r--r-- | src/example/test.yaml | 16 | ||||
-rwxr-xr-x | src/pdmgen.py | 24 | ||||
-rw-r--r-- | src/templates/elog_with_metadata.mako.cpp | 5 |
5 files changed, 185 insertions, 0 deletions
diff --git a/src/elog.hpp b/src/elog.hpp index c3b0d02..3f8ae3b 100644 --- a/src/elog.hpp +++ b/src/elog.hpp @@ -12,6 +12,25 @@ namespace dbus namespace monitoring { +/** @struct ToString + * @brief Convert numbers to strings + */ +template <typename T> struct ToString +{ + static auto op(T&& value) + { + return std::to_string(std::forward<T>(value)); + } +}; + +template <> struct ToString<std::string> +{ + static auto op(const std::string& value) + { + return value; + } +}; + /** @class ElogBase * @brief Elog callback implementation. * @@ -89,6 +108,103 @@ class Elog : public ElogBase }; + +/** + * @class ElogWithMetadataCapture + * + * @brief A callback class that will save the paths, names, and + * current values of certain properties in the metadata of the + * error log it creates. + * + * The intended use case of this class is to create an error log with + * metadata that includes the property names and values that caused + * the condition to issue this callback. When the condition ran, it had + * set the pass/fail field on each property it checked in the properties' + * entries in the Storage array. This class then looks at those pass/fail + * fields to see which properties to log. + * + * Note that it's OK if different conditions and callbacks share the same + * properties because everything runs serially, so another condition can't + * touch those pass/fail fields until all of the first condition's callbacks + * are done. + * + * This class requires that the error log created only have 1 metadata field, + * and it must take a string. + * + * @tparam errorType - Error log type + * @tparam metadataType - The metadata to use + * @tparam propertyType - The data type of the captured properties + */ +template<typename errorType, + typename metadataType, + typename propertyType> +class ElogWithMetadataCapture : public IndexedCallback +{ + public: + ElogWithMetadataCapture() = delete; + ElogWithMetadataCapture(const ElogWithMetadataCapture&) = delete; + ElogWithMetadataCapture(ElogWithMetadataCapture&&) = default; + ElogWithMetadataCapture& operator=( + const ElogWithMetadataCapture&) = delete; + ElogWithMetadataCapture& operator=( + ElogWithMetadataCapture&&) = default; + virtual ~ElogWithMetadataCapture() = default; + explicit ElogWithMetadataCapture( + const PropertyIndex& index) : + IndexedCallback(index) {} + + /** + * @brief Callback interface implementation that + * creates an error log + */ + void operator()(Context ctx) override + { + auto data = captureMetadata(); + + phosphor::logging::report<errorType>( + metadataType(data.c_str())); + } + + private: + + /** + * @brief Builds a metadata string with property information + * + * Finds all of the properties in the index that have + * their condition pass/fail fields (get<1>(storage)) + * set to true, and then packs those paths, names, and values + * into a metadata string that looks like: + * + * |path1:name1=value1|path2:name2=value2|... + * + * @return The metadata string + */ + std::string captureMetadata() + { + std::string metadata{'|'}; + + for (const auto& n : index) + { + const auto& storage = std::get<2>(n.second).get(); + const auto& result = std::get<1>(storage); + + if (!result.empty() && any_ns::any_cast<bool>(result)) + { + const auto& path = std::get<0>(n.first).get(); + const auto& propertyName = std::get<2>(n.first).get(); + auto value = ToString<propertyType>::op( + any_ns::any_cast<propertyType>( + std::get<0>(storage))); + + metadata += path + ":" + propertyName + + '=' + value + '|'; + } + } + + return metadata; + }; +}; + /** @brief Argument type deduction for constructing Elog instances. * * @tparam T - Error log type diff --git a/src/example/example.yaml b/src/example/example.yaml index bfb1c62..ec0a611 100644 --- a/src/example/example.yaml +++ b/src/example/example.yaml @@ -99,6 +99,30 @@ value: testing... type: string +- name: example elog with metadata capture callback + description: > + 'Callbacks are actions pdm should take when instructed to do so. + + This callback creates an elog, and it will capture the values of the + properties that passed its condition check in the metadata field + (that must be a string type) in the form: + + |path1:property1=value1|path2:property2=value2| + + Note that as this callback depends on the condition that called it to + fill in the result of its checks on each property, this callback should + use the same properties and paths keywords as the condition that calls it. + + Currently an error log with only 1 metadata entry of type string is + supported.' + + class: callback + callback: elog_with_metadata + paths: example path group + properties: example property group + error: xyz::openbmc_project::Common::Callout::Error::Inventory + metadata: xyz::openbmc_project::Common::Callout::Inventory::CALLOUT_INVENTORY_PATH + - name: example event callback description: > 'Callbacks are actions PDM should take when instructed to do so. diff --git a/src/example/test.yaml b/src/example/test.yaml index 6632891..b37ff72 100644 --- a/src/example/test.yaml +++ b/src/example/test.yaml @@ -278,6 +278,22 @@ properties: test string property group error: xyz::openbmc_project::Common::Error::InternalFailure +- name: test elog that captures the passing string metadata + class: callback + callback: elog_with_metadata + paths: test path group + properties: test string property group + error: xyz::openbmc_project::Common::Callout::Error::Inventory + metadata: xyz::openbmc_project::Common::Callout::Inventory::CALLOUT_INVENTORY_PATH + +- name: test elog that captures the passing int64_t metadata + class: callback + callback: elog_with_metadata + paths: test path group + properties: test s64 property group + error: xyz::openbmc_project::Common::Callout::Error::Inventory + metadata: xyz::openbmc_project::Common::Callout::Inventory::CALLOUT_INVENTORY_PATH + - name: test method class: callback callback: method diff --git a/src/pdmgen.py b/src/pdmgen.py index 7487015..55df3e3 100755 --- a/src/pdmgen.py +++ b/src/pdmgen.py @@ -718,6 +718,29 @@ class Event(Callback, Renderer): c=self, indent=indent) + +class ElogWithMetadata(Callback, Renderer): + '''Handle the elog_with_metadata callback config file directive.''' + + def __init__(self, *a, **kw): + self.error = kw.pop('error') + self.metadata = kw.pop('metadata') + super(ElogWithMetadata, self).__init__(**kw) + + def construct(self, loader, indent): + with open('errors.hpp', 'a') as fd: + fd.write( + self.render( + loader, + 'errors.mako.hpp', + c=self)) + return self.render( + loader, + 'elog_with_metadata.mako.cpp', + c=self, + indent=indent) + + class ResolveCallout(Callback, Renderer): '''Handle the 'resolve callout' callback config file directive.''' @@ -901,6 +924,7 @@ class Everything(Renderer): 'callback': { 'journal': Journal, 'elog': Elog, + 'elog_with_metadata': ElogWithMetadata, 'event': Event, 'group': GroupOfCallbacks, 'method': Method, diff --git a/src/templates/elog_with_metadata.mako.cpp b/src/templates/elog_with_metadata.mako.cpp new file mode 100644 index 0000000..a26aa2c --- /dev/null +++ b/src/templates/elog_with_metadata.mako.cpp @@ -0,0 +1,5 @@ +std::make_unique<ElogWithMetadataCapture< +${indent(1)}sdbusplus::${c.error}, +${indent(1)}phosphor::logging::${c.metadata}, +${indent(1)}${c.datatype}>>( +${indent(1)}ConfigPropertyIndicies::get()[${c.instances}])\ |