summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/elog.hpp116
-rw-r--r--src/example/example.yaml24
-rw-r--r--src/example/test.yaml16
-rwxr-xr-xsrc/pdmgen.py24
-rw-r--r--src/templates/elog_with_metadata.mako.cpp5
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}])\
OpenPOWER on IntegriCloud