aboutsummaryrefslogtreecommitdiff
path: root/src/common/utils/Log.h
blob: 6ebfed366ea649d35329d49993c29ba309e91c6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
 * Copyright (c) 2021,2023 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifndef SRC_COMMON_LOG_H
#define SRC_COMMON_LOG_H

#ifndef ARM_COMPUTE_LOGGING_ENABLED

#define ARM_COMPUTE_CREATE_ACL_LOGGER()
#define ARM_COMPUTE_LOG_MSG_ACL(log_level, msg)
#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(log_level, fmt, ...)
#define ARM_COMPUTE_LOG_ERROR_ACL(msg)
#define ARM_COMPUTE_LOG_ERROR_WITH_FUNCNAME_ACL(msg)
#define ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(msg)
#define ARM_COMPUTE_LOG_PARAMS(...)

#else /* ARM_COMPUTE_LOGGING_ENABLED */

#include "arm_compute/core/Error.h"
#include "arm_compute/core/utils/logging/Macros.h"

#include "utils/TypePrinter.h"

/** Create a logger
 *
 * @note It will eventually create all default loggers in don't exist
 */
#define ARM_COMPUTE_CREATE_ACL_LOGGER()                                                                      \
    do                                                                                                       \
    {                                                                                                        \
        if (arm_compute::logging::LoggerRegistry::get().logger("ComputeLibrary") == nullptr)                 \
        {                                                                                                    \
            arm_compute::logging::LoggerRegistry::get().create_logger("ComputeLibrary",                      \
                                                                      arm_compute::logging::LogLevel::INFO); \
        }                                                                                                    \
    } while (false)

/** Log a message to the logger
 *
 * @param[in] log_level Logging level
 * @param[in] msg       Message to log
 */
#define ARM_COMPUTE_LOG_MSG_ACL(log_level, msg)                \
    do                                                         \
    {                                                          \
        ARM_COMPUTE_CREATE_ACL_LOGGER();                       \
        ARM_COMPUTE_LOG_MSG("ComputeLibrary", log_level, msg); \
    } while (false)

/** Log a message with format to the logger
 *
 * @param[in] log_level Logging level
 * @param[in] fmt       String format (printf style)
 * @param[in] ...       Message arguments
 */
#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(log_level, fmt, ...)                        \
    do                                                                                  \
    {                                                                                   \
        ARM_COMPUTE_CREATE_ACL_LOGGER();                                                \
        ARM_COMPUTE_LOG_MSG_WITH_FORMAT("ComputeLibrary", log_level, fmt, __VA_ARGS__); \
    } while (false)

/** Log an error message to the logger
 *
 * @param[in] msg Message to log
 */
