Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/util.h"
8 : :
9 : : #include "spdk/log.h"
10 : :
11 : : static const char *const spdk_level_names[] = {
12 : : [SPDK_LOG_ERROR] = "ERROR",
13 : : [SPDK_LOG_WARN] = "WARNING",
14 : : [SPDK_LOG_NOTICE] = "NOTICE",
15 : : [SPDK_LOG_INFO] = "INFO",
16 : : [SPDK_LOG_DEBUG] = "DEBUG",
17 : : };
18 : :
19 : : #define MAX_TMPBUF 1024
20 : :
21 : : static struct spdk_log_opts g_log_opts = {
22 : : .log = NULL,
23 : : .open = NULL,
24 : : .close = NULL,
25 : : .user_ctx = NULL,
26 : : };
27 : : static bool g_log_timestamps = true;
28 : :
29 : : enum spdk_log_level g_spdk_log_level;
30 : : enum spdk_log_level g_spdk_log_print_level;
31 : :
32 : : void
33 : 2354 : spdk_log_set_level(enum spdk_log_level level)
34 : : {
35 [ + + # # ]: 2354 : assert(level >= SPDK_LOG_DISABLED);
36 [ + + # # ]: 2354 : assert(level <= SPDK_LOG_DEBUG);
37 : 2354 : g_spdk_log_level = level;
38 : 2354 : }
39 : :
40 : : enum spdk_log_level
41 : 56 : spdk_log_get_level(void) {
42 : 56 : return g_spdk_log_level;
43 : : }
44 : :
45 : : void
46 : 2387 : spdk_log_set_print_level(enum spdk_log_level level)
47 : : {
48 [ + + # # ]: 2387 : assert(level >= SPDK_LOG_DISABLED);
49 [ + + # # ]: 2387 : assert(level <= SPDK_LOG_DEBUG);
50 : 2387 : g_spdk_log_print_level = level;
51 : 2387 : }
52 : :
53 : : enum spdk_log_level
54 : 20 : spdk_log_get_print_level(void) {
55 : 20 : return g_spdk_log_print_level;
56 : : }
57 : :
58 : : static void
59 : 2338 : log_open(void *ctx)
60 : : {
61 [ - + + - ]: 2338 : openlog("spdk", LOG_PID, LOG_LOCAL7);
62 : 2338 : }
63 : :
64 : : static void
65 : 2338 : log_close(void *ctx)
66 : : {
67 : 2338 : closelog();
68 : 2338 : }
69 : :
70 : : void
71 : 2342 : spdk_log_open(spdk_log_cb *log)
72 : : {
73 [ + + ]: 2342 : if (log) {
74 : 4 : struct spdk_log_opts opts = {.log = log};
75 : 4 : opts.size = SPDK_SIZEOF(&opts, log);
76 : 4 : spdk_log_open_ext(&opts);
77 : 1 : } else {
78 : 2338 : spdk_log_open_ext(NULL);
79 : : }
80 : 2342 : }
81 : :
82 : : void
83 : 2346 : spdk_log_open_ext(struct spdk_log_opts *opts)
84 : : {
85 [ + + ]: 2346 : if (!opts) {
86 [ + - ]: 2338 : g_log_opts.open = log_open;
87 [ + - ]: 2338 : g_log_opts.close = log_close;
88 : 2338 : goto out;
89 : : }
90 : :
91 [ + + # # : 8 : g_log_opts.log = SPDK_GET_FIELD(opts, log, NULL);
# # # # #
# # # ]
92 [ + + # # : 8 : g_log_opts.open = SPDK_GET_FIELD(opts, open, NULL);
# # # # #
# # # ]
93 [ + + # # : 8 : g_log_opts.close = SPDK_GET_FIELD(opts, close, NULL);
# # # # #
# # # ]
94 [ + + # # : 8 : g_log_opts.user_ctx = SPDK_GET_FIELD(opts, user_ctx, NULL);
# # # # #
# # # ]
95 : :
96 : 2230 : out:
97 [ + + + - ]: 2346 : if (g_log_opts.open) {
98 [ + - - + : 2342 : g_log_opts.open(g_log_opts.user_ctx);
+ - + - ]
99 : 115 : }
100 : 2346 : }
101 : :
102 : : void
103 : 2368 : spdk_log_close(void)
104 : : {
105 [ + + + + ]: 2368 : if (g_log_opts.close) {
106 [ + - - + : 2342 : g_log_opts.close(g_log_opts.user_ctx);
+ - + - ]
107 : 115 : }
108 [ + + ]: 2368 : memset(&g_log_opts, 0, sizeof(g_log_opts));
109 : 2368 : }
110 : :
111 : : void
112 : 0 : spdk_log_enable_timestamps(bool value)
113 : : {
114 [ # # ]: 0 : g_log_timestamps = value;
115 : 0 : }
116 : :
117 : : static void
118 : 6844549 : get_timestamp_prefix(char *buf, int buf_size)
119 : : {
120 : : struct tm *info;
121 : 24996 : char date[24];
122 : 24996 : struct timespec ts;
123 : : long usec;
124 : :
125 [ + + + + ]: 6844549 : if (!g_log_timestamps) {
126 [ # # # # ]: 0 : buf[0] = '\0';
127 : 0 : return;
128 : : }
129 : :
130 [ + + ]: 6844549 : clock_gettime(CLOCK_REALTIME, &ts);
131 : 6844549 : info = localtime(&ts.tv_sec);
132 [ + - + - ]: 6844549 : usec = ts.tv_nsec / 1000;
133 [ + + ]: 6844549 : if (info == NULL) {
134 [ # # ]: 0 : snprintf(buf, buf_size, "[%s.%06ld] ", "unknown date", usec);
135 : 0 : return;
136 : : }
137 : :
138 [ - + - + : 6844549 : strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", info);
- + ]
139 [ - + ]: 6844549 : snprintf(buf, buf_size, "[%s.%06ld] ", date, usec);
140 : 6214 : }
141 : :
142 : : void
143 : 7451689 : spdk_log(enum spdk_log_level level, const char *file, const int line, const char *func,
144 : : const char *format, ...)
145 : : {
146 : 33607 : va_list ap;
147 : :
148 : 7451689 : va_start(ap, format);
149 : 7451689 : spdk_vlog(level, file, line, func, format, ap);
150 : 7451689 : va_end(ap);
151 : 7451689 : }
152 : :
153 : : int
154 : 6844585 : spdk_log_to_syslog_level(enum spdk_log_level level)
155 : : {
156 [ + + + + : 6844585 : switch (level) {
- + ]
157 : 29889 : case SPDK_LOG_DEBUG:
158 : : case SPDK_LOG_INFO:
159 : 29890 : return LOG_INFO;
160 : 2915996 : case SPDK_LOG_NOTICE:
161 : 2920553 : return LOG_NOTICE;
162 : 339 : case SPDK_LOG_WARN:
163 : 364 : return LOG_WARNING;
164 : 3892133 : case SPDK_LOG_ERROR:
165 : 3893778 : return LOG_ERR;
166 : 0 : case SPDK_LOG_DISABLED:
167 : 0 : return -1;
168 : 0 : default:
169 : 0 : break;
170 : : }
171 : :
172 : 0 : return LOG_INFO;
173 : 6228 : }
174 : :
175 : : void
176 : 7452845 : spdk_vlog(enum spdk_log_level level, const char *file, const int line, const char *func,
177 : : const char *format, va_list ap)
178 : : {
179 : 7452845 : int severity = LOG_INFO;
180 : 7452845 : char *buf, _buf[MAX_TMPBUF], *ext_buf = NULL;
181 : 33607 : char timestamp[64];
182 : 33607 : va_list ap_copy;
183 : : int rc;
184 : :
185 [ + + - + ]: 7452845 : if (g_log_opts.log) {
186 [ # # # # : 24 : g_log_opts.log(level, file, line, func, format, ap);
# # ]
187 : 598321 : return;
188 : : }
189 : :
190 [ + + + + ]: 7452821 : if (level > g_spdk_log_print_level && level > g_spdk_log_level) {
191 : 608272 : return;
192 : : }
193 : :
194 : 6844549 : severity = spdk_log_to_syslog_level(level);
195 [ + + ]: 6844549 : if (severity < 0) {
196 : 0 : return;
197 : : }
198 : :
199 : 6844549 : buf = _buf;
200 : :
201 : 6844549 : va_copy(ap_copy, ap);
202 [ - + ]: 6844549 : rc = vsnprintf(_buf, sizeof(_buf), format, ap);
203 [ + + ]: 6844549 : if (rc > MAX_TMPBUF) {
204 : : /* The output including the terminating was more than MAX_TMPBUF bytes.
205 : : * Try allocating memory large enough to hold the output.
206 : : */
207 : 3 : rc = vasprintf(&ext_buf, format, ap_copy);
208 [ + - ]: 3 : if (rc < 0) {
209 : : /* Failed to allocate memory. Allow output to be truncated. */
210 : 0 : } else {
211 : 3 : buf = ext_buf;
212 : : }
213 : 0 : }
214 : 6844549 : va_end(ap_copy);
215 : :
216 [ + + ]: 6844549 : if (level <= g_spdk_log_print_level) {
217 : 6844549 : get_timestamp_prefix(timestamp, sizeof(timestamp));
218 [ + + ]: 6844549 : if (file) {
219 [ - + - + : 6839005 : fprintf(stderr, "%s%s:%4d:%s: *%s*: %s", timestamp, file, line, func, spdk_level_names[level], buf);
- + ]
220 : 5994 : } else {
221 [ - + - + ]: 5544 : fprintf(stderr, "%s%s", timestamp, buf);
222 : : }
223 : 6214 : }
224 : :
225 [ + + ]: 6844549 : if (level <= g_spdk_log_level) {
226 [ + + ]: 6813831 : if (file) {
227 [ - + - + : 6809289 : syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
- + ]
228 : 5994 : } else {
229 : 4542 : syslog(severity, "%s", buf);
230 : : }
231 : 6214 : }
232 : :
233 : 6844549 : free(ext_buf);
234 : 7602 : }
235 : :
236 : : void
237 : 0 : spdk_vflog(FILE *fp, const char *file, const int line, const char *func,
238 : : const char *format, va_list ap)
239 : : {
240 : 0 : char buf[MAX_TMPBUF];
241 : 0 : char timestamp[64];
242 : :
243 [ # # ]: 0 : vsnprintf(buf, sizeof(buf), format, ap);
244 : :
245 : 0 : get_timestamp_prefix(timestamp, sizeof(timestamp));
246 : :
247 [ # # ]: 0 : if (file) {
248 [ # # # # ]: 0 : fprintf(fp, "%s%s:%4d:%s: %s", timestamp, file, line, func, buf);
249 : 0 : } else {
250 [ # # # # ]: 0 : fprintf(fp, "%s%s", timestamp, buf);
251 : : }
252 : :
253 : 0 : fflush(fp);
254 : 0 : }
255 : :
256 : : void
257 : 0 : spdk_flog(FILE *fp, const char *file, const int line, const char *func,
258 : : const char *format, ...)
259 : : {
260 : 0 : va_list ap;
261 : :
262 : 0 : va_start(ap, format);
263 : 0 : spdk_vflog(fp, file, line, func, format, ap);
264 : 0 : va_end(ap);
265 : 0 : }
266 : :
267 : : static void
268 : 5839 : fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len)
269 : : {
270 : 12 : char tmpbuf[MAX_TMPBUF];
271 : 12 : char buf16[16 + 1];
272 : : size_t total;
273 : : unsigned int idx;
274 : :
275 [ - + ]: 5839 : fprintf(fp, "%s\n", label);
276 : :
277 [ # # ]: 5839 : memset(buf16, 0, sizeof buf16);
278 : 5839 : total = 0;
279 [ + + ]: 4358482 : for (idx = 0; idx < len; idx++) {
280 [ + + + + : 4352643 : if (idx != 0 && idx % 16 == 0) {
# # ]
281 [ # # # # ]: 266209 : snprintf(tmpbuf + total, sizeof tmpbuf - total,
282 : 1 : " %s", buf16);
283 [ # # ]: 266208 : memset(buf16, 0, sizeof buf16);
284 [ - + ]: 266208 : fprintf(fp, "%s\n", tmpbuf);
285 : 266208 : total = 0;
286 : 1 : }
287 [ + + # # ]: 4352643 : if (idx % 16 == 0) {
288 [ # # # # ]: 272051 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
289 : 4 : "%08x ", idx);
290 : 4 : }
291 [ + + # # ]: 4352643 : if (idx % 8 == 0) {
292 [ # # # # ]: 544085 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
293 : : "%s", " ");
294 : 6 : }
295 [ # # # # ]: 8705246 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
296 [ # # # # ]: 4352643 : "%2.2x ", buf[idx] & 0xff);
297 [ + + # # : 4352643 : buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.';
# # # # #
# # # # #
# # # # #
# # # #
# ]
298 : 40 : }
299 [ + + # # ]: 5948 : for (; idx % 16 != 0; idx++) {
300 [ + + ]: 109 : if (idx == 8) {
301 [ # # # # ]: 5 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
302 : : " ");
303 : 1 : }
304 : :
305 [ # # # # ]: 109 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " ");
306 : 24 : }
307 [ # # # # ]: 5839 : snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16);
308 [ - + ]: 5839 : fprintf(fp, "%s\n", tmpbuf);
309 : 5839 : fflush(fp);
310 : 5839 : }
311 : :
312 : : void
313 : 5839 : spdk_log_dump(FILE *fp, const char *label, const void *buf, size_t len)
314 : : {
315 : 5839 : fdump(fp, label, buf, len);
316 : 5839 : }
|