summaryrefslogtreecommitdiffstats
path: root/src/elog.hpp
blob: c3b0d02a73c5c358de5fc07bf13678b8f88df237 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#pragma once
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include "callback.hpp"
#include <sdbusplus/exception.hpp>
#include <experimental/tuple>

namespace phosphor
{
namespace dbus
{
namespace monitoring
{

/** @class ElogBase
 *  @brief Elog callback implementation.
 *
 *  The elog callback logs the elog and
 *  elog metadata.
 */
class ElogBase : public Callback
{
    public:
        ElogBase(const ElogBase&) = delete;
        ElogBase(ElogBase&&) = default;
        ElogBase& operator=(const ElogBase&) = delete;
        ElogBase& operator=(ElogBase&&) = default;
        virtual ~ElogBase() = default;
        ElogBase() :
            Callback() {}

        /** @brief Callback interface implementation. */
        void operator()(Context ctx) override;

    private:
        /** @brief Delegate type specific calls to subclasses. */
        virtual void log() const = 0;
};

namespace detail
{

/** @class CallElog
 *  @brief Provide explicit call forwarding to phosphor::logging::report.
 *
 *  @tparam T - Error log type
 *  @tparam Args - Metadata fields types.
 */
template <typename T, typename ...Args>
struct CallElog
{
    static void op(Args&& ...args)
    {
        phosphor::logging::report<T>(std::forward<Args>(args)...);
    }
};

} // namespace detail

/** @class Elog
 *  @brief C++ type specific logic for the elog callback.
 *         The elog callback logs the elog and elog metadata.
 *
 *  @tparam T - Error log type
 *  @tparam Args - Metadata fields types.
 *  @param[in] arguments - Metadata fields to be added to the error log
 */
template <typename T, typename ...Args>
class Elog : public ElogBase
{
    public:
        Elog(const Elog&) = delete;
        Elog(Elog&&) = default;
        Elog& operator=(const Elog&) = delete;
        Elog& operator=(Elog&&) = default;
        ~Elog() = default;
        Elog(Args&& ... arguments) :
            ElogBase(), args(std::forward<Args>(arguments)...) {}

    private:
        /** @brief elog interface implementation. */
        void log() const override
        {
            std::experimental::apply(
                detail::CallElog<T, Args...>::op,
                std::tuple_cat(args));
        }
        std::tuple<Args...> args;

};

/** @brief Argument type deduction for constructing Elog instances.
 *
 *  @tparam T - Error log type
 *  @tparam Args - Metadata fields types.
 *  @param[in] arguments - Metadata fields to be added to the error log
 */
template <typename T, typename ...Args>
auto makeElog(Args&& ... arguments)
{
    return std::make_unique<Elog<T, Args...>>(
               std::forward<Args>(arguments)...);
}

} // namespace monitoring
} // namespace dbus
} // namespace phosphor
OpenPOWER on IntegriCloud