1 /* 2 * Copyright (C) 2002-2003 Fhg Fokus 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. This program is released under 10 * the GPL with the additional exemption that compiling, linking, 11 * and/or using OpenSSL is allowed. 12 * 13 * For a license to use the SEMS software under conditions 14 * other than those described here, or to purchase support for this 15 * software, please contact iptel.org by e-mail at the following addresses: 16 * info@iptel.org 17 * 18 * SEMS is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 28 /** @file log.h */ 29 #ifndef _log_h_ 30 #define _log_h_ 31 32 #include <sys/types.h> /* pid_t */ 33 #include <stdio.h> 34 #include <unistd.h> /* getpid() */ 35 #include <pthread.h> /* pthread_self() */ 36 #include <execinfo.h> /* backtrace_symbols() */ 37 38 #ifdef __cplusplus 39 #include <cxxabi.h> /* __cxa_demangle() */ 40 #endif 41 42 43 #ifdef __cplusplus 44 extern "C" { 45 # if 0 46 } 47 # endif 48 #endif 49 50 /** 51 * @{ Log levels 52 */ 53 enum Log_Level { 54 L_ERR = 0, 55 L_WARN, 56 L_INFO, 57 L_DBG 58 }; 59 /** @} */ 60 61 #define FIX_LOG_LEVEL(level) \ 62 ((level) < L_ERR ? L_ERR : ((level) > L_DBG ? L_DBG : (level))) 63 64 #ifdef __cplusplus 65 # ifdef PRETTY_FUNCTION_LOG 66 # define FUNC_NAME __PRETTY_FUNCTION__ 67 # else 68 # define FUNC_NAME __FUNCTION__ 69 #endif 70 #else 71 # define FUNC_NAME __FUNCTION__ 72 #endif 73 74 #ifdef __linux 75 # ifndef _GNU_SOURCE 76 # define _GNU_SOURCE 77 # endif 78 # include <linux/unistd.h> 79 # include <sys/syscall.h> 80 # define GET_PID() syscall(__NR_gettid) 81 #else 82 # define GET_PID() getpid() 83 #endif 84 85 #ifdef _DEBUG 86 # ifndef NO_THREADID_LOG 87 # define GET_TID() pthread_self() 88 # define LOC_FMT " [#%lx/%u] [%s, %s:%d]" 89 # define LOC_DATA (unsigned long)tid_, pid_, FUNC_NAME, __FILE__, __LINE__ 90 # else 91 # define GET_TID() 0 92 # define LOC_FMT " [%u] [%s %s:%d]" 93 # define LOC_DATA pid_, FUNC_NAME, __FILE__, __LINE__ 94 # endif 95 #else 96 # define GET_TID() 0 97 # define LOC_FMT " [%u/%s:%d]" 98 # define LOC_DATA pid_, __FILE__, __LINE__ 99 #endif 100 101 #ifdef LOG_LOC_DATA_ATEND 102 #define COMPLETE_LOG_FMT "%s: %s" LOC_FMT "\n", log_level2str[level_], msg_, LOC_DATA 103 #else 104 #define COMPLETE_LOG_FMT LOC_FMT " %s: %s" "\n", LOC_DATA, log_level2str[level_], msg_ 105 #endif 106 107 #ifndef LOG_BUFFER_LEN 108 #define LOG_BUFFER_LEN 4096 109 #endif 110 111 /* The underscores in parameter and local variable names are there to 112 avoid collisions. */ 113 #define _LOG(level__, fmt, args...) \ 114 do { \ 115 int level_ = FIX_LOG_LEVEL(level__); \ 116 \ 117 if ((level_) <= log_level) { \ 118 pid_t pid_ = GET_PID(); \ 119 pthread_t tid_ = GET_TID(); \ 120 char msg_[LOG_BUFFER_LEN]; \ 121 int n_ = snprintf(msg_, sizeof(msg_), fmt, ##args); \ 122 if ((n_ < LOG_BUFFER_LEN) && (msg_[n_ - 1] == '\n')) \ 123 msg_[n_ - 1] = '\0'; \ 124 if (log_stderr) { \ 125 fprintf(stderr, COMPLETE_LOG_FMT); \ 126 fflush(stderr); \ 127 } \ 128 run_log_hooks(level_, pid_, tid_, FUNC_NAME, __FILE__, __LINE__, msg_); \ 129 } \ 130 } while(0) 131 132 /** 133 * @{ Logging macros 134 */ 135 136 #define CAT_ERROR(error_category, fmt, args... ) \ 137 _LOG(L_ERR, error_category " " fmt, ##args) 138 #define CAT_WARN(error_category, fmt, args... ) \ 139 _LOG(L_WARN, error_category " " fmt, ##args) 140 #define CAT_INFO(error_category, fmt, args... ) \ 141 _LOG(L_INFO, error_category " " fmt, ##args) 142 #define CAT_DBG(error_category, fmt, args... ) \ 143 _LOG(L_DBG, error_category " " fmt, ##args) 144 145 #define CATEGORIZED_PREFIX "SNMP:" 146 #define CATEGORY_ERROR CATEGORIZED_PREFIX "0" 147 #define CATEGORY_WARNING CATEGORIZED_PREFIX "1" 148 #define CATEGORY_INFO CATEGORIZED_PREFIX "2" 149 #define CATEGORY_DEBUG CATEGORIZED_PREFIX "3" 150 151 #ifdef USE_LOG_CATEGORY_PREFIXES 152 # define ERROR_CATEGORY_EGENERAL CATEGORY_ERROR ".0" " " 153 # define ERROR_CATEGORY_WGENERAL CATEGORY_WARNING ".0" " " 154 # define ERROR_CATEGORY_IGENERAL CATEGORY_INFO ".0" " " 155 # define ERROR_CATEGORY_DGENERAL CATEGORY_DEBUG ".0" " " 156 #else 157 # define ERROR_CATEGORY_EGENERAL 158 # define ERROR_CATEGORY_WGENERAL 159 # define ERROR_CATEGORY_IGENERAL 160 # define ERROR_CATEGORY_DGENERAL 161 #endif 162 163 #define ERROR(fmt, args...) CAT_ERROR(ERROR_CATEGORY_EGENERAL, fmt, ##args) 164 #define WARN(fmt, args...) CAT_WARN(ERROR_CATEGORY_WGENERAL, fmt, ##args) 165 #define INFO(fmt, args...) CAT_INFO(ERROR_CATEGORY_IGENERAL, fmt, ##args) 166 #define DBG(fmt, args...) CAT_DBG(ERROR_CATEGORY_DGENERAL, fmt, ##args) 167 168 /** @} */ 169 170 extern int log_level; 171 extern int log_stderr; 172 extern const char* log_level2str[]; 173 174 void init_logging(void); 175 void run_log_hooks(int, pid_t, pthread_t, const char*, const char*, int, char*); 176 177 #ifndef DISABLE_SYSLOG_LOG 178 int set_syslog_facility(const char*); 179 #endif 180 181 void log_stacktrace(int ll); 182 183 #ifdef __cplusplus 184 } 185 #endif 186 187 #ifdef __cplusplus 188 /* ...only for C++ */ 189 #define log_demangled_stacktrace __lds 190 void __lds(int ll, unsigned int max_frames = 63); 191 class AmLoggingFacility; 192 void register_log_hook(AmLoggingFacility*); 193 #endif 194 195 #endif /* !_log_h_ */ 196