1 #pragma once
2 #include <phosphor-logging/elog-errors.hpp>
3 #include <phosphor-logging/elog.hpp>
4 #include "callback.hpp"
5 #include <sdbusplus/exception.hpp>
6 #include <experimental/tuple>
7 
8 namespace phosphor
9 {
10 namespace dbus
11 {
12 namespace monitoring
13 {
14 
15 /** @class ElogBase
16  *  @brief Elog callback implementation.
17  *
18  *  The elog callback logs the elog and
19  *  elog metadata.
20  */
21 class ElogBase : public Callback
22 {
23     public:
24         ElogBase(const ElogBase&) = delete;
25         ElogBase(ElogBase&&) = default;
26         ElogBase& operator=(const ElogBase&) = delete;
27         ElogBase& operator=(ElogBase&&) = default;
28         virtual ~ElogBase() = default;
29         ElogBase() :
30             Callback() {}
31 
32         /** @brief Callback interface implementation. */
33         void operator()() override;
34 
35     private:
36         /** @brief Delegate type specific calls to subclasses. */
37         virtual void log() const = 0;
38 };
39 
40 namespace detail
41 {
42 
43 /** @class CallElog
44  *  @brief Provide explicit call forwarding to phosphor::logging::report.
45  *
46  *  @tparam T - Error log type
47  *  @tparam Args - Metadata fields types.
48  */
49 template <typename T, typename ...Args>
50 struct CallElog
51 {
52     static void op(Args&& ...args)
53     {
54         phosphor::logging::report<T>(std::forward<Args>(args)...);
55     }
56 };
57 
58 } // namespace detail
59 
60 /** @class Elog
61  *  @brief C++ type specific logic for the elog callback.
62  *         The elog callback logs the elog and elog metadata.
63  *
64  *  @tparam T - Error log type
65  *  @tparam Args - Metadata fields types.
66  *  @param[in] arguments - Metadata fields to be added to the error log
67  */
68 template <typename T, typename ...Args>
69 class Elog : public ElogBase
70 {
71     public:
72         Elog(const Elog&) = delete;
73         Elog(Elog&&) = default;
74         Elog& operator=(const Elog&) = delete;
75         Elog& operator=(Elog&&) = default;
76         ~Elog() = default;
77         Elog(Args&& ... arguments) :
78             ElogBase(), args(std::forward<Args>(arguments)...) {}
79 
80     private:
81         /** @brief elog interface implementation. */
82         void log() const override
83         {
84             std::experimental::apply(
85                 detail::CallElog<T, Args...>::op,
86                 std::tuple_cat(args));
87         }
88         std::tuple<Args...> args;
89 
90 };
91 
92 /** @brief Argument type deduction for constructing Elog instances.
93  *
94  *  @tparam T - Error log type
95  *  @tparam Args - Metadata fields types.
96  *  @param[in] arguments - Metadata fields to be added to the error log
97  */
98 template <typename T, typename ...Args>
99 auto makeElog(Args&& ... arguments)
100 {
101     return std::make_unique<Elog<T, Args...>>(
102                std::forward<Args>(arguments)...);
103 }
104 
105 } // namespace monitoring
106 } // namespace dbus
107 } // namespace phosphor
108