1 /* 2 * s3fs - FUSE-based file system backed by Amazon S3 3 * 4 * Copyright(C) 2007 Randy Rizun <rrizun@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 #ifndef S3FS_LOGGER_H_ 22 #define S3FS_LOGGER_H_ 23 24 #include <cstdio> 25 #include <syslog.h> 26 #include <sys/time.h> 27 28 #ifdef CLOCK_MONOTONIC_COARSE 29 #define S3FS_CLOCK_MONOTONIC CLOCK_MONOTONIC_COARSE 30 #else 31 // case of OSX 32 #define S3FS_CLOCK_MONOTONIC CLOCK_MONOTONIC 33 #endif 34 35 //------------------------------------------------------------------- 36 // S3fsLog class 37 //------------------------------------------------------------------- 38 class S3fsLog 39 { 40 public: 41 enum s3fs_log_level{ 42 LEVEL_CRIT = 0, // LEVEL_CRIT 43 LEVEL_ERR = 1, // LEVEL_ERR 44 LEVEL_WARN = 3, // LEVEL_WARNING 45 LEVEL_INFO = 7, // LEVEL_INFO 46 LEVEL_DBG = 15 // LEVEL_DEBUG 47 }; 48 49 protected: 50 static const int NEST_MAX = 4; 51 static const char* const nest_spaces[NEST_MAX]; 52 static const char LOGFILEENV[]; 53 static const char MSGTIMESTAMP[]; 54 55 static S3fsLog* pSingleton; 56 static s3fs_log_level debug_level; 57 static FILE* logfp; 58 static std::string* plogfile; 59 static bool time_stamp; 60 61 protected: 62 bool LowLoadEnv(); 63 bool LowSetLogfile(const char* pfile); 64 s3fs_log_level LowSetLogLevel(s3fs_log_level level); 65 s3fs_log_level LowBumpupLogLevel(); 66 67 public: 68 static bool IsS3fsLogLevel(s3fs_log_level level); 69 static bool IsS3fsLogCrit() { return IsS3fsLogLevel(LEVEL_CRIT); } 70 static bool IsS3fsLogErr() { return IsS3fsLogLevel(LEVEL_ERR); } 71 static bool IsS3fsLogWarn() { return IsS3fsLogLevel(LEVEL_WARN); } 72 static bool IsS3fsLogInfo() { return IsS3fsLogLevel(LEVEL_INFO); } 73 static bool IsS3fsLogDbg() { return IsS3fsLogLevel(LEVEL_DBG); } 74 75 static int GetSyslogLevel(s3fs_log_level level) 76 { 77 return ( LEVEL_DBG == (level & LEVEL_DBG) ? LOG_DEBUG : 78 LEVEL_INFO == (level & LEVEL_DBG) ? LOG_INFO : 79 LEVEL_WARN == (level & LEVEL_DBG) ? LOG_WARNING : 80 LEVEL_ERR == (level & LEVEL_DBG) ? LOG_ERR : LOG_CRIT ); 81 } 82 83 static std::string GetCurrentTime(); 84 85 static const char* GetLevelString(s3fs_log_level level) 86 { 87 return ( LEVEL_DBG == (level & LEVEL_DBG) ? "[DBG] " : 88 LEVEL_INFO == (level & LEVEL_DBG) ? "[INF] " : 89 LEVEL_WARN == (level & LEVEL_DBG) ? "[WAN] " : 90 LEVEL_ERR == (level & LEVEL_DBG) ? "[ERR] " : "[CRT] " ); 91 } 92 93 static const char* GetS3fsLogNest(int nest) 94 { 95 if(nest < NEST_MAX){ 96 return nest_spaces[nest]; 97 }else{ 98 return nest_spaces[NEST_MAX - 1]; 99 } 100 } 101 102 static bool IsSetLogFile() 103 { 104 return (NULL != logfp); 105 } 106 107 static FILE* GetOutputLogFile() 108 { 109 return (logfp ? logfp : stdout); 110 } 111 112 static FILE* GetErrorLogFile() 113 { 114 return (logfp ? logfp : stderr); 115 } 116 117 static void SeekEnd() 118 { 119 if(logfp){ 120 fseek(logfp, 0, SEEK_END); 121 } 122 } 123 124 static void Flush() 125 { 126 if(logfp){ 127 fflush(logfp); 128 } 129 } 130 131 static bool SetLogfile(const char* pfile); 132 static bool ReopenLogfile(); 133 static s3fs_log_level SetLogLevel(s3fs_log_level level); 134 static s3fs_log_level BumpupLogLevel(); 135 static bool SetTimeStamp(bool value); 136 137 explicit S3fsLog(); 138 ~S3fsLog(); 139 }; 140 141 //------------------------------------------------------------------- 142 // Debug macros 143 //------------------------------------------------------------------- 144 #define S3FS_LOW_LOGPRN(level, fmt, ...) \ 145 do{ \ 146 if(S3fsLog::IsS3fsLogLevel(level)){ \ 147 if(foreground || S3fsLog::IsSetLogFile()){ \ 148 S3fsLog::SeekEnd(); \ 149 fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(level), __FILE__, __func__, __LINE__, __VA_ARGS__); \ 150 S3fsLog::Flush(); \ 151 }else{ \ 152 syslog(S3fsLog::GetSyslogLevel(level), "%s%s:%s(%d): " fmt "%s", instance_name.c_str(), __FILE__, __func__, __LINE__, __VA_ARGS__); \ 153 } \ 154 } \ 155 }while(0) 156 157 #define S3FS_LOW_LOGPRN2(level, nest, fmt, ...) \ 158 do{ \ 159 if(S3fsLog::IsS3fsLogLevel(level)){ \ 160 if(foreground || S3fsLog::IsSetLogFile()){ \ 161 S3fsLog::SeekEnd(); \ 162 fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(level), S3fsLog::GetS3fsLogNest(nest), __FILE__, __func__, __LINE__, __VA_ARGS__); \ 163 S3fsLog::Flush(); \ 164 }else{ \ 165 syslog(S3fsLog::GetSyslogLevel(level), "%s%s" fmt "%s", instance_name.c_str(), S3fsLog::GetS3fsLogNest(nest), __VA_ARGS__); \ 166 } \ 167 } \ 168 }while(0) 169 170 #define S3FS_LOW_CURLDBG(fmt, ...) \ 171 do{ \ 172 if(foreground || S3fsLog::IsSetLogFile()){ \ 173 S3fsLog::SeekEnd(); \ 174 fprintf(S3fsLog::GetOutputLogFile(), "%s[CURL DBG] " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), __VA_ARGS__); \ 175 S3fsLog::Flush(); \ 176 }else{ \ 177 syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_CRIT), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__); \ 178 } \ 179 }while(0) 180 181 #define S3FS_LOW_LOGPRN_EXIT(fmt, ...) \ 182 do{ \ 183 if(foreground || S3fsLog::IsSetLogFile()){ \ 184 S3fsLog::SeekEnd(); \ 185 fprintf(S3fsLog::GetErrorLogFile(), "s3fs: " fmt "%s\n", __VA_ARGS__); \ 186 S3fsLog::Flush(); \ 187 }else{ \ 188 fprintf(S3fsLog::GetErrorLogFile(), "s3fs: " fmt "%s\n", __VA_ARGS__); \ 189 syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_CRIT), "%ss3fs: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \ 190 } \ 191 }while(0) 192 193 // Special macro for init message 194 #define S3FS_PRN_INIT_INFO(fmt, ...) \ 195 do{ \ 196 if(foreground || S3fsLog::IsSetLogFile()){ \ 197 S3fsLog::SeekEnd(); \ 198 fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(S3fsLog::LEVEL_INFO), S3fsLog::GetS3fsLogNest(0), __FILE__, __func__, __LINE__, __VA_ARGS__, ""); \ 199 S3fsLog::Flush(); \ 200 }else{ \ 201 syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s%s" fmt "%s", instance_name.c_str(), S3fsLog::GetS3fsLogNest(0), __VA_ARGS__, ""); \ 202 } \ 203 }while(0) 204 205 #define S3FS_PRN_LAUNCH_INFO(fmt, ...) \ 206 do{ \ 207 if(foreground || S3fsLog::IsSetLogFile()){ \ 208 S3fsLog::SeekEnd(); \ 209 fprintf(S3fsLog::GetOutputLogFile(), "%s%s" fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(S3fsLog::LEVEL_INFO), __VA_ARGS__, ""); \ 210 S3fsLog::Flush(); \ 211 }else{ \ 212 syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__, ""); \ 213 } \ 214 }while(0) 215 216 // Special macro for checking cache files 217 #define S3FS_LOW_CACHE(fp, fmt, ...) \ 218 do{ \ 219 if(foreground || S3fsLog::IsSetLogFile()){ \ 220 S3fsLog::SeekEnd(); \ 221 fprintf(fp, fmt "%s\n", __VA_ARGS__); \ 222 S3fsLog::Flush(); \ 223 }else{ \ 224 syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \ 225 } \ 226 }while(0) 227 228 // [NOTE] 229 // small trick for VA_ARGS 230 // 231 #define S3FS_PRN_EXIT(fmt, ...) S3FS_LOW_LOGPRN_EXIT(fmt, ##__VA_ARGS__, "") 232 #define S3FS_PRN_CRIT(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_CRIT, fmt, ##__VA_ARGS__, "") 233 #define S3FS_PRN_ERR(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_ERR, fmt, ##__VA_ARGS__, "") 234 #define S3FS_PRN_WARN(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_WARN, fmt, ##__VA_ARGS__, "") 235 #define S3FS_PRN_DBG(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_DBG, fmt, ##__VA_ARGS__, "") 236 #define S3FS_PRN_INFO(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 0, fmt, ##__VA_ARGS__, "") 237 #define S3FS_PRN_INFO1(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 1, fmt, ##__VA_ARGS__, "") 238 #define S3FS_PRN_INFO2(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 2, fmt, ##__VA_ARGS__, "") 239 #define S3FS_PRN_INFO3(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 3, fmt, ##__VA_ARGS__, "") 240 #define S3FS_PRN_CURL(fmt, ...) S3FS_LOW_CURLDBG(fmt, ##__VA_ARGS__, "") 241 #define S3FS_PRN_CACHE(fp, ...) S3FS_LOW_CACHE(fp, ##__VA_ARGS__, "") 242 243 #endif // S3FS_LOGGER_H_ 244 245 /* 246 * Local variables: 247 * tab-width: 4 248 * c-basic-offset: 4 249 * End: 250 * vim600: expandtab sw=4 ts=4 fdm=marker 251 * vim<600: expandtab sw=4 ts=4 252 */ 253