blob: eec5679f03c0d59bcd4d70b55a517472c8218704 [file] [log] [blame]
Adriana Kobylakf855c3e2016-09-29 20:48:08 -05001#pragma once
Adriana Kobylakf855c3e2016-09-29 20:48:08 -05002#include <tuple>
3#include <utility>
Saqib Khan2bb15192017-02-13 13:19:55 -06004#include <phosphor-logging/log.hpp>
Marri Devender Rao7d0a07b2017-04-04 03:43:00 -05005#include <sdbusplus/exception.hpp>
Adriana Kobylakf855c3e2016-09-29 20:48:08 -05006namespace phosphor
7{
8
9namespace logging
10{
11
12/**
13 * @brief Structure used by callers to indicate they want to use the last value
14 * put in the journal for input parameter.
15*/
16template <typename T>
17struct prev_entry
18{
19 using type = T;
20};
21
22
23
24namespace details
25{
26/**
27 * @brief Used to return the generated tuple for the error code meta data
28 *
29 * The prev_entry (above) and deduce_entry_type structures below are used
30 * to verify at compile time the required parameters have been passed to
31 * the elog interface and then to forward on the appropriate tuple to the
32 * log interface.
33 */
34template <typename T>
35struct deduce_entry_type
36{
37
38 using type = T;
39 auto get() { return value._entry; }
40
41 T value;
42};
43
44/**
45 * @brief Used to return an empty tuple for prev_entry parameters
46 *
47 * This is done so we can still call the log() interface with the variable
48 * arg parameters to elog. The log() interface will simply ignore the empty
49 * tuples which is what we want for prev_entry parameters.
50 */
51template <typename T>
52struct deduce_entry_type<prev_entry<T>>
53{
54 using type = T;
55 auto get() { return std::make_tuple(); }
56
57 prev_entry<T> value;
58};
59
60/**
61 * @brief Typedef for above structure usage
62 */
63template <typename T> using deduce_entry_type_t =
64 typename deduce_entry_type<T>::type;
65
Andrew Geissler6d910ad2016-10-16 20:49:14 -050066/**
Deepak Kodihalli15331102017-03-09 23:50:43 -060067 * @brief Used to map an sdbusplus error to a phosphor-logging error type
Andrew Geissler6d910ad2016-10-16 20:49:14 -050068 *
Deepak Kodihalli15331102017-03-09 23:50:43 -060069 * Users log errors via the sdbusplus error name, and the execption that's
70 * thrown is the corresponding sdbusplus exception. However, there's a need
71 * to map the sdbusplus error name to the phosphor-logging error name, in order
72 * to verify the error metadata at compile-time.
Andrew Geissler6d910ad2016-10-16 20:49:14 -050073 */
Deepak Kodihalli15331102017-03-09 23:50:43 -060074template <typename T>
75struct map_exception_type
Andrew Geissler6d910ad2016-10-16 20:49:14 -050076{
Deepak Kodihalli15331102017-03-09 23:50:43 -060077 using type = T;
Andrew Geissler6d910ad2016-10-16 20:49:14 -050078};
79
Deepak Kodihalli15331102017-03-09 23:50:43 -060080/**
81 * @brief Typedef for above structure usage
82 */
83template <typename T> using map_exception_type_t =
84 typename map_exception_type<T>::type;
85
Marri Devender Rao7d0a07b2017-04-04 03:43:00 -050086/** @fn commit()
87 * @brief Create an error log entry based on journal
88 * entry with a specified exception name
89 * @param[in] name - name of the error exception
90 */
91void commit(const char* name);
92
Deepak Kodihalli15331102017-03-09 23:50:43 -060093} // namespace details
94
Adriana Kobylakf855c3e2016-09-29 20:48:08 -050095/** @fn commit()
Marri Devender Rao7d0a07b2017-04-04 03:43:00 -050096 * \deprecated use commit<T>()
97 * @brief Create an error log entry based on journal
98 * entry with a specified MSG_ID
99 * @param[in] name - name of the error exception
100 */
101void commit(std::string&& name);
102
103/** @fn commit()
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500104 * @brief Create an error log entry based on journal
105 * entry with a specified MSG_ID
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500106 */
Marri Devender Rao7d0a07b2017-04-04 03:43:00 -0500107template <typename T>
108void commit()
109{
110 // Validate if the exception is derived from sdbusplus::exception.
111 static_assert(
112 std::is_base_of<sdbusplus::exception::exception, T>::value,
113 "T must be a descendant of sdbusplus::exception::exception"
114 );
115 details::commit(details::map_exception_type_t<T>::errName);
116}
117
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500118
119/** @fn elog()
120 * @brief Create a journal log entry based on predefined
121 * error log information
122 * @tparam T - Error log type
123 * @param[in] i_args - Metadata fields to be added to the journal entry
124 */
125template <typename T, typename ...Args>
126void elog(Args... i_args)
127{
Marri Devender Rao7d0a07b2017-04-04 03:43:00 -0500128 // Validate if the exception is derived from sdbusplus::exception.
129 static_assert(
130 std::is_base_of<sdbusplus::exception::exception, T>::value,
131 "T must be a descendant of sdbusplus::exception::exception"
132 );
133
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500134 // Validate the caller passed in the required parameters
Deepak Kodihalli15331102017-03-09 23:50:43 -0600135 static_assert(std::is_same<typename details::
136 map_exception_type_t<T>::metadata_types,
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500137 std::tuple<
138 details::deduce_entry_type_t<Args>...>>
139 ::value,
140 "You are not passing in required arguments for this error");
141
Deepak Kodihalli15331102017-03-09 23:50:43 -0600142 log<details::map_exception_type_t<T>::L>(
Marri Devender Rao7d0a07b2017-04-04 03:43:00 -0500143 T::errDesc,
Deepak Kodihalli15331102017-03-09 23:50:43 -0600144 details::deduce_entry_type<Args>{i_args}.get()...);
Andrew Geissler6d910ad2016-10-16 20:49:14 -0500145
146 // Now throw an exception for this error
Deepak Kodihalli15331102017-03-09 23:50:43 -0600147 throw T();
Adriana Kobylakf855c3e2016-09-29 20:48:08 -0500148}
149
150} // namespace logging
151
152} // namespace phosphor
153