blob: 4c826ac082782da18ba92ffee35c33ea80a92357 [file] [log] [blame]
Adriana Kobylak91da4532016-07-20 12:42:55 -05001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
Patrick Venturef18bf832018-10-26 18:14:00 -070019#include <systemd/sd-journal.h>
20
Patrick Venture59a6b1f2018-08-29 11:41:01 -070021#include <phosphor-logging/sdjournal.hpp>
Patrick Venturef18bf832018-10-26 18:14:00 -070022#include <sdbusplus/server/transaction.hpp>
Adriana Kobylak91da4532016-07-20 12:42:55 -050023#include <tuple>
Joseph Reynolds8f6f7fc2018-05-04 10:11:00 -050024#include <type_traits>
Adriana Kobylak91da4532016-07-20 12:42:55 -050025
26namespace phosphor
27{
28
29namespace logging
30{
31
32/** @enum level
33 * @brief Enum for priority level
34 */
35enum class level
36{
Patrick Venturef18bf832018-10-26 18:14:00 -070037 EMERG = LOG_EMERG,
38 ALERT = LOG_ALERT,
39 CRIT = LOG_CRIT,
40 ERR = LOG_ERR,
Adriana Kobylak91da4532016-07-20 12:42:55 -050041 WARNING = LOG_WARNING,
Patrick Venturef18bf832018-10-26 18:14:00 -070042 NOTICE = LOG_NOTICE,
43 INFO = LOG_INFO,
44 DEBUG = LOG_DEBUG,
Adriana Kobylak91da4532016-07-20 12:42:55 -050045};
46
Adriana Kobylak91da4532016-07-20 12:42:55 -050047namespace details
48{
49
50/** @fn prio()
51 * @brief Prepend PRIORITY= to the input priority string.
52 * This is required by sd_journal_send().
53 * @tparam L - Priority level
54 */
55template <level L>
56constexpr auto prio()
57{
Patrick Venturef18bf832018-10-26 18:14:00 -070058 constexpr const char* prio_str = "PRIORITY=%d";
Adriana Kobylak91da4532016-07-20 12:42:55 -050059 constexpr const auto prio_tuple = std::make_tuple(prio_str, L);
60 return prio_tuple;
61}
62
63/** @fn helper_log()
64 * @brief Helper function for details::log(). Log request to journal.
65 * @tparam T - Type of tuple
66 * @tparam I - std::integer_sequence of indexes (0..N) for each tuple element
67 * @param[in] e - Tuple containing the data to be logged
68 * @param[unnamed] - std::integer_sequence of tuple's index values
69 */
Patrick Venturef18bf832018-10-26 18:14:00 -070070template <typename T, size_t... I>
Adriana Kobylak91da4532016-07-20 12:42:55 -050071void helper_log(T&& e, std::integer_sequence<size_t, I...>)
72{
Andrew Geissler328889d2016-10-10 12:43:48 -050073 // https://www.freedesktop.org/software/systemd/man/sd_journal_print.html
Patrick Venture3f9cb092019-01-03 14:31:09 -080074 // TODO: Re-enable call through interface for testing (or move the code
75 // into the body of the object).
76 sd_journal_send(std::get<I>(std::forward<T>(e))..., NULL);
Adriana Kobylak91da4532016-07-20 12:42:55 -050077}
78
79/** @fn details::log()
80 * @brief Implementation of logging::log() function.
81 * Send request msg and size to helper funct to log it to the journal.
82 * @tparam T - Type of tuple
83 * @param[in] e - Tuple containing the data to be logged
84 */
85template <typename T>
86void log(T&& e)
87{
88 constexpr auto e_size = std::tuple_size<std::decay_t<T>>::value;
89 helper_log(std::forward<T>(e), std::make_index_sequence<e_size>{});
90}
91
92} // namespace details
93
William A. Kennington III3b818462019-07-12 16:04:59 -070094template <class T>
95struct is_char_ptr_argtype
96 : std::integral_constant<
97 bool,
98 (std::is_pointer<typename std::decay<T>::type>::value &&
99 std::is_same<typename std::remove_cv<typename std::remove_pointer<
100 typename std::decay<T>::type>::type>::type,
101 char>::value)>
102{
103};
104
105template <class T>
106struct is_printf_argtype
107 : std::integral_constant<
108 bool,
109 (std::is_integral<typename std::remove_reference<T>::type>::value ||
110 std::is_enum<typename std::remove_reference<T>::type>::value ||
111 std::is_floating_point<
112 typename std::remove_reference<T>::type>::value ||
113 std::is_pointer<typename std::decay<T>::type>::value)>
114{
115};
116
117template <bool...>
118struct bool_pack;
119
120template <bool... bs>
121using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
122
123/** @fn entry()
124 * @brief Pack each format string entry as a tuple to be able to validate
125 * the string and parameters when multiple entries are passed to be logged.
126 * @tparam Arg - Types of first argument
127 * @tparam Args - Types of remaining arguments
128 * @param[in] arg - First metadata string of form VAR=value where
129 * VAR is the variable name in uppercase and
130 * value is of any size and format
131 * @param[in] args - Remaining metadata strings
132 */
133template <typename Arg, typename... Args>
134constexpr auto entry(Arg&& arg, Args&&... args)
135{
136 static_assert(is_char_ptr_argtype<Arg>::value,
137 "bad argument type: use char*");
138 static_assert(all_true<is_printf_argtype<Args>::value...>::value,
139 "bad argument type: use string.c_str() if needed");
140 return std::make_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...);
141}
142
143/** @fn log()
144 * @brief Log message to systemd journal
145 * @tparam L - Priority level
146 * @param[in] msg - Message to be logged in C-string format
147 * @param[in] entry - Metadata fields to be added to the message
148 * @details Usage: log<level::XX>(const char*, entry(*format), entry()...);
149 * @example log<level::DEBUG>(
150 * "Simple Example");
151 * char msg_str[] = "File not found";
152 * log<level::DEBUG>(
153 * msg_str,
154 * entry("MY_METADATA=%s_%x, name, number));
155 */
Patrick Venturef18bf832018-10-26 18:14:00 -0700156template <level L, typename Msg, typename... Entry>
Adriana Kobylak7d0692a2016-12-06 15:13:23 -0600157void log(Msg msg, Entry... e)
Adriana Kobylak91da4532016-07-20 12:42:55 -0500158{
159 static_assert((std::is_same<const char*, std::decay_t<Msg>>::value ||
160 std::is_same<char*, std::decay_t<Msg>>::value),
161 "First parameter must be a C-string.");
162
Patrick Venturef18bf832018-10-26 18:14:00 -0700163 constexpr const char* msg_str = "MESSAGE=%s";
Adriana Kobylak91da4532016-07-20 12:42:55 -0500164 const auto msg_tuple = std::make_tuple(msg_str, std::forward<Msg>(msg));
165
Stanley Chu31d78f72022-02-08 13:45:32 +0800166 constexpr auto transactionStr = "TRANSACTION_ID=%llu";
Adriana Kobylak7d0692a2016-12-06 15:13:23 -0600167 auto transactionId = sdbusplus::server::transaction::get_id();
168
Patrick Venturef18bf832018-10-26 18:14:00 -0700169 auto log_tuple = std::tuple_cat(details::prio<L>(), msg_tuple,
Adriana Kobylak7d0692a2016-12-06 15:13:23 -0600170 entry(transactionStr, transactionId),
171 std::forward<Entry>(e)...);
Adriana Kobylak91da4532016-07-20 12:42:55 -0500172 details::log(log_tuple);
173}
174
Adriana Kobylak91da4532016-07-20 12:42:55 -0500175} // namespace logging
176
177} // namespace phosphor