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 :
8 : #include "spdk/log.h"
9 :
10 : static const char *const spdk_level_names[] = {
11 : [SPDK_LOG_ERROR] = "ERROR",
12 : [SPDK_LOG_WARN] = "WARNING",
13 : [SPDK_LOG_NOTICE] = "NOTICE",
14 : [SPDK_LOG_INFO] = "INFO",
15 : [SPDK_LOG_DEBUG] = "DEBUG",
16 : };
17 :
18 : #define MAX_TMPBUF 1024
19 :
20 : static logfunc *g_log = NULL;
21 : static bool g_log_timestamps = true;
22 :
23 : enum spdk_log_level g_spdk_log_level;
24 : enum spdk_log_level g_spdk_log_print_level;
25 :
26 82 : SPDK_LOG_REGISTER_COMPONENT(log)
27 :
28 : void
29 5 : spdk_log_set_level(enum spdk_log_level level)
30 : {
31 5 : assert(level >= SPDK_LOG_DISABLED);
32 5 : assert(level <= SPDK_LOG_DEBUG);
33 5 : g_spdk_log_level = level;
34 5 : }
35 :
36 : enum spdk_log_level
37 5 : spdk_log_get_level(void) {
38 5 : return g_spdk_log_level;
39 : }
40 :
41 : void
42 5 : spdk_log_set_print_level(enum spdk_log_level level)
43 : {
44 5 : assert(level >= SPDK_LOG_DISABLED);
45 5 : assert(level <= SPDK_LOG_DEBUG);
46 5 : g_spdk_log_print_level = level;
47 5 : }
48 :
49 : enum spdk_log_level
50 5 : spdk_log_get_print_level(void) {
51 5 : return g_spdk_log_print_level;
52 : }
53 :
54 : void
55 2 : spdk_log_open(logfunc *logf)
56 : {
57 2 : if (logf) {
58 1 : g_log = logf;
59 : } else {
60 1 : openlog("spdk", LOG_PID, LOG_LOCAL7);
61 : }
62 2 : }
63 :
64 : void
65 1 : spdk_log_close(void)
66 : {
67 1 : if (!g_log) {
68 1 : closelog();
69 : }
70 1 : }
71 :
72 : void
73 0 : spdk_log_enable_timestamps(bool value)
74 : {
75 0 : g_log_timestamps = value;
76 0 : }
77 :
78 : static void
79 1166 : get_timestamp_prefix(char *buf, int buf_size)
80 : {
81 : struct tm *info;
82 1166 : char date[24];
83 1166 : struct timespec ts;
84 : long usec;
85 :
86 1166 : if (!g_log_timestamps) {
87 0 : buf[0] = '\0';
88 0 : return;
89 : }
90 :
91 1166 : clock_gettime(CLOCK_REALTIME, &ts);
92 1166 : info = localtime(&ts.tv_sec);
93 1166 : usec = ts.tv_nsec / 1000;
94 1166 : if (info == NULL) {
95 0 : snprintf(buf, buf_size, "[%s.%06ld] ", "unknown date", usec);
96 0 : return;
97 : }
98 :
99 1166 : strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", info);
100 1166 : snprintf(buf, buf_size, "[%s.%06ld] ", date, usec);
101 : }
102 :
103 : void
104 2333 : spdk_log(enum spdk_log_level level, const char *file, const int line, const char *func,
105 : const char *format, ...)
106 : {
107 2333 : va_list ap;
108 :
109 2333 : va_start(ap, format);
110 2333 : spdk_vlog(level, file, line, func, format, ap);
111 2333 : va_end(ap);
112 2333 : }
113 :
114 : int
115 1166 : spdk_log_to_syslog_level(enum spdk_log_level level)
116 : {
117 1166 : switch (level) {
118 1 : case SPDK_LOG_DEBUG:
119 : case SPDK_LOG_INFO:
120 1 : return LOG_INFO;
121 0 : case SPDK_LOG_NOTICE:
122 0 : return LOG_NOTICE;
123 1 : case SPDK_LOG_WARN:
124 1 : return LOG_WARNING;
125 1164 : case SPDK_LOG_ERROR:
126 1164 : return LOG_ERR;
127 0 : case SPDK_LOG_DISABLED:
128 0 : return -1;
129 0 : default:
130 0 : break;
131 : }
132 :
133 0 : return LOG_INFO;
134 : }
135 :
136 : void
137 2333 : spdk_vlog(enum spdk_log_level level, const char *file, const int line, const char *func,
138 : const char *format, va_list ap)
139 : {
140 2333 : int severity = LOG_INFO;
141 2333 : char buf[MAX_TMPBUF];
142 2333 : char timestamp[64];
143 :
144 2333 : if (g_log) {
145 5 : g_log(level, file, line, func, format, ap);
146 5 : return;
147 : }
148 :
149 2328 : if (level > g_spdk_log_print_level && level > g_spdk_log_level) {
150 1162 : return;
151 : }
152 :
153 1166 : severity = spdk_log_to_syslog_level(level);
154 1166 : if (severity < 0) {
155 0 : return;
156 : }
157 :
158 1166 : vsnprintf(buf, sizeof(buf), format, ap);
159 :
160 1166 : if (level <= g_spdk_log_print_level) {
161 1166 : get_timestamp_prefix(timestamp, sizeof(timestamp));
162 1166 : if (file) {
163 1166 : fprintf(stderr, "%s%s:%4d:%s: *%s*: %s", timestamp, file, line, func, spdk_level_names[level], buf);
164 : } else {
165 0 : fprintf(stderr, "%s%s", timestamp, buf);
166 : }
167 : }
168 :
169 1166 : if (level <= g_spdk_log_level) {
170 1166 : if (file) {
171 1166 : syslog(severity, "%s:%4d:%s: *%s*: %s", file, line, func, spdk_level_names[level], buf);
172 : } else {
173 0 : syslog(severity, "%s", buf);
174 : }
175 : }
176 : }
177 :
178 : void
179 0 : spdk_vflog(FILE *fp, const char *file, const int line, const char *func,
180 : const char *format, va_list ap)
181 : {
182 0 : char buf[MAX_TMPBUF];
183 0 : char timestamp[64];
184 :
185 0 : vsnprintf(buf, sizeof(buf), format, ap);
186 :
187 0 : get_timestamp_prefix(timestamp, sizeof(timestamp));
188 :
189 0 : if (file) {
190 0 : fprintf(fp, "%s%s:%4d:%s: %s", timestamp, file, line, func, buf);
191 : } else {
192 0 : fprintf(fp, "%s%s", timestamp, buf);
193 : }
194 :
195 0 : fflush(fp);
196 0 : }
197 :
198 : void
199 0 : spdk_flog(FILE *fp, const char *file, const int line, const char *func,
200 : const char *format, ...)
201 : {
202 0 : va_list ap;
203 :
204 0 : va_start(ap, format);
205 0 : spdk_vflog(fp, file, line, func, format, ap);
206 0 : va_end(ap);
207 0 : }
208 :
209 : static void
210 3 : fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len)
211 : {
212 3 : char tmpbuf[MAX_TMPBUF];
213 3 : char buf16[16 + 1];
214 : size_t total;
215 : unsigned int idx;
216 :
217 3 : fprintf(fp, "%s\n", label);
218 :
219 3 : memset(buf16, 0, sizeof buf16);
220 3 : total = 0;
221 43 : for (idx = 0; idx < len; idx++) {
222 40 : if (idx != 0 && idx % 16 == 0) {
223 1 : snprintf(tmpbuf + total, sizeof tmpbuf - total,
224 : " %s", buf16);
225 1 : memset(buf16, 0, sizeof buf16);
226 1 : fprintf(fp, "%s\n", tmpbuf);
227 1 : total = 0;
228 : }
229 40 : if (idx % 16 == 0) {
230 4 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
231 : "%08x ", idx);
232 : }
233 40 : if (idx % 8 == 0) {
234 6 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
235 : "%s", " ");
236 : }
237 40 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
238 40 : "%2.2x ", buf[idx] & 0xff);
239 40 : buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.';
240 : }
241 27 : for (; idx % 16 != 0; idx++) {
242 24 : if (idx == 8) {
243 1 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
244 : " ");
245 : }
246 :
247 24 : total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " ");
248 : }
249 3 : snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16);
250 3 : fprintf(fp, "%s\n", tmpbuf);
251 3 : fflush(fp);
252 3 : }
253 :
254 : void
255 3 : spdk_log_dump(FILE *fp, const char *label, const void *buf, size_t len)
256 : {
257 3 : fdump(fp, label, buf, len);
258 3 : }
|