blob: 1b95e0cc2e43774832f87c94f23d19986a033c5d [file] [log] [blame]
Radek Krejci5aeea3a2018-09-05 13:29:36 +02001/**
2 * @file log.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Logger manipulation routines and error definitions.
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#ifndef LY_LOG_H_
16#define LY_LOG_H_
17
Radek Krejci1deb5be2020-08-26 16:43:36 +020018#include <stdint.h>
19
Radek Krejci5aeea3a2018-09-05 13:29:36 +020020#ifdef __cplusplus
21extern "C" {
22#endif
23
Radek Krejciad573502018-09-07 15:26:55 +020024/* dummy context structure */
25struct ly_ctx;
26
Radek Krejci5aeea3a2018-09-05 13:29:36 +020027/**
Radek Krejci857189e2020-09-01 13:26:36 +020028 * @brief Type to indicate boolean value.
29 *
30 * Do not test for actual value. Instead, handle it as true/false value in condition.
31 */
32typedef uint8_t ly_bool;
33
34/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +020035 * @defgroup log Logger
36 * @{
37 *
38 * Publicly visible functions and values of the libyang logger. For more
39 * information, see \ref howtologger.
40 */
41
42/**
43 * @typedef LY_LOG_LEVEL
44 * @brief Verbosity levels of the libyang logger.
45 */
46typedef enum
47{
48 LY_LLERR = 0, /**< Print only error messages, default value. */
49 LY_LLWRN = 1, /**< Print error and warning messages. */
50 LY_LLVRB = 2, /**< Besides errors and warnings, print some other verbose messages. */
51 LY_LLDBG = 3 /**< Print all messages including some development debug messages (be careful,
52 without subsequently calling ly_verb_dbg() no debug messages will be printed!). */
53} LY_LOG_LEVEL;
54
55/**
56 * @brief Set logger verbosity level.
57 * @param[in] level Verbosity level.
58 * @return Previous verbosity level.
59 */
Radek Krejci52b6d512020-10-12 12:33:17 +020060LY_LOG_LEVEL ly_log_level(LY_LOG_LEVEL level);
Radek Krejci5aeea3a2018-09-05 13:29:36 +020061
62/**
63 * @defgroup logopts Logging options
64 * @ingroup logger
65 *
66 * Logging option bits of libyang.
67 *
68 * @{
69 */
70#define LY_LOLOG 0x01 /**< Log messages normally, using callback if set. If not set, messages will
71 not be printed by libyang. */
72#define LY_LOSTORE 0x02 /**< Store any generated errors or warnings, never verbose or debug messages.
73 Note that if #LY_LOLOG is not set then verbose and debug messages are always lost. */
74#define LY_LOSTORE_LAST 0x06 /**< Store any generated errors or warnings but only the last message, always overwrite
75 the previous one. */
76
77/**
78 * @}
79 */
80
81/**
82 * @brief Set additional logger options. Default is #LY_LOLOG | #LY_LOSTORE_LAST.
83 *
84 * @param[in] opts Bitfield of @ref logopts.
85 * @return Previous logger options.
86 */
Radek Krejci1deb5be2020-08-26 16:43:36 +020087uint32_t ly_log_options(uint32_t opts);
Radek Krejci5aeea3a2018-09-05 13:29:36 +020088
89#ifndef NDEBUG
90
91/**
92 * @defgroup dbggroup Debug message groups
93 * @ingroup log
94 *
95 * Selected displayed debug message groups.
96 *
97 * @{
98 */
99
100#define LY_LDGDICT 0x01 /**< Dictionary additions and deletions. */
101#define LY_LDGYANG 0x02 /**< YANG parser messages. */
102#define LY_LDGYIN 0x04 /**< YIN parser messages. */
103#define LY_LDGXPATH 0x08 /**< XPath parsing end evaluation. */
104#define LY_LDGDIFF 0x10 /**< Diff processing and creation. */
105
106/**
107 * @}
108 */
109
110/**
111 * @brief Enable specific debugging messages (independent of log level).
112 * @param[in] dbg_groups Bitfield of enabled debug message groups (see @ref dbggroup).
113 */
Radek Krejci1deb5be2020-08-26 16:43:36 +0200114void ly_verb_dbg(uint32_t dbg_groups);
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200115
116#endif
117
118/**
Michal Vaskod8085612020-08-21 12:55:23 +0200119 * @brief Logger callback.
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200120 *
121 * !IMPORTANT! If an error has a specific error-app-tag defined in the model, it will NOT be set
122 * at the time of calling this callback. It will be set right after, so to retrieve it
123 * it must be checked afterwards with ly_errapptag().
124 *
Michal Vaskod8085612020-08-21 12:55:23 +0200125 * @param[in] level Log level of the message.
126 * @param[in] msg Message.
127 * @param[in] path Optional path of the concerned node.
128 */
129typedef void (*ly_log_clb)(LY_LOG_LEVEL level, const char *msg, const char *path);
130
131/**
132 * @brief Set logger callback.
133 *
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200134 * @param[in] clb Logging callback.
135 * @param[in] path flag to resolve and provide path as the third parameter of the callback function. In case of
136 * validation and some other errors, it can be useful to get the path to the problematic element. Note,
137 * that according to the tree type and the specific situation, the path can slightly differs (keys
138 * presence) or it can be NULL, so consider it as an optional parameter. If the flag is 0, libyang will
139 * not bother with resolving the path.
140 */
Radek Krejci857189e2020-09-01 13:26:36 +0200141void ly_set_log_clb(ly_log_clb clb, ly_bool path);
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200142
143/**
144 * @brief Get logger callback.
145 * @return Logger callback (can be NULL).
146 */
Michal Vaskod8085612020-08-21 12:55:23 +0200147ly_log_clb ly_get_log_clb(void);
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200148
149/** @} log */
150
151/**
152 * @defgroup errors Error information
153 * @{
154 */
155
156/**
157 * @typedef LY_ERR
158 * @brief libyang's error codes returned by the libyang functions.
159 */
160typedef enum
161{
162 LY_SUCCESS = 0, /**< no error, not set by functions, included just to complete #LY_ERR enumeration */
163 LY_EMEM, /**< Memory allocation failure */
Radek Krejcidc1c7e72018-09-07 14:58:20 +0200164 LY_ESYS, /**< System call failure */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200165 LY_EINVAL, /**< Invalid value */
166 LY_EEXIST, /**< Item already exists */
Radek Krejcid33273d2018-10-25 14:55:52 +0200167 LY_ENOTFOUND, /**< Item does not exists */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200168 LY_EINT, /**< Internal error */
169 LY_EVALID, /**< Validation failure */
Radek Krejcid3ca0632019-04-16 16:54:54 +0200170 LY_EDENIED, /**< Operation is not allowed */
Radek Krejcie553e6d2019-06-07 15:33:18 +0200171 LY_EINCOMPLETE, /**< The operation did not failed, but for some reason it was not possible to finish it completely.
172 According to the specific use case, the caller is usually supposed to perform the operation again. */
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200173 LY_ENOT, /**< Negative result */
Radek Krejcia4614e62020-05-15 14:19:28 +0200174 LY_EOTHER, /**< Unknown error */
175
176 LY_EPLUGIN = 128/**< Error reported by a plugin - the highest bit in the first byte is set.
177 This value is used ORed with one of the other LY_ERR value and can be simply masked. */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200178} LY_ERR;
179
180/**
181 * @typedef LY_VECODE
182 * @brief libyang's codes of validation error. Whenever ly_errno is set to LY_EVALID, the ly_vecode is also set
183 * to the appropriate LY_VECODE value.
184 * @ingroup logger
185 */
186typedef enum {
187 LYVE_SUCCESS = 0, /**< no error */
Radek Krejci94aa9942018-09-07 17:12:17 +0200188 LYVE_SYNTAX, /**< generic syntax error */
189 LYVE_SYNTAX_YANG, /**< YANG-related syntax error */
David Sedlák0a875b42019-03-07 22:24:05 +0100190 LYVE_SYNTAX_YIN, /**< YIN-related syntax error */
Radek Krejci70853c52018-10-15 14:46:16 +0200191 LYVE_REFERENCE, /**< invalid referencing or using an item */
Radek Krejcib1646a92018-11-02 16:08:26 +0100192 LYVE_XPATH, /**< invalid XPath expression */
Radek Krejcie7b95092019-05-15 11:03:07 +0200193 LYVE_SEMANTICS, /**< generic semantic error */
194 LYVE_SYNTAX_XML, /**< XML-related syntax error */
Radek Krejci1798aae2020-07-14 13:26:06 +0200195 LYVE_SYNTAX_JSON, /**< JSON-related syntax error */
Michal Vaskoecd62de2019-11-13 12:35:11 +0100196 LYVE_DATA, /**< YANG data does not reflect some of the module restrictions */
Radek Krejcia4614e62020-05-15 14:19:28 +0200197
198 LYVE_OTHER /**< Unknown error */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200199} LY_VECODE;
200
201/**
202 * @brief Libyang full error structure.
203 */
204struct ly_err_item {
205 LY_LOG_LEVEL level;
206 LY_ERR no;
207 LY_VECODE vecode;
208 char *msg;
209 char *path;
210 char *apptag;
211 struct ly_err_item *next;
212 struct ly_err_item *prev; /* first item's prev points to the last item */
213};
214
215/**
216 * @brief Get the last (thread, context-specific) validation error code.
217 *
218 * This value is set only if ly_errno is #LY_EVALID.
219 *
220 * @param[in] ctx Relative context.
221 * @return Validation error code.
222 */
223LY_VECODE ly_vecode(const struct ly_ctx *ctx);
224
225/**
Radek Krejcid33273d2018-10-25 14:55:52 +0200226 * @brief Get the last (thread, context-specific) error code.
227 *
228 * @param[in] ctx Relative context.
229 * @return LY_ERR value of the last error code.
230 */
231LY_ERR ly_errcode(const struct ly_ctx *ctx);
232
233/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200234 * @brief Get the last (thread, context-specific) error message. If the coresponding module defined
235 * a specific error message, it will be used instead the default one.
236 *
237 * Sometimes, the error message is extended with path of the element where the problem is.
238 * The path is available via ly_errpath().
239 *
240 * @param[in] ctx Relative context.
241 * @return Text of the last error message, empty string if there is no error.
242 */
243const char *ly_errmsg(const struct ly_ctx *ctx);
244
245/**
246 * @brief Get the last (thread, context-specific) path of the element where was an error.
247 *
248 * The path always corresponds to the error message available via ly_errmsg(), so
249 * whenever a subsequent error message is printed, the path is erased or rewritten.
250 * The path reflects the type of the processed tree - data path for data tree functions
251 * and schema path in case of schema tree functions. In case of processing YIN schema
252 * or XML data, the path can be just XML path. In such a case, the corresponding
253 * ly_vecode (value 1-3) is set.
254 *
255 * @param[in] ctx Relative context.
256 * @return Path of the error element, empty string if error path does not apply to the last error.
257 */
258const char *ly_errpath(const struct ly_ctx *ctx);
259
260/**
261 * @brief Get the last (thread, context-specific) error-app-tag if there was a specific one defined
262 * in the module for the last error.
263 *
264 * The app-tag always corresponds to the error message available via ly_errmsg(), so
265 * whenever a subsequent error message is printed, the app-tag is erased or rewritten.
266 *
267 * @param[in] ctx Relative context.
268 * @return Error-app-tag of the last error, empty string if the error-app-tag does not apply to the last error.
269 */
270const char *ly_errapptag(const struct ly_ctx *ctx);
271
272/**
273 * @brief Get the first (thread, context-specific) generated error structure.
274 *
275 * @param[in] ctx Relative context.
Radek Krejci572ee602020-09-16 14:35:08 +0200276 * @return The first error structure (can be NULL), do not modify!
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200277 */
278struct ly_err_item *ly_err_first(const struct ly_ctx *ctx);
279
280/**
Radek Krejci572ee602020-09-16 14:35:08 +0200281 * @brief Get the latest (thread, context-specific) generated error structure.
282 *
283 * @param[in] ctx Relative context.
284 * @return The last error structure (can be NULL), do not modify!
285 */
286struct ly_err_item *ly_err_last(const struct ly_ctx *ctx);
287
288/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200289 * @brief Print the error structure as if just generated.
290 *
291 * @param[in] eitem Error item structure to print.
292 */
293void ly_err_print(struct ly_err_item *eitem);
294
295/**
296 * @brief Free error structures from a context.
297 *
298 * If \p eitem is not set, free all the error structures.
299 *
300 * @param[in] ctx Relative context.
301 * @param[in] eitem Oldest error structure to remove, optional.
302 */
303void ly_err_clean(struct ly_ctx *ctx, struct ly_err_item *eitem);
304
305/** @} errors */
306
307#ifdef __cplusplus
308}
309#endif
310
311#endif /* LY_LOG_H_ */