#define ARM_COMPUTE_LOG_ERROR_ACL(msg)                                                     \
    do                                                                                     \
    {                                                                                      \
        ARM_COMPUTE_CREATE_ACL_LOGGER();                                                   \
        ARM_COMPUTE_LOG_MSG("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \
    } while (false)

/** Log an error message to the logger with function name before the message
 *
 * @param[in] msg Message to log
 */
#define ARM_COMPUTE_LOG_ERROR_WITH_FUNCNAME_ACL(msg)                                                     \
    do                                                                                                   \
    {                                                                                                    \
        ARM_COMPUTE_CREATE_ACL_LOGGER();                                                                 \
        ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \
    } while (false)

/** Log an information message to the logger with function name before the message
 *
 * @param[in] msg Message to log
 */
#define ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(msg)                                                     \
    do                                                                                                  \
    {                                                                                                   \
        ARM_COMPUTE_CREATE_ACL_LOGGER();                                                                \
        ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::INFO, msg); \
    } while (false)

/** Function template specialization for the out of bound element at index = tuple_size
 *
 * @param[in,out] data_registry   Reference to the input parameters data in a string format
 * @param[in]     in_params_tuple Tuple of different input data types
 */
template <std::size_t Index, typename... Tp>
inline typename std::enable_if<Index == sizeof...(Tp), void>::type
logParamsImpl(std::vector<std::string> &data_registry, const std::tuple<Tp...> &in_params_tuple)
{
    // Because it is out of bound index so do nothing
    ARM_COMPUTE_UNUSED(data_registry);
    ARM_COMPUTE_UNUSED(in_params_tuple);
}

/** Function template to iterate over all input parameters tuple at compile time:
 *
 * @param[in,out] data_registry   Reference to a vector of input parameters data in a string format
 * @param[in]     in_params_tuple Constant reference to a tuple of different input data types
 */
template <std::size_t Index, typename... Tp>
    inline typename std::enable_if <
    Index<sizeof...(Tp), void>::type logParamsImpl(std::vector<std::string> &data_registry,
                                                   const std::tuple<Tp...>  &in_params_tuple)
{
    data_registry.push_back(arm_compute::to_string(std::get<Index>(in_params_tuple)));
    // Unfold the next tuple element
    logParamsImpl<Index + 1, Tp...>(data_registry, in_params_tuple);
}

/** Function Template with variable number of inputs to collect all the passed parameters from
 *  the logging macro ARM_COMPUTE_LOG_PARAMS(...)
 *
 * @param[in] ...ins The input parameters in the variadic template, taken by universal references Ts.. &&, (not by value)
 *                   to avoid detecting T as an abstract data type when passing any of these parameters as an L-value
 *                   reference to an abstract type.
 *
 * @return  Vector of the parameters' data in a string format
 */
template <typename... Ts>
const std::vector<std::string> logParams(Ts &&...ins)
{
    std::vector<std::string> data_registry{};
    std::tuple<Ts...>        in_params_tuple{ins...};

    // Start logging the tuple elements, starting from 0 to tuple_size-1
    logParamsImpl<0>(data_registry, in_params_tuple);
    return data_registry;
}

/** Inline function to parse the input parameters string passed from strignizing of the variadic macro input
 *  #__VA_ARGS__.
 *  It is Inline to avoid the redefinition of this function each time this header is included
 *
 * @param[in] in_params_str Constant reference to a string consists of the names of the input parameters provided
 *                          as:ARM_COMPUTE_LOG_PARAMS(src0, src1) the params_names = "src0, src1"
 *
 * @return  Vector of strings containing all the names of the input parameters
 */
inline const std::vector<std::string> getParamsNames(const std::string &in_params_str)
{
    std::stringstream ss(in_params_str);

    // Vector containing all the names of the input parameters
    std::vector<std::string> names;
    std::string              temp;

    // Usually the input parameters string would be name of parameters separated
    // by ',' e.g. "src0, src1, policy"
    while (std::getline(ss, temp, ','))
    {
        names.push_back(temp);
    }
    for (auto &name : names)
    {
        // Totally get rid of white space characters
        name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
    }
    return names;
}

/** It constructs the log message to be displayed by the logger by writing each parameter name and its
 *  corresponding data info string.
 *
 * @param[in] params_names  Constant reference to a string consists of the the input parameters' names
 *                          provided e.g.: ARM_COMPUTE_LOG_PARAMS(src0, src1) then params_names = "src0, src1"
 * @param[in] data_registry Constant reference to a registry of all parameters' data in string format,
 *                          stringnized by arm_compute::to_string()
 *
 * @return  Log message string to be displayed
 */
inline const std::string constructDataLog(const std::vector<std::string> &params_names,
                                          const std::vector<std::string> &data_registry)
{
    std::string dataLog = "\n ";
    ARM_COMPUTE_ERROR_ON(params_names.size() != data_registry.size());
    for (uint8_t i = 0; i < params_names.size(); ++i)
    {
        dataLog += params_names[i] + ": " + data_registry.at(i) + "\n ";
    }

    return dataLog;
}

/** Macro for logging input Parameters from any function.
 *  It detects the input parameters names, and their corresponding values before stringizing them using
 *  the overloaded arm_compute::to_string() type printer. Finally, displayed using the printer configured
 *  in the logger.
 *
 * @param[in] ... Input parameters
 */
#define ARM_COMPUTE_LOG_PARAMS(...)                                                  \
    do                                                                               \
    {                                                                                \
        ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(                                      \
            constructDataLog(getParamsNames(#__VA_ARGS__), logParams(__VA_ARGS__))); \
    } while (false)
#endif /* ARM_COMPUTE_LOGGING_ENABLED */
#endif /* SRC_COMMON_LOG_H */