summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2018-02-19 14:03:05 -0600
committerBrad Bishop <bradleyb@fuzziesquirrel.com>2018-02-27 18:36:05 +0000
commit3c5318d843651dd18a6b8b0da67e3aaef810ca91 (patch)
tree7d842b08dc0d9324a9700c7b141edbb8c31448e7
parent35e75f0a402dd5c5e7786674bf861800ab675e0f (diff)
downloadphosphor-dbus-monitor-3c5318d843651dd18a6b8b0da67e3aaef810ca91.zip
phosphor-dbus-monitor-3c5318d843651dd18a6b8b0da67e3aaef810ca91.tar.gz
Add ElogWithMetaDataCapture class
This callback class will create an error log with exactly 1 metadata field, which takes a string. This metadata field will be filled in with the property paths, names, and values of the properties that passed the condition checks that caused the callback to be called in the first place. Tested: Ran with YAML rules that used this callback and checked that everything worked as specified. Change-Id: Ib37206c63385939c583a09e7ba979d6e016691f6 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
-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