LogImp.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "LogImp.h"
  17. #include "servant/RemoteLogger.h"
  18. GlobeInfo g_globe;
  19. TC_DayLogger& GlobeInfo::makeDayLogger(const string &app, const string &server, const string &logname, const string &format,const string& ip)
  20. {
  21. string sLogPath = _log_path + "/" + app + "/" + server + "/" + logname;
  22. TLOGDEBUG("GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|format:" << format << endl);
  23. DLOG << "GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|format:" << format << endl;
  24. TC_DayLogger *p = new TC_DayLogger();
  25. p->init(sLogPath, format);
  26. p->setupThread(&_group);
  27. //所有标识都不要
  28. p->modFlag(0xffff, false);
  29. _loggers[logname][ip] = p;
  30. _formats[logname][ip] = format;
  31. return (*p);
  32. }
  33. TC_DayLogger& GlobeInfo::makeDayLogger(const LogInfo & info, const string &logname, const string &format,const string& ip)
  34. {
  35. string sLogPath = getRealLogName(info);
  36. //获取配置中的记录方式
  37. string sFormat = format;
  38. string sLogType = info.sLogType;
  39. string sKey = info.appname + "." +info.servername + "." + info.sFilename;
  40. map<string,string>::iterator it = _mLogType.find(sKey);
  41. if(it != _mLogType.end())
  42. {
  43. //服务端的配置优先级最高
  44. sLogType = it->second;
  45. //使用规范格式
  46. sFormat = "";
  47. }
  48. TLOGDEBUG("GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|app:" << info.appname << "|server:" << info.servername << "|filename:" << info.sFilename
  49. << "|format:" << format << "|setdivision:" << info.setdivision << "|bHasSufix:" << info.bHasSufix << "|bHasAppNamePrefix:" << info.bHasAppNamePrefix
  50. << "|sConcatStr" << info.sConcatStr << "|sSepar" << info.sSepar << "|sLogType:" << sLogType << endl);
  51. DLOG << "GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|app:" << info.appname << "|server:" << info.servername << "|filename:" << info.sFilename
  52. << "|format:" << format << "|setdivision:" << info.setdivision << "|bHasSufix:" << info.bHasSufix << "|bHasAppNamePrefix:" << info.bHasAppNamePrefix
  53. << "|sConcatStr" << info.sConcatStr << "|sSepar" << info.sSepar << "|sLogType:" << sLogType <<endl;
  54. TC_DayLogger *p = new TC_DayLogger();
  55. p->init(sLogPath, format,info.bHasSufix,info.sConcatStr,getTarsLogType(sFormat,sLogType));
  56. p->setSeparator(info.sSepar);
  57. p->enableSqareWrapper(info.bHasSquareBracket);
  58. p->setupThread(&_group);
  59. //所有标识都不要
  60. p->modFlag(0xffff, false);
  61. _loggers[logname][ip] = p;
  62. _formats[logname][ip] = format;
  63. return (*p);
  64. }
  65. LogTypePtr GlobeInfo::getTarsLogType(const string& sFormat,const string& sCutType)
  66. {
  67. LogTypePtr logTypePtr = NULL;
  68. if(sCutType != "")
  69. {
  70. string sType = TC_Common::lower(sCutType);
  71. string::size_type pos = string::npos;
  72. if((pos = sType.find("day")) != string::npos)
  73. {
  74. int n = 1;
  75. if(sType.substr(0,pos) != "" && TC_Common::isdigit(sType.substr(0,pos)) == true)
  76. {
  77. n = TC_Common::strto<int>(sType.substr(0,pos));
  78. }
  79. string format = (sFormat=="") ? LogByDay::FORMAT : sFormat;
  80. logTypePtr = new LogByDay(format,n);
  81. }
  82. else if((pos = sType.find("hour")) != string::npos)
  83. {
  84. int n = 1;
  85. if(sType.substr(0,pos) != "" && TC_Common::isdigit(sType.substr(0,pos)) == true)
  86. {
  87. n = TC_Common::strto<int>(sType.substr(0,pos));
  88. }
  89. string format = (sFormat=="") ? LogByHour::FORMAT : sFormat;
  90. logTypePtr = new LogByHour(format,n);
  91. }
  92. else if((pos = sType.find("minute")) != string::npos)
  93. {
  94. int n = 10;//支持5,10分钟
  95. if(sType.substr(0,pos) != "" && TC_Common::isdigit(sType.substr(0,pos)) == true)
  96. {
  97. n = TC_Common::strto<int>(sType.substr(0,pos));
  98. }
  99. string format = (sFormat=="") ? LogByMinute::FORMAT : sFormat;
  100. logTypePtr = new LogByMinute(format,n);
  101. }
  102. }
  103. return logTypePtr;
  104. }
  105. string GlobeInfo::getRealLogName(const LogInfo & info)
  106. {
  107. string sRealLogname;
  108. if(info.bHasAppNamePrefix)
  109. {
  110. sRealLogname = info.sFilename.empty() ? (info.appname +"." + info.servername) : \
  111. (info.appname +"." + info.servername + info.sConcatStr + info.sFilename);
  112. }
  113. else
  114. {
  115. sRealLogname = info.sFilename;
  116. }
  117. string setDivision = getSetGoodFormat(info.setdivision);
  118. string sLogPath = _log_path + "/" + info.appname + "/" + setDivision + "/" + info.servername + "/" + sRealLogname;
  119. return sLogPath;
  120. }
  121. string GlobeInfo::getLogName(const LogInfo & info)
  122. {
  123. string sLogname = TC_Common::tostr<bool>(info.bHasSufix) + info.sConcatStr + TC_Common::tostr<bool>(info.bHasAppNamePrefix) + info.sConcatStr +\
  124. TC_Common::tostr<bool>(info.bHasSquareBracket) + info.sConcatStr + info.sSepar + info.sConcatStr +\
  125. info.setdivision + info.sConcatStr + info.appname + info.sConcatStr + info.servername + info.sConcatStr + info.sFilename + info.sConcatStr + info.sLogType;
  126. return sLogname;
  127. }
  128. bool GlobeInfo::HasSameFormat(const string& logname,const string& format,string& ip)
  129. {
  130. map<string,string>::iterator itFormat = _formats[logname].begin();
  131. bool bHasFormat = false; //是否有创建过的format
  132. for(; itFormat != _formats[logname].end(); itFormat++)
  133. {
  134. if(itFormat->second == format) //找到创建过的format
  135. {
  136. bHasFormat = true;
  137. ip = itFormat->first; //为创建过相同format的节点ip
  138. break;
  139. }
  140. }
  141. return bHasFormat;
  142. }
  143. bool GlobeInfo::IsLoggerAttached(const string& logname,const string& sExcludeIp,const TC_DayLogger* pLogger)
  144. {
  145. map<string,TC_DayLogger*>::iterator itLogger = _loggers[logname].begin();
  146. bool bIsAttached = false; //是否有ip在用该logger实例
  147. for(; itLogger != _loggers[logname].end(); itLogger++)
  148. {
  149. if(itLogger->first != sExcludeIp && itLogger->second == pLogger)
  150. {
  151. bIsAttached = true;
  152. TLOGDEBUG("GlobeInfo::IsLoggerAttached first:" << itLogger->first<< endl);
  153. break;
  154. }
  155. }
  156. return bIsAttached;
  157. }
  158. TC_DayLogger& GlobeInfo::getLogger(const LogInfo & info,const string& ip)
  159. {
  160. string format = info.sFormat;
  161. if(binary_search(_vHourlist.begin(), _vHourlist.end(), (info.appname + "." + info.servername)) != false)
  162. {
  163. format = "%Y%m%d%H";
  164. }
  165. string setDivision = getSetGoodFormat(info.setdivision);
  166. if(!TC_File::isFileExistEx((_log_path + "/" + info.appname + "/" + setDivision + "/" + info.servername), S_IFDIR))
  167. {
  168. TC_File::makeDirRecursive(_log_path + "/" + info.appname + "/" + setDivision + "/" + info.servername);
  169. }
  170. string logname = getLogName(info);
  171. TLOGDEBUG("GlobeInfo::getLogger logname:" << logname << "|format:" << format << "|setDivision:" << setDivision << endl);
  172. Lock lock(*this);
  173. map<string, map<string,TC_DayLogger*> >::iterator itLogName = _loggers.find(logname);
  174. if( itLogName == _loggers.end()) //没有创建过的log
  175. {
  176. return makeDayLogger(info, logname, format, ip);
  177. }
  178. map<string,TC_DayLogger*>::iterator itIp = itLogName->second.find(ip);
  179. if(itIp == itLogName->second.end()) //没有创建过的ip节点
  180. {
  181. string sSameIp("");
  182. if(HasSameFormat(logname,format,sSameIp)) //有创建过的format,把新的节点ip划分到同组
  183. {
  184. _loggers[logname][ip] = _loggers[logname][sSameIp];//使用具有相同format的logger实例
  185. _formats[logname][ip] = format;
  186. return (*(_loggers[logname][ip]));
  187. }
  188. else //没有创建过该format,新建立一个logname下的format组
  189. {
  190. return makeDayLogger(info, logname, format,ip);
  191. }
  192. }
  193. else //该logname下的这个ip节点创建过
  194. {
  195. if(_formats[logname][ip] != format) //该ip节点的日志格式变化了
  196. {
  197. string sSameIp("");
  198. TC_DayLogger* pOldLogger = _loggers[logname][ip];
  199. if(HasSameFormat(logname,format,sSameIp))//已经有该格式,归入同组
  200. {
  201. _loggers[logname][ip] = _loggers[logname][sSameIp];
  202. _formats[logname][ip] = format;
  203. if(pOldLogger) //删除旧的loger
  204. {
  205. pOldLogger->unSetupThread();
  206. delete pOldLogger;
  207. pOldLogger = NULL;
  208. }
  209. return (*(_loggers[logname][ip]));
  210. }
  211. else
  212. {
  213. _loggers[logname][ip] = NULL;
  214. _formats[logname][ip] = "";
  215. if(!IsLoggerAttached(logname,ip,pOldLogger))//可能有多个节点引用这个loger,这里需要判断
  216. {
  217. pOldLogger->unSetupThread();
  218. delete pOldLogger;
  219. pOldLogger = NULL;
  220. }
  221. return makeDayLogger(info, logname, format,ip);
  222. }
  223. }
  224. }
  225. //没有改变格式
  226. return (*(_loggers[logname][ip]));
  227. }
  228. TC_DayLogger& GlobeInfo::getLogger(const string &app, const string &server, const string &file, const string &sformat,const string& ip)
  229. {
  230. if(!TC_File::isFileExistEx((_log_path + "/" + app + "/" + server), S_IFDIR))
  231. {
  232. TC_File::makeDirRecursive(_log_path + "/" + app + "/" + server);
  233. }
  234. string format = sformat;
  235. if(binary_search(_vHourlist.begin(),_vHourlist.end(),(app + "." + server)) != false)
  236. {
  237. format = "%Y%m%d%H";
  238. }
  239. string logname = file.empty() ? (app + "." + server) : (app + "." + server + "_" + file);
  240. TLOGDEBUG("GlobeInfo::getLogger logname:" << logname << "|format:" << format << endl);
  241. Lock lock(*this);
  242. map<string, map<string,TC_DayLogger*> >::iterator itLogName = _loggers.find(logname);
  243. if( itLogName == _loggers.end()) //没有创建过的log
  244. {
  245. return makeDayLogger(app, server, logname, format,ip);
  246. }
  247. map<string,TC_DayLogger*>::iterator itIp = itLogName->second.find(ip);
  248. if(itIp == itLogName->second.end()) //没有创建过的ip节点
  249. {
  250. string sSameIp("");
  251. if(HasSameFormat(logname,format,sSameIp)) //有创建过的format,把新的节点ip划分到同组
  252. {
  253. _loggers[logname][ip] = _loggers[logname][sSameIp];//使用具有相同format的logger实例
  254. _formats[logname][ip] = format;
  255. return (*(_loggers[logname][ip]));
  256. }
  257. else //没有创建过该format,新建立一个logname下的format组
  258. {
  259. return makeDayLogger(app, server, logname, format,ip);
  260. }
  261. }
  262. else //该logname下的这个ip节点创建过
  263. {
  264. if(_formats[logname][ip] != format) //该ip节点的日志格式变化了
  265. {
  266. string sSameIp("");
  267. TC_DayLogger* pOldLogger = _loggers[logname][ip];
  268. if(HasSameFormat(logname,format,sSameIp))//已经有该格式,归入同组
  269. {
  270. _loggers[logname][ip] = _loggers[logname][sSameIp];
  271. _formats[logname][ip] = format;
  272. if(pOldLogger) //删除旧的loger
  273. {
  274. pOldLogger->unSetupThread();
  275. delete pOldLogger;
  276. pOldLogger = NULL;
  277. }
  278. return (*(_loggers[logname][ip]));
  279. }
  280. else
  281. {
  282. _loggers[logname][ip] = NULL;
  283. _formats[logname][ip] = "";
  284. if(!IsLoggerAttached(logname,ip,pOldLogger))//可能有多个节点引用这个loger,这里需要判断
  285. {
  286. pOldLogger->unSetupThread();
  287. delete pOldLogger;
  288. pOldLogger = NULL;
  289. }
  290. return makeDayLogger(app, server, logname, format,ip);
  291. }
  292. }
  293. }
  294. //没有改变格式
  295. return (*(_loggers[logname][ip]));
  296. }
  297. string GlobeInfo::getSetGoodFormat(const string& sSetDivision)
  298. {
  299. vector<string> vtSetDivisions = TC_Common::sepstr<string>(sSetDivision,".");
  300. if(vtSetDivisions.size() != 3)
  301. {
  302. return "";
  303. }
  304. else
  305. {
  306. if(vtSetDivisions[2] == "*")
  307. {
  308. return string(vtSetDivisions[0] + vtSetDivisions[1]);
  309. }
  310. else
  311. {
  312. return string(vtSetDivisions[0] + vtSetDivisions[1] + vtSetDivisions[2]);
  313. }
  314. }
  315. }
  316. void GlobeInfo::update(const vector<string> &vHourlist, const map<string,string> &mLogType)
  317. {
  318. Lock lock(*this);
  319. _vHourlist = vHourlist;
  320. _mLogType = mLogType;
  321. }
  322. //////////////////////////////////////////
  323. //
  324. void LogImp::initialize()
  325. {
  326. }
  327. void LogImp::logger(const string &app, const string &server, const string &file, const string &format, const vector<string> &buffer, tars::TarsCurrentPtr current)
  328. {
  329. LOG_CONSOLE_DEBUG << app << ", " << server << ", " << file << ", " << format << endl;
  330. TC_DayLogger &dl = g_globe.getLogger(app, server, file, format,current->getIp());
  331. //记录日志
  332. for(size_t i = 0; i < buffer.size(); i++)
  333. {
  334. if(g_globe._bIpPrefix)
  335. {
  336. dl.any() << current->getIp() << "|" << buffer[i];
  337. }
  338. else
  339. {
  340. dl.any() << buffer[i];
  341. }
  342. }
  343. }
  344. void LogImp::loggerbyInfo(const LogInfo & info,const vector<std::string> & buffer,tars::TarsCurrentPtr current)
  345. {
  346. LOG_CONSOLE_DEBUG << info.writeToJsonString() << endl;
  347. TC_DayLogger &dl = g_globe.getLogger(info,current->getIp());
  348. //记录日志
  349. for(size_t i = 0; i < buffer.size(); i++)
  350. {
  351. if(g_globe._bIpPrefix)
  352. {
  353. dl.any() << current->getIp() << info.sSepar << buffer[i];
  354. }
  355. else
  356. {
  357. dl.any() << buffer[i];
  358. }
  359. }
  360. }