xref: /spdk/lib/log/log.c (revision 4835489a9d6310b1261d67c5a5bee6677e7ee3ac)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk_internal/log.h"
37 
38 static TAILQ_HEAD(, spdk_trace_flag) g_trace_flags = TAILQ_HEAD_INITIALIZER(g_trace_flags);
39 
40 static enum spdk_log_level g_spdk_log_level = SPDK_LOG_NOTICE;
41 static enum spdk_log_level g_spdk_log_print_level = SPDK_LOG_NOTICE;
42 
43 SPDK_LOG_REGISTER_TRACE_FLAG("log", SPDK_TRACE_LOG)
44 
45 #define MAX_TMPBUF 1024
46 
47 static const char *const spdk_level_names[] = {
48 	[SPDK_LOG_ERROR]	= "ERROR",
49 	[SPDK_LOG_WARN]		= "WARNING",
50 	[SPDK_LOG_NOTICE]	= "NOTICE",
51 	[SPDK_LOG_INFO]		= "INFO",
52 	[SPDK_LOG_DEBUG]	= "DEBUG",
53 };
54 
55 void
56 spdk_log_open(void)
57 {
58 	openlog("spdk", LOG_PID, LOG_LOCAL7);
59 }
60 
61 void
62 spdk_log_close(void)
63 {
64 	closelog();
65 }
66 
67 void
68 spdk_log_set_level(enum spdk_log_level level)
69 {
70 	g_spdk_log_level = level;
71 }
72 
73 enum spdk_log_level
74 spdk_log_get_level(void) {
75 	return g_spdk_log_level;
76 }
77 
78 void
79 spdk_log_set_print_level(enum spdk_log_level level)
80 {
81 	g_spdk_log_print_level = level;
82 }
83 
84 enum spdk_log_level
85 spdk_log_get_print_level(void) {
86 	return g_spdk_log_print_level;
87 }
88 
89 void
90 spdk_log(enum spdk_log_level level, const char *file, const int line, const char *func,
91 	 const char *format, ...)
92 {
93 	int severity = LOG_INFO;
94 	char buf[MAX_TMPBUF];
95 	va_list ap;
96 
97 	switch (level) {
98 	case SPDK_LOG_ERROR:
99 		severity = LOG_ERR;
100 		break;
101 	case SPDK_LOG_WARN:
102 		severity = LOG_WARNING;
103 		break;
104 	case SPDK_LOG_NOTICE:
105 		severity = LOG_NOTICE;
106 		break;
107 	case SPDK_LOG_INFO:
108 	case SPDK_LOG_DEBUG:
109 		severity = LOG_INFO;
110 		break;
111 	}
112 
113 	va_start(ap, format);
114 
115 	vsnprintf(buf, sizeof(buf), format, ap);
116 
117 	if (level <= g_spdk_log_print_level) {
118 		fprintf(stderr, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
119 	}
120 
121 	if (level <= g_spdk_log_level) {
122 		syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
123 	}
124 
125 	va_end(ap);
126 }
127 
128 static void
129 fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len)
130 {
131 	char tmpbuf[MAX_TMPBUF];
132 	char buf16[16 + 1];
133 	size_t total;
134 	unsigned int idx;
135 
136 	fprintf(fp, "%s\n", label);
137 
138 	memset(buf16, 0, sizeof buf16);
139 	total = 0;
140 	for (idx = 0; idx < len; idx++) {
141 		if (idx != 0 && idx % 16 == 0) {
142 			snprintf(tmpbuf + total, sizeof tmpbuf - total,
143 				 " %s", buf16);
144 			fprintf(fp, "%s\n", tmpbuf);
145 			total = 0;
146 		}
147 		if (idx % 16 == 0) {
148 			total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
149 					  "%08x ", idx);
150 		}
151 		if (idx % 8 == 0) {
152 			total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
153 					  "%s", " ");
154 		}
155 		total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
156 				  "%2.2x ", buf[idx] & 0xff);
157 		buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.';
158 	}
159 	for (; idx % 16 != 0; idx++) {
160 		total += snprintf(tmpbuf + total, sizeof tmpbuf - total, "   ");
161 		buf16[idx % 16] = ' ';
162 	}
163 	snprintf(tmpbuf + total, sizeof tmpbuf - total, "  %s", buf16);
164 	fprintf(fp, "%s\n", tmpbuf);
165 	fflush(fp);
166 }
167 
168 void
169 spdk_trace_dump(FILE *fp, const char *label, const void *buf, size_t len)
170 {
171 	fdump(fp, label, buf, len);
172 }
173 
174 static struct spdk_trace_flag *
175 get_trace_flag(const char *name)
176 {
177 	struct spdk_trace_flag *flag;
178 
179 	TAILQ_FOREACH(flag, &g_trace_flags, tailq) {
180 		if (strcasecmp(name, flag->name) == 0) {
181 			return flag;
182 		}
183 	}
184 
185 	return NULL;
186 }
187 
188 void
189 spdk_log_register_trace_flag(const char *name, struct spdk_trace_flag *flag)
190 {
191 	struct spdk_trace_flag *iter;
192 
193 	if (name == NULL || flag == NULL) {
194 		SPDK_ERRLOG("missing spdk_trace_flag parameters\n");
195 		abort();
196 	}
197 
198 	if (get_trace_flag(name)) {
199 		SPDK_ERRLOG("duplicate spdk_trace_flag '%s'\n", name);
200 		abort();
201 	}
202 
203 	TAILQ_FOREACH(iter, &g_trace_flags, tailq) {
204 		if (strcasecmp(iter->name, flag->name) > 0) {
205 			TAILQ_INSERT_BEFORE(iter, flag, tailq);
206 			return;
207 		}
208 	}
209 
210 	TAILQ_INSERT_TAIL(&g_trace_flags, flag, tailq);
211 }
212 
213 bool
214 spdk_log_get_trace_flag(const char *name)
215 {
216 	struct spdk_trace_flag *flag = get_trace_flag(name);
217 
218 	if (flag && flag->enabled) {
219 		return true;
220 	}
221 
222 	return false;
223 }
224 
225 static int
226 set_trace_flag(const char *name, bool value)
227 {
228 	struct spdk_trace_flag *flag;
229 
230 	if (strcasecmp(name, "all") == 0) {
231 		TAILQ_FOREACH(flag, &g_trace_flags, tailq) {
232 			flag->enabled = value;
233 		}
234 		return 0;
235 	}
236 
237 	flag = get_trace_flag(name);
238 	if (flag == NULL) {
239 		return -1;
240 	}
241 
242 	flag->enabled = value;
243 
244 	return 0;
245 }
246 
247 int
248 spdk_log_set_trace_flag(const char *name)
249 {
250 	return set_trace_flag(name, true);
251 }
252 
253 int
254 spdk_log_clear_trace_flag(const char *name)
255 {
256 	return set_trace_flag(name, false);
257 }
258 
259 struct spdk_trace_flag *
260 spdk_log_get_first_trace_flag(void)
261 {
262 	return TAILQ_FIRST(&g_trace_flags);
263 }
264 
265 struct spdk_trace_flag *
266 spdk_log_get_next_trace_flag(struct spdk_trace_flag *flag)
267 {
268 	return TAILQ_NEXT(flag, tailq);
269 }
270 
271 void
272 spdk_tracelog_usage(FILE *f, const char *trace_arg)
273 {
274 #ifdef DEBUG
275 	struct spdk_trace_flag *flag;
276 
277 	fprintf(f, " %s flag    enable trace flag (all", trace_arg);
278 
279 	TAILQ_FOREACH(flag, &g_trace_flags, tailq) {
280 		fprintf(f, ", %s", flag->name);
281 	}
282 
283 	fprintf(f, ")\n");
284 #else
285 	fprintf(f, " %s flag    enable trace flag (not supported - must rebuild with CONFIG_DEBUG=y)\n",
286 		trace_arg);
287 #endif
288 }
289