blob: 996fd58395ee0532c45427c3ee278bd57b7222d5 [file] [log] [blame]
Gunnar Mills9679d432017-08-03 15:54:43 -05001#pragma once
2#include <phosphor-logging/elog-errors.hpp>
3#include <phosphor-logging/elog.hpp>
4#include "callback.hpp"
5#include <sdbusplus/exception.hpp>
Gunnar Mills30474cf2017-08-11 09:38:54 -05006#include <experimental/tuple>
Gunnar Mills9679d432017-08-03 15:54:43 -05007
8namespace phosphor
9{
10namespace dbus
11{
12namespace monitoring
13{
14
Matt Spinler3c5318d2018-02-19 14:03:05 -060015/** @struct ToString
16 * @brief Convert numbers to strings
17 */
18template <typename T> struct ToString
19{
20 static auto op(T&& value)
21 {
22 return std::to_string(std::forward<T>(value));
23 }
24};
25
26template <> struct ToString<std::string>
27{
28 static auto op(const std::string& value)
29 {
30 return value;
31 }
32};
33
Gunnar Mills9679d432017-08-03 15:54:43 -050034/** @class ElogBase
35 * @brief Elog callback implementation.
36 *
37 * The elog callback logs the elog and
38 * elog metadata.
39 */
40class ElogBase : public Callback
41{
Brad Bishopd1eac882018-03-29 10:34:05 -040042 public:
43 ElogBase(const ElogBase&) = delete;
44 ElogBase(ElogBase&&) = default;
45 ElogBase& operator=(const ElogBase&) = delete;
46 ElogBase& operator=(ElogBase&&) = default;
47 virtual ~ElogBase() = default;
48 ElogBase() : Callback()
49 {
50 }
Gunnar Mills9679d432017-08-03 15:54:43 -050051
Brad Bishopd1eac882018-03-29 10:34:05 -040052 /** @brief Callback interface implementation. */
53 void operator()(Context ctx) override;
Gunnar Mills9679d432017-08-03 15:54:43 -050054
Brad Bishopd1eac882018-03-29 10:34:05 -040055 private:
56 /** @brief Delegate type specific calls to subclasses. */
57 virtual void log() const = 0;
Gunnar Mills9679d432017-08-03 15:54:43 -050058};
59
Gunnar Mills30474cf2017-08-11 09:38:54 -050060namespace detail
61{
62
63/** @class CallElog
64 * @brief Provide explicit call forwarding to phosphor::logging::report.
65 *
66 * @tparam T - Error log type
67 * @tparam Args - Metadata fields types.
68 */
Brad Bishopd1eac882018-03-29 10:34:05 -040069template <typename T, typename... Args> struct CallElog
Gunnar Mills30474cf2017-08-11 09:38:54 -050070{
Brad Bishopd1eac882018-03-29 10:34:05 -040071 static void op(Args&&... args)
Gunnar Mills30474cf2017-08-11 09:38:54 -050072 {
73 phosphor::logging::report<T>(std::forward<Args>(args)...);
74 }
75};
76
77} // namespace detail
Gunnar Mills9679d432017-08-03 15:54:43 -050078
79/** @class Elog
80 * @brief C++ type specific logic for the elog callback.
Gunnar Mills30474cf2017-08-11 09:38:54 -050081 * The elog callback logs the elog and elog metadata.
Gunnar Mills9679d432017-08-03 15:54:43 -050082 *
83 * @tparam T - Error log type
Gunnar Mills30474cf2017-08-11 09:38:54 -050084 * @tparam Args - Metadata fields types.
85 * @param[in] arguments - Metadata fields to be added to the error log
Gunnar Mills9679d432017-08-03 15:54:43 -050086 */
Brad Bishopd1eac882018-03-29 10:34:05 -040087template <typename T, typename... Args> class Elog : public ElogBase
Gunnar Mills9679d432017-08-03 15:54:43 -050088{
Brad Bishopd1eac882018-03-29 10:34:05 -040089 public:
90 Elog(const Elog&) = delete;
91 Elog(Elog&&) = default;
92 Elog& operator=(const Elog&) = delete;
93 Elog& operator=(Elog&&) = default;
94 ~Elog() = default;
95 Elog(Args&&... arguments) :
96 ElogBase(), args(std::forward<Args>(arguments)...)
97 {
98 }
Gunnar Mills9679d432017-08-03 15:54:43 -050099
Brad Bishopd1eac882018-03-29 10:34:05 -0400100 private:
101 /** @brief elog interface implementation. */
102 void log() const override
103 {
104 std::experimental::apply(detail::CallElog<T, Args...>::op,
105 std::tuple_cat(args));
106 }
107 std::tuple<Args...> args;
Gunnar Mills9679d432017-08-03 15:54:43 -0500108};
109
Matt Spinler3c5318d2018-02-19 14:03:05 -0600110/**
111 * @class ElogWithMetadataCapture
112 *
113 * @brief A callback class that will save the paths, names, and
114 * current values of certain properties in the metadata of the
115 * error log it creates.
116 *
117 * The intended use case of this class is to create an error log with
118 * metadata that includes the property names and values that caused
119 * the condition to issue this callback. When the condition ran, it had
120 * set the pass/fail field on each property it checked in the properties'
121 * entries in the Storage array. This class then looks at those pass/fail
122 * fields to see which properties to log.
123 *
124 * Note that it's OK if different conditions and callbacks share the same
125 * properties because everything runs serially, so another condition can't
126 * touch those pass/fail fields until all of the first condition's callbacks
127 * are done.
128 *
129 * This class requires that the error log created only have 1 metadata field,
130 * and it must take a string.
131 *
132 * @tparam errorType - Error log type
133 * @tparam metadataType - The metadata to use
134 * @tparam propertyType - The data type of the captured properties
135 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400136template <typename errorType, typename metadataType, typename propertyType>
Matt Spinler3c5318d2018-02-19 14:03:05 -0600137class ElogWithMetadataCapture : public IndexedCallback
138{
Brad Bishopd1eac882018-03-29 10:34:05 -0400139 public:
140 ElogWithMetadataCapture() = delete;
141 ElogWithMetadataCapture(const ElogWithMetadataCapture&) = delete;
142 ElogWithMetadataCapture(ElogWithMetadataCapture&&) = default;
143 ElogWithMetadataCapture& operator=(const ElogWithMetadataCapture&) = delete;
144 ElogWithMetadataCapture& operator=(ElogWithMetadataCapture&&) = default;
145 virtual ~ElogWithMetadataCapture() = default;
146 explicit ElogWithMetadataCapture(const PropertyIndex& index) :
147 IndexedCallback(index)
148 {
149 }
Matt Spinler3c5318d2018-02-19 14:03:05 -0600150
Brad Bishopd1eac882018-03-29 10:34:05 -0400151 /**
152 * @brief Callback interface implementation that
153 * creates an error log
154 */
155 void operator()(Context ctx) override
156 {
157 auto data = captureMetadata();
158
159 phosphor::logging::report<errorType>(metadataType(data.c_str()));
160 }
161
162 private:
163 /**
164 * @brief Builds a metadata string with property information
165 *
166 * Finds all of the properties in the index that have
167 * their condition pass/fail fields (get<resultIndex>(storage))
168 * set to true, and then packs those paths, names, and values
169 * into a metadata string that looks like:
170 *
171 * |path1:name1=value1|path2:name2=value2|...
172 *
173 * @return The metadata string
174 */
175 std::string captureMetadata()
176 {
177 std::string metadata{'|'};
178
179 for (const auto& n : index)
Matt Spinler3c5318d2018-02-19 14:03:05 -0600180 {
Brad Bishopd1eac882018-03-29 10:34:05 -0400181 const auto& storage = std::get<storageIndex>(n.second).get();
182 const auto& result = std::get<resultIndex>(storage);
Matt Spinler3c5318d2018-02-19 14:03:05 -0600183
Brad Bishopd1eac882018-03-29 10:34:05 -0400184 if (!result.empty() && any_ns::any_cast<bool>(result))
185 {
186 const auto& path = std::get<pathIndex>(n.first).get();
187 const auto& propertyName =
188 std::get<propertyIndex>(n.first).get();
189 auto value =
190 ToString<propertyType>::op(any_ns::any_cast<propertyType>(
191 std::get<valueIndex>(storage)));
192
193 metadata += path + ":" + propertyName + '=' + value + '|';
194 }
Matt Spinler3c5318d2018-02-19 14:03:05 -0600195 }
196
Brad Bishopd1eac882018-03-29 10:34:05 -0400197 return metadata;
198 };
Matt Spinler3c5318d2018-02-19 14:03:05 -0600199};
200
Gunnar Mills30474cf2017-08-11 09:38:54 -0500201/** @brief Argument type deduction for constructing Elog instances.
202 *
203 * @tparam T - Error log type
204 * @tparam Args - Metadata fields types.
205 * @param[in] arguments - Metadata fields to be added to the error log
206 */
Brad Bishopd1eac882018-03-29 10:34:05 -0400207template <typename T, typename... Args> auto makeElog(Args&&... arguments)
Gunnar Mills30474cf2017-08-11 09:38:54 -0500208{
Brad Bishopd1eac882018-03-29 10:34:05 -0400209 return std::make_unique<Elog<T, Args...>>(std::forward<Args>(arguments)...);
Gunnar Mills30474cf2017-08-11 09:38:54 -0500210}
211
Gunnar Mills9679d432017-08-03 15:54:43 -0500212} // namespace monitoring
213} // namespace dbus
214} // namespace phosphor