blob: fe79bdc49cc2783035dbaa54310b5c53a57d746c [file] [log] [blame]
Adriana Kobylakf855c3e2016-09-29 20:48:08 -05001#pragma once
2
3#include <tuple>
4#include <utility>
Saqib Khan2bb15192017-02-13 13:19:55 -06005#include <phosphor-logging/log.hpp>
Adriana Kobylakebd59fa2017-02-06 20:55:39 -06006#include <phosphor-logging/elog-errors.hpp>
Adriana Kobylakf855c3e2016-09-29 20:48:08 -05007
8namespace phosphor
9{
10
11namespace logging
12{
13
14/**
15 * @brief Structure used by callers to indicate they want to use the last value
16 * put in the journal for input parameter.
17*/
18template <typename T>
19struct prev_entry
20{
21 using type = T;
22};
23
24
25
26namespace details
27{
28/**
29 * @brief Used to return the generated tuple for the error code meta data
30 *
31 * The prev_entry (above) and deduce_entry_type structures below are used
32 * to verify at compile time the required parameters have been passed to
33 * the elog interface and then to forward on the appropriate tuple to the
34 * log interface.
35 */
36template <typename T>
37struct deduce_entry_type
38{
39
40 using type = T;
41 auto get() { return value._entry; }
42
43 T value;
44};
45
46/**
47 * @brief Used to return an empty tuple for prev_entry parameters
48 *
49 * This is done so we can still call the log() interface with the variable
50 * arg parameters to elog. The log() interface will simply ignore the empty
51 * tuples which is what we want for prev_entry parameters.
52 */
53template <typename T>
54struct deduce_entry_type<prev_entry<T>>
55{
56 using type = T;
57 auto get() { return std::make_tuple(); }
58
59 prev_entry<T> value;
60};
61
62/**
63 * @brief Typedef for above structure usage
64 */
65template <typename T> using deduce_entry_type_t =
66 typename deduce_entry_type<T>::type;
67
68} // namespace details
69
Andrew Geissler6d910ad2016-10-16 20:49:14 -050070/**
71 * @brief Error log exception base class
72 *
73 * This allows people to capture all error log exceptions if desired
74 */
75class elogExceptionBase : public std::exception {};
76
77/**
78 * @brief Error log exception class
79 *
80 * This is for capturing specific error log exceptions
81 */
82template <typename T> class elogException : public elogExceptionBase
83{
Adriana Kobylak205b1132017-02-06 20:15:29 -060084 public:
85 const char* what() const noexcept override { return T::err_code; }
86 const char* name() const noexcept { return T::err_code; }
Andrew Geissler6d910ad2016-10-16 20:49:14 -050087};
88
Adriana Kobylakf855c3e2016-09-29 20:48:08 -050089/** @fn commit()
90 * @brief Create an error log entry based on journal
91 * entry with a specified MSG_ID
Adriana Kobylak205b1132017-02-06 20:15:29 -060092 * @param[in] - Exception name
Adriana Kobylakf855c3e2016-09-29 20:48:08 -050093 */
Adriana Kobylak205b1132017-02-06 20:15:29 -060094void commit(std::string&& name);
Adriana Kobylakf855c3e2016-09-29 20:48:08 -050095
96/** @fn elog()
97 * @brief Create a journal log entry based on predefined
98 * error log information
99 * @tparam T - Error log type
100 * @param[in] i_args - Metadata fields to be added to the journal entry
101 */
102template <typename T, typename ...Args>
103void elog(Args... i_args)
104{
105 // Validate the caller passed in the required parameters
106 static_assert(std::is_same<typename T::metadata_types,
107 std::tuple<
108 details::deduce_entry_type_t<Args>...>>
109 ::value,
110 "You are not passing in required arguments for this error");
111
112 log<T::L>(T::err_msg,
113 details::deduce_entry_type<Args>{i_args}.get()...);
Andrew Geissler6d910ad2016-10-16 20:49:14 -0500114
115 // Now throw an exception for this error
116 throw elogException<T>();
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500117}
118
119} // namespace logging
120
121} // namespace phosphor
122