blob: a5ba738081ce8f65882189e235a27047ea9243b3 [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
19#include <tuple>
20#include <systemd/sd-journal.h>
Adriana Kobylak7d0692a2016-12-06 15:13:23 -060021#include <sdbusplus/server/transaction.hpp>
Adriana Kobylak91da4532016-07-20 12:42:55 -050022
23namespace phosphor
24{
25
26namespace logging
27{
28
29/** @enum level
30 * @brief Enum for priority level
31 */
32enum class level
33{
34 EMERG = LOG_EMERG,
35 ALERT = LOG_ALERT,
36 CRIT = LOG_CRIT,
37 ERR = LOG_ERR,
38 WARNING = LOG_WARNING,
39 NOTICE = LOG_NOTICE,
40 INFO = LOG_INFO,
41 DEBUG = LOG_DEBUG,
42};
43
44/** @fn log()
45 * @brief Log message to systemd journal
46 * @tparam L - Priority level
47 * @param[in] msg - Message to be logged in C-string format
48 * @param[in] entry - Metadata fields to be added to the message
49 * @details Usage: log<level::XX>(const char*, entry(*format), entry()...);
50 * @example log<level::DEBUG>(
51 * "Simple Example");
52 * char msg_str[] = "File not found";
53 * log<level::DEBUG>(
54 * msg_str,
55 * entry("MY_METADATA=%s_%x, name, number));
56 */
57template <level L, typename Msg, typename ...Entry>
58void log(Msg msg, Entry... entry);
59
60/** @fn entry()
61 * @brief Pack each format string entry as a tuple to be able to validate
62 * the string and parameters when multiple entries are passed to be logged.
63 * @tparam Arg - Types of first argument
64 * @tparam Args - Types of remaining arguments
65 * @param[in] arg - First metadata string of form VAR=value where
66 * VAR is the variable name in uppercase and
67 * value is of any size and format
68 * @param[in] args - Remaining metadata strings
69 */
70template <typename Arg, typename ...Args>
71constexpr auto entry(Arg&& arg, Args&&... args);
72
73namespace details
74{
75
76/** @fn prio()
77 * @brief Prepend PRIORITY= to the input priority string.
78 * This is required by sd_journal_send().
79 * @tparam L - Priority level
80 */
81template <level L>
82constexpr auto prio()
83{
84 constexpr const char *prio_str = "PRIORITY=%d";
85 constexpr const auto prio_tuple = std::make_tuple(prio_str, L);
86 return prio_tuple;
87}
88
89/** @fn helper_log()
90 * @brief Helper function for details::log(). Log request to journal.
91 * @tparam T - Type of tuple
92 * @tparam I - std::integer_sequence of indexes (0..N) for each tuple element
93 * @param[in] e - Tuple containing the data to be logged
94 * @param[unnamed] - std::integer_sequence of tuple's index values
95 */
96template <typename T, size_t ...I>
97void helper_log(T&& e, std::integer_sequence<size_t, I...>)
98{
Andrew Geissler328889d2016-10-10 12:43:48 -050099 // https://www.freedesktop.org/software/systemd/man/sd_journal_print.html
Adriana Kobylak91da4532016-07-20 12:42:55 -0500100 sd_journal_send(std::get<I>(std::forward<T>(e))..., NULL);
101}
102
103/** @fn details::log()
104 * @brief Implementation of logging::log() function.
105 * Send request msg and size to helper funct to log it to the journal.
106 * @tparam T - Type of tuple
107 * @param[in] e - Tuple containing the data to be logged
108 */
109template <typename T>
110void log(T&& e)
111{
112 constexpr auto e_size = std::tuple_size<std::decay_t<T>>::value;
113 helper_log(std::forward<T>(e), std::make_index_sequence<e_size>{});
114}
115
116} // namespace details
117
118template <level L, typename Msg, typename ...Entry>
Adriana Kobylak7d0692a2016-12-06 15:13:23 -0600119void log(Msg msg, Entry... e)
Adriana Kobylak91da4532016-07-20 12:42:55 -0500120{
121 static_assert((std::is_same<const char*, std::decay_t<Msg>>::value ||
122 std::is_same<char*, std::decay_t<Msg>>::value),
123 "First parameter must be a C-string.");
124
125 constexpr const char *msg_str = "MESSAGE=%s";
126 const auto msg_tuple = std::make_tuple(msg_str, std::forward<Msg>(msg));
127
Adriana Kobylak7d0692a2016-12-06 15:13:23 -0600128 constexpr auto transactionStr = "TRANSACTION_ID=%lld";
129 auto transactionId = sdbusplus::server::transaction::get_id();
130
Adriana Kobylak91da4532016-07-20 12:42:55 -0500131 auto log_tuple = std::tuple_cat(details::prio<L>(),
132 msg_tuple,
Adriana Kobylak7d0692a2016-12-06 15:13:23 -0600133 entry(transactionStr, transactionId),
134 std::forward<Entry>(e)...);
Adriana Kobylak91da4532016-07-20 12:42:55 -0500135 details::log(log_tuple);
136}
137
138template <typename Arg, typename ...Args>
139constexpr auto entry(Arg&& arg, Args&&... args)
140{
141 const auto entry_tuple = std::make_tuple(std::forward<Arg>(arg),
142 std::forward<Args>(args)...);
143 return entry_tuple;
144}
145
146} // namespace logging
147
148} // namespace phosphor