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