summaryrefslogtreecommitdiffstats
path: root/src/knot/common/log.h
blob: 49a8375bca163b8cbb455f0804524e7561c294f0 (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
/*  Copyright (C) 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

/*!
 * \brief Logging facility.
 *
 * Supported log levels/priorities:
 * LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, and LOG_DEBUG.
 *
 * \see syslog.h
 */

#pragma once

#include <assert.h>
#include <syslog.h>
#include <stdint.h>
#include <stdbool.h>

#include "libknot/dname.h"
#include "knot/conf/conf.h"

/*! \brief Format for timestamps in log files. */
#define KNOT_LOG_TIME_FORMAT "%Y-%m-%dT%H:%M:%S%z"

/*! \brief Logging targets. */
typedef enum {
	LOG_TARGET_SYSLOG = 0, /*!< System log. */
	LOG_TARGET_STDERR = 1, /*!< Standard error stream. */
	LOG_TARGET_STDOUT = 2, /*!< Standard output stream. */
	LOG_TARGET_FILE   = 3  /*!< Generic logging to a file (unbuffered). */
} log_target_t;

/*! \brief Logging sources. */
typedef enum {
	LOG_SOURCE_SERVER  = 0, /*!< Server module. */
	LOG_SOURCE_CONTROL = 1, /*!< Server control module. */
	LOG_SOURCE_ZONE    = 2, /*!< Zone manipulation module. */
	LOG_SOURCE_ANY     = 3  /*!< Any module. */
} log_source_t;

/*! \brief Logging format flags. */
typedef enum {
	LOG_FLAG_NOTIMESTAMP = 1 << 0, /*!< Don't print timestamp prefix. */
	LOG_FLAG_NOINFO      = 1 << 1  /*!< Don't print info level prefix. */
} log_flag_t;

/*!
 * \brief Setup logging subsystem.
 */
void log_init(void);

/*!
 * \brief Close and deinitialize log.
 */
void log_close(void);

/*!
 * \brief Set logging format flag.
 */
void log_flag_set(log_flag_t flag);

/*!
 * \brief Set log levels for given target.
 *
 * \param target  Logging target index (LOG_TARGET_SYSLOG...).
 * \param src     Logging source (LOG_SOURCE_SERVER...LOG_SOURCE_ANY).
 * \param levels  Bitmask of specified log levels.
 */
void log_levels_set(log_target_t target, log_source_t src, int levels);

/*!
 * \brief Add log levels to a given target.
 *
 * New levels are added on top of existing, the resulting levels set is
 * "old_levels OR new_levels".
 *
 * \param target  Logging target index (LOG_TARGET_SYSLOG...).
 * \param src     Logging source (LOG_SOURCE_SERVER...LOG_SOURCE_ANY).
 * \param levels  Bitmask of specified log levels.
 */
void log_levels_add(log_target_t target, log_source_t src, int levels);

/*!
 * \brief Log message into server category.
 *
 * Function follows printf() format.
 *
 * \note LOG_SOURCE_ANY is not a valid value for the src parameter.
 *
 * \param priority  Message priority.
 * \param src       Message source (LOG_SOURCE_SERVER...LOG_SOURCE_ZONE).
 * \param fmt       Content of the logged message.
 */
void log_fmt(int priority, log_source_t src, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));

/*!
 * \brief Log message into zone category.
 *
 * \see log_fmt
 *
 * \param priority  Message priority.
 * \param src       Message source (LOG_SOURCE_SERVER...LOG_SOURCE_ZONE).
 * \param zone      Zone name in wire format.
 * \param param     Optional key-value parameter for structured logging.
 * \param fmt       Content of the logged message.
 */
void log_fmt_zone(int priority, log_source_t src, const knot_dname_t *zone,
                  const char *param, const char *fmt, ...)
__attribute__((format(printf, 5, 6)));

/*!
 * \brief Log message into zone category.
 *
 * \see log_fmt
 *
 * \param zone  Zone name as an ASCII string.
 * \param priority  Message priority.
 * \param src       Message source (LOG_SOURCE_SERVER...LOG_SOURCE_ZONE).
 * \param fmt       Content of the logged message.
 */
