summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am4
-rw-r--r--src/callback.hpp57
-rw-r--r--src/example/example.yaml21
-rw-r--r--src/journal.cpp46
-rw-r--r--src/journal.hpp90
-rwxr-xr-xsrc/pdmgen.py28
-rw-r--r--src/propertywatchimpl.hpp6
-rw-r--r--src/templates/generated.mako.hpp29
-rw-r--r--src/templates/journal.mako.cpp3
9 files changed, 273 insertions, 11 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3b4d9cf..f223713 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,6 +7,7 @@ sbin_PROGRAMS = phosphor-dbus-monitor
phosphor_dbus_monitor_SOURCES = \
functor.cpp \
+ journal.cpp \
main.cpp \
monitor.cpp \
propertywatch.cpp
@@ -21,7 +22,8 @@ BUILT_SOURCES = generated.hpp
CLEANFILES = generated.hpp
TEMPLATES = \
- templates/generated.mako.hpp
+ templates/generated.mako.hpp \
+ templates/journal.mako.cpp
generated.hpp: $(PDMGEN) $(YAML_PATH) $(TEMPLATES)
$(AM_V_GEN)$(PYTHON) ${PDMGEN} \
diff --git a/src/callback.hpp b/src/callback.hpp
new file mode 100644
index 0000000..d7a678c
--- /dev/null
+++ b/src/callback.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "data_types.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+/** @class Callback
+ * @brief Callback interface.
+ *
+ * Callbacks of any type can be run.
+ */
+class Callback
+{
+ public:
+ Callback() = default;
+ Callback(const Callback&) = delete;
+ Callback(Callback&&) = default;
+ Callback& operator=(const Callback&) = delete;
+ Callback& operator=(Callback&&) = default;
+ virtual ~Callback() = default;
+
+ /** @brief Run the callback. */
+ virtual void operator()() = 0;
+};
+
+/** @class IndexedCallback
+ * @brief Callback with an index.
+ */
+class IndexedCallback : public Callback
+{
+ public:
+ IndexedCallback() = delete;
+ IndexedCallback(const IndexedCallback&) = delete;
+ IndexedCallback(IndexedCallback&&) = default;
+ IndexedCallback& operator=(const IndexedCallback&) = delete;
+ IndexedCallback& operator=(IndexedCallback&&) = default;
+ virtual ~IndexedCallback() = default;
+ explicit IndexedCallback(const PropertyIndex& callbackIndex)
+ : Callback(), index(callbackIndex) {}
+
+ /** @brief Run the callback. */
+ virtual void operator()() override = 0;
+
+ protected:
+
+ /** @brief Property names and their associated storage. */
+ const PropertyIndex& index;
+};
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/example/example.yaml b/src/example/example.yaml
index 4e216cd..171aeaa 100644
--- a/src/example/example.yaml
+++ b/src/example/example.yaml
@@ -53,3 +53,24 @@
watch: property
paths: example path group
properties: example property group
+
+- name: example journal callback
+ description: >
+ 'Callbacks are actions PDM should take when instructed to do so.
+
+ Some callback types refer to a group of paths and group of properties
+ in a similar fashion as the property watch directive.
+
+ The journal callback logs the specified message to the systemd journal
+ with the specified severity.
+
+ Additionally, the journal callback will add to the journal key value
+ pair metadata for each property in the specified property group with
+ the key being the property element metadata and the value being the
+ property value.'
+ class: callback
+ callback: journal
+ paths: example path group
+ properties: example property group
+ severity: INFO
+ message: Hello world from PDM!
diff --git a/src/journal.cpp b/src/journal.cpp
new file mode 100644
index 0000000..46f74e9
--- /dev/null
+++ b/src/journal.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2017 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "journal.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+void JournalBase::operator()()
+{
+ for (const auto& n : index)
+ {
+ const auto& path = std::get<0>(n.first);
+ const auto& pathMeta = std::get<0>(n.second);
+ const auto& propertyMeta = std::get<1>(n.second);
+ const auto& value = std::get<2>(n.second);
+
+ if (!value.get().empty())
+ {
+ log(message,
+ pathMeta,
+ path,
+ propertyMeta,
+ value);
+ }
+ }
+}
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/journal.hpp b/src/journal.hpp
new file mode 100644
index 0000000..4e47670
--- /dev/null
+++ b/src/journal.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include <phosphor-logging/log.hpp>
+#include "callback.hpp"
+#include "format.hpp"
+
+namespace phosphor
+{
+namespace dbus
+{
+namespace monitoring
+{
+
+/** @class JournalBase
+ * @brief Journal callback implementation.
+ *
+ * The journal callback logs the client message and
+ * journal metadata key value pairs as specified by the
+ * client supplied property index.
+ */
+class JournalBase : public IndexedCallback
+{
+ public:
+ JournalBase() = delete;
+ JournalBase(const JournalBase&) = delete;
+ JournalBase(JournalBase&&) = default;
+ JournalBase& operator=(const JournalBase&) = delete;
+ JournalBase& operator=(JournalBase&&) = default;
+ virtual ~JournalBase() = default;
+ JournalBase(const char* msg, const PropertyIndex& index) :
+ IndexedCallback(index), message(msg) {}
+
+ /** @brief Callback interface implementation. */
+ void operator()() override;
+
+ private:
+ /** @brief Delegate type specific calls to subclasses. */
+ virtual void log(
+ const char* message,
+ const std::string& pathMeta,
+ const std::string& path,
+ const std::string& propertyMeta,
+ const any_ns::any& value) const = 0;
+
+ /** @brief The client provided message to be traced. */
+ const char* message;
+};
+
+/** @class Journal
+ * @brief C++ type specific logic for the journal callback.
+ *
+ * @tparam T - The C++ type of the property values being traced.
+ * @tparam Severity - The log severity of the log entry.
+ */
+template <typename T, phosphor::logging::level Severity>
+class Journal : public JournalBase
+{
+ public:
+ Journal() = delete;
+ Journal(const Journal&) = delete;
+ Journal(Journal&&) = default;
+ Journal& operator=(const Journal&) = delete;
+ Journal& operator=(Journal&&) = default;
+ ~Journal() = default;
+ Journal(const char* msg, const PropertyIndex& index) :
+ JournalBase(msg, index) {}
+
+ private:
+ /** @brief log interface implementation. */
+ void log(
+ const char* message,
+ const std::string& pathMeta,
+ const std::string& path,
+ const std::string& propertyMeta,
+ const any_ns::any& value) const override
+ {
+ phosphor::logging::log<Severity>(
+ message,
+ phosphor::logging::entry(
+ pathMeta + GetFormat<decltype(pathMeta)>::format,
+ path),
+ phosphor::logging::entry(
+ propertyMeta + GetFormat<T>::format,
+ any_ns::any_cast<T>(value)));
+ }
+};
+
+} // namespace monitoring
+} // namespace dbus
+} // namespace phosphor
diff --git a/src/pdmgen.py b/src/pdmgen.py
index 070c118..e4a97e7 100755
--- a/src/pdmgen.py
+++ b/src/pdmgen.py
@@ -413,6 +413,29 @@ class PropertyWatch(HasPropertyIndex):
super(PropertyWatch, self).__init__(**kw)
+class Callback(HasPropertyIndex):
+ '''Interface and common logic for callbacks.'''
+
+ def __init__(self, *a, **kw):
+ super(Callback, self).__init__(**kw)
+
+
+class Journal(Callback, Renderer):
+ '''Handle the journal callback config file directive.'''
+
+ def __init__(self, *a, **kw):
+ self.severity = kw.pop('severity')
+ self.message = kw.pop('message')
+ super(Journal, self).__init__(**kw)
+
+ def construct(self, loader, indent):
+ return self.render(
+ loader,
+ 'journal.mako.cpp',
+ c=self,
+ indent=indent)
+
+
class Everything(Renderer):
'''Parse/render entry point.'''
@@ -440,6 +463,9 @@ class Everything(Renderer):
'instance': {
'element': Instance,
},
+ 'callback': {
+ 'journal': Journal,
+ },
}
if cls not in class_map:
@@ -529,6 +555,7 @@ class Everything(Renderer):
self.instances = kw.pop('instance', [])
self.instancegroups = kw.pop('instancegroup', [])
self.watches = kw.pop('watch', [])
+ self.callbacks = kw.pop('callback', [])
super(Everything, self).__init__(**kw)
@@ -550,6 +577,7 @@ class Everything(Renderer):
instances=self.instances,
watches=self.watches,
instancegroups=self.instancegroups,
+ callbacks=self.callbacks,
indent=Indent()))
if __name__ == '__main__':
diff --git a/src/propertywatchimpl.hpp b/src/propertywatchimpl.hpp
index 46799ed..6e957ae 100644
--- a/src/propertywatchimpl.hpp
+++ b/src/propertywatchimpl.hpp
@@ -32,10 +32,6 @@ void PropertyWatch<DBusInterfaceType>::start()
{
return;
}
- else
- {
- alreadyRan = true;
- }
// The index has a flat layout which is not optimal here. Nest
// properties in a map of interface names in a map of object paths.
@@ -107,6 +103,8 @@ void PropertyWatch<DBusInterfaceType>::start()
}
}
}
+
+ alreadyRan = true;
}
template <typename T, typename DBusInterfaceType>
diff --git a/src/templates/generated.mako.hpp b/src/templates/generated.mako.hpp
index 0911e3a..61c2b6f 100644
--- a/src/templates/generated.mako.hpp
+++ b/src/templates/generated.mako.hpp
@@ -5,6 +5,7 @@
#include <array>
#include <string>
#include "data_types.hpp"
+#include "journal.hpp"
#include "propertywatchimpl.hpp"
#include "sdbusplus.hpp"
@@ -107,15 +108,15 @@ struct ConfigPropertyIndicies
{
PropertyIndex::key_type
{
- ConfigPaths::get()[${i[0]}],
- ConfigInterfaces::get()[${i[2]}],
- ConfigProperties::get()[${i[3]}]
+ std::cref(ConfigPaths::get()[${i[0]}]),
+ std::cref(ConfigInterfaces::get()[${i[2]}]),
+ std::cref(ConfigProperties::get()[${i[3]}])
},
PropertyIndex::mapped_type
{
- ConfigMeta::get()[${i[1]}],
- ConfigMeta::get()[${i[4]}],
- ConfigPropertyStorage::get()[${i[5]}]
+ std::cref(ConfigMeta::get()[${i[1]}]),
+ std::cref(ConfigMeta::get()[${i[4]}]),
+ std::ref(ConfigPropertyStorage::get()[${i[5]}])
},
},
% endfor
@@ -127,6 +128,22 @@ struct ConfigPropertyIndicies
}
};
+struct ConfigPropertyCallbacks
+{
+ using Callbacks = std::array<std::unique_ptr<Callback>, ${len(callbacks)}>;
+
+ static auto& get()
+ {
+ static const Callbacks propertyCallbacks =
+ {
+% for c in callbacks:
+ ${c.construct(loader, indent=indent +3)},
+% endfor
+ };
+ return propertyCallbacks;
+ }
+};
+
struct ConfigPropertyWatches
{
using PropertyWatches = std::array<std::unique_ptr<Watch>, ${len(watches)}>;
diff --git a/src/templates/journal.mako.cpp b/src/templates/journal.mako.cpp
new file mode 100644
index 0000000..787337d
--- /dev/null
+++ b/src/templates/journal.mako.cpp
@@ -0,0 +1,3 @@
+std::make_unique<Journal<${c.datatype}, phosphor::logging::level::${c.severity}>>(
+${indent(1)}"${c.message}",
+${indent(1)}ConfigPropertyIndicies::get()[${c.instances}])\
OpenPOWER on IntegriCloud