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