void log_fmt_zone_str(int priority, log_source_t src, const char *zone, const char *fmt, ...)
__attribute__((format(printf, 4, 5)));

/*!
 * \brief Convenient logging macros.
 */
#define log_fatal(msg, ...)   log_fmt(LOG_CRIT,    LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
#define log_error(msg, ...)   log_fmt(LOG_ERR,     LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
#define log_warning(msg, ...) log_fmt(LOG_WARNING, LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
#define log_notice(msg, ...)  log_fmt(LOG_NOTICE,  LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
#define log_info(msg, ...)    log_fmt(LOG_INFO,    LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)
#define log_debug(msg, ...)   log_fmt(LOG_DEBUG,   LOG_SOURCE_SERVER, msg, ##__VA_ARGS__)

#define log_ctl_fatal(msg, ...)   log_fmt(LOG_CRIT,    LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
#define log_ctl_error(msg, ...)   log_fmt(LOG_ERR,     LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
#define log_ctl_warning(msg, ...) log_fmt(LOG_WARNING, LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
#define log_ctl_notice(msg, ...)  log_fmt(LOG_NOTICE,  LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
#define log_ctl_info(msg, ...)    log_fmt(LOG_INFO,    LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)
#define log_ctl_debug(msg, ...)   log_fmt(LOG_DEBUG,   LOG_SOURCE_CONTROL, msg, ##__VA_ARGS__)

#define log_ctl_zone_str_error(zone, msg, ...) log_fmt_zone_str(LOG_ERR,   LOG_SOURCE_CONTROL, zone, msg, ##__VA_ARGS__)
#define log_ctl_zone_str_info(zone, msg, ...)  log_fmt_zone_str(LOG_INFO,  LOG_SOURCE_CONTROL, zone, msg, ##__VA_ARGS__)
#define log_ctl_zone_str_debug(zone, msg, ...) log_fmt_zone_str(LOG_DEBUG, LOG_SOURCE_CONTROL, zone, msg, ##__VA_ARGS__)

#define log_zone_fatal(zone, msg, ...)   log_fmt_zone(LOG_CRIT,    LOG_SOURCE_ZONE, zone, NULL, msg, ##__VA_ARGS__)
#define log_zone_error(zone, msg, ...)   log_fmt_zone(LOG_ERR,     LOG_SOURCE_ZONE, zone, NULL, msg, ##__VA_ARGS__)
#define log_zone_warning(zone, msg, ...) log_fmt_zone(LOG_WARNING, LOG_SOURCE_ZONE, zone, NULL, msg, ##__VA_ARGS__)
#define log_zone_notice(zone, msg, ...)  log_fmt_zone(LOG_NOTICE,  LOG_SOURCE_ZONE, zone, NULL, msg, ##__VA_ARGS__)
#define log_zone_info(zone, msg, ...)    log_fmt_zone(LOG_INFO,    LOG_SOURCE_ZONE, zone, NULL, msg, ##__VA_ARGS__)
#define log_zone_debug(zone, msg, ...)   log_fmt_zone(LOG_DEBUG,   LOG_SOURCE_ZONE, zone, NULL, msg, ##__VA_ARGS__)

#define log_zone_str_fatal(zone, msg, ...)   log_fmt_zone_str(LOG_CRIT,    LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
#define log_zone_str_error(zone, msg, ...)   log_fmt_zone_str(LOG_ERR,     LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
#define log_zone_str_warning(zone, msg, ...) log_fmt_zone_str(LOG_WARNING, LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
#define log_zone_str_notice(zone, msg, ...)  log_fmt_zone_str(LOG_NOTICE,  LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
#define log_zone_str_info(zone, msg, ...)    log_fmt_zone_str(LOG_INFO,    LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)
#define log_zone_str_debug(zone, msg, ...)   log_fmt_zone_str(LOG_DEBUG,   LOG_SOURCE_ZONE, zone, msg, ##__VA_ARGS__)

/*!
 * \brief Update open files ownership.
 *
 * \param uid  New owner id.
 * \param gid  New group id.
 *
 * \return Error code, KNOT_EOK if success.
 */
int log_update_privileges(int uid, int gid);

/*!
 * \brief Setup logging facilities from config.
 */
void log_reconfigure(conf_t *conf);