jlog.cpp 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include "build-config.h"
  15. #include <algorithm>
  16. #include "stdio.h"
  17. #include "jlog.hpp"
  18. #include "jlog.ipp"
  19. #include "jmutex.hpp"
  20. #include "jarray.hpp"
  21. #include "jsocket.hpp"
  22. #include "jmisc.hpp"
  23. #include "jprop.hpp"
  24. #include "lnuid.h"
  25. using namespace ln_uid;
  26. #define MSGCOMP_NUMBER 1000
  27. #define FILE_LOG_ENABLES_QUEUEUING
  28. #ifndef _WIN32
  29. #define AUDIT_DATA_LOG_TEMPLATE "/var/log/seisint/log_data_XXXXXX"
  30. #endif
  31. // Time, in nanoseconds, after which the clock field loops --- 3600000000000ns = 1hr
  32. #define CLOCK_LOOP_NANOSECONDS I64C(3600000000000)
  33. // LogMsgSysInfo
  34. static FILE *getNullHandle()
  35. {
  36. #ifdef _WIN32
  37. return fopen("nul","w");
  38. #else
  39. return fopen("/dev/null","w");
  40. #endif
  41. }
  42. LogMsgSysInfo::LogMsgSysInfo(LogMsgId _id, unsigned port, LogMsgSessionId session)
  43. {
  44. id = _id;
  45. #ifdef _WIN32
  46. // Hack for the fact that Windows doesn't handle gettimeofday
  47. // Subsecond timing granularities in log files will not be available
  48. time(&timeStarted);
  49. #else
  50. gettimeofday(&timeStarted, NULL);
  51. #endif
  52. processID = GetCurrentProcessId();
  53. threadID = threadLogID();
  54. sessionID = session;
  55. node.setLocalHost(port);
  56. }
  57. void LogMsgSysInfo::serialize(MemoryBuffer & out) const
  58. {
  59. out.append(id).append((unsigned) queryTime()).append(processID).append(threadID).append(sessionID); node.serialize(out);
  60. }
  61. void LogMsgSysInfo::deserialize(MemoryBuffer & in)
  62. {
  63. unsigned t;
  64. in.read(id).read(t).read(processID).read(threadID).read(sessionID); node.deserialize(in);
  65. #ifdef _WIN32
  66. timeStarted = t;
  67. #else
  68. timeStarted.tv_sec = t;
  69. timeStarted.tv_usec = 0; // For back-compatibility reasons, the subsecond timings are not serialized
  70. #endif
  71. }
  72. // LogMsg
  73. StringBuffer & LogMsg::toStringPlain(StringBuffer & out, unsigned fields) const
  74. {
  75. out.ensureCapacity(LOG_MSG_FORMAT_BUFFER_LENGTH);
  76. if(fields & MSGFIELD_audience)
  77. out.append("aud=").append(LogMsgAudienceToVarString(category.queryAudience())).append(' ');
  78. if(fields & MSGFIELD_class)
  79. out.append("cls=").append(LogMsgClassToVarString(category.queryClass())).append(' ');
  80. if(fields & MSGFIELD_detail)
  81. out.appendf("det=%d ", category.queryDetail());
  82. if(fields & MSGFIELD_msgID)
  83. out.appendf("id=%X ", sysInfo.queryMsgID());
  84. if(fields & MSGFIELD_timeDate)
  85. {
  86. time_t timeNum = sysInfo.queryTime();
  87. char timeString[12];
  88. struct tm timeStruct;
  89. localtime_r(&timeNum, &timeStruct);
  90. if(fields & MSGFIELD_date)
  91. {
  92. strftime(timeString, 12, "%Y-%m-%d ", &timeStruct);
  93. out.append(timeString);
  94. }
  95. if(fields & MSGFIELD_microTime)
  96. {
  97. out.appendf("%02d:%02d:%02d.%06d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs());
  98. }
  99. else if(fields & MSGFIELD_milliTime)
  100. {
  101. out.appendf("%02d:%02d:%02d.%03d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs()/1000);
  102. }
  103. else if(fields & MSGFIELD_time)
  104. {
  105. strftime(timeString, 12, "%H:%M:%S ", &timeStruct);
  106. out.append(timeString);
  107. }
  108. }
  109. if(fields & MSGFIELD_process)
  110. out.appendf("pid=%d ",sysInfo.queryProcessID());
  111. if(fields & MSGFIELD_thread)
  112. out.appendf("tid=%d ",sysInfo.queryThreadID());
  113. if(fields & MSGFIELD_session)
  114. {
  115. if(sysInfo.querySessionID() == UnknownSession)
  116. out.append("sid=unknown ");
  117. else
  118. out.appendf("sid=%" I64F "u ", sysInfo.querySessionID());
  119. }
  120. if(fields & MSGFIELD_node)
  121. {
  122. sysInfo.queryNode()->getUrlStr(out);
  123. out.append(" ");
  124. }
  125. if(fields & MSGFIELD_job)
  126. {
  127. if(jobInfo.queryJobID() == UnknownJob)
  128. out.append("job=unknown ");
  129. else
  130. out.appendf("job=%" I64F "u ", jobInfo.queryJobID());
  131. }
  132. if(fields & MSGFIELD_user)
  133. {
  134. if(jobInfo.queryUserID() == UnknownUser)
  135. out.append("usr=unknown ");
  136. else
  137. out.appendf("usr=%" I64F "u ", jobInfo.queryUserID());
  138. }
  139. if(fields & MSGFIELD_component)
  140. out.appendf("cmp=%u ", component);
  141. if (fields & MSGFIELD_quote)
  142. out.append('"');
  143. if (fields & MSGFIELD_prefix)
  144. out.append(msgPrefix(category.queryClass()));
  145. if((fields & MSGFIELD_code) && (msgCode != NoLogMsgCode))
  146. out.append(msgCode).append(": ").append(text.str());
  147. else
  148. out.append(text.str());
  149. if (fields & MSGFIELD_quote)
  150. out.append('"');
  151. return out;
  152. }
  153. StringBuffer & LogMsg::toStringXML(StringBuffer & out, unsigned fields) const
  154. {
  155. out.ensureCapacity(LOG_MSG_FORMAT_BUFFER_LENGTH);
  156. out.append("<msg ");
  157. if(fields & MSGFIELD_audience)
  158. out.append("Audience=\"").append(LogMsgAudienceToVarString(category.queryAudience())).append("\" ");
  159. if(fields & MSGFIELD_class)
  160. out.append("Class=\"").append(LogMsgClassToVarString(category.queryClass())).append("\" ");
  161. if(fields & MSGFIELD_detail)
  162. out.append("Detail=\"").append(category.queryDetail()).append("\" ");
  163. #ifdef LOG_MSG_NEWLINE
  164. if(fields & MSGFIELD_allCategory) out.append("\n ");
  165. #endif
  166. if(fields & MSGFIELD_msgID)
  167. out.append("MessageID=\"").append(sysInfo.queryMsgID()).append("\" ");
  168. if(fields & MSGFIELD_timeDate)
  169. {
  170. time_t timeNum = sysInfo.queryTime();
  171. char timeString[20];
  172. struct tm timeStruct;
  173. localtime_r(&timeNum, &timeStruct);
  174. if(fields & MSGFIELD_date)
  175. {
  176. strftime(timeString, 20, "date=\"%Y-%m-%d\" ", &timeStruct);
  177. out.append(timeString);
  178. }
  179. if(fields & MSGFIELD_microTime)
  180. {
  181. out.appendf("time=\"%02d:%02d:%02d.%06d\" ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs());
  182. }
  183. else if(fields & MSGFIELD_milliTime)
  184. {
  185. out.appendf("time=\"%02d:%02d:%02d.%03d\" ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs()/1000);
  186. }
  187. else if(fields & MSGFIELD_time)
  188. {
  189. strftime(timeString, 20, "time=\"%H:%M:%S\" ", &timeStruct);
  190. out.append(timeString);
  191. }
  192. }
  193. if(fields & MSGFIELD_process)
  194. out.append("PID=\"").append(sysInfo.queryProcessID()).append("\" ");
  195. if(fields & MSGFIELD_thread)
  196. out.append("TID=\"").append(sysInfo.queryThreadID()).append("\" ");
  197. if(fields & MSGFIELD_session)
  198. {
  199. if(sysInfo.querySessionID() == UnknownSession)
  200. out.append("SessionID=\"unknown\" ");
  201. else
  202. out.append("SessionID=\"").append(sysInfo.querySessionID()).append("\" ");
  203. }
  204. if(fields & MSGFIELD_node)
  205. {
  206. out.append("Node=\"");
  207. sysInfo.queryNode()->getUrlStr(out);
  208. out.append("\" ");
  209. }
  210. #ifdef LOG_MSG_NEWLINE
  211. if(fields & MSGFIELD_allSysInfo) out.append("\n ");
  212. #endif
  213. if(fields & MSGFIELD_job)
  214. {
  215. if(jobInfo.queryJobID() == UnknownJob)
  216. out.append("JobID=\"unknown\" ");
  217. else
  218. out.append("JobID=\"").append(jobInfo.queryJobID()).append("\" ");
  219. }
  220. if(fields & MSGFIELD_user)
  221. {
  222. if(jobInfo.queryUserID() == UnknownUser)
  223. out.append("UserID=\"unknown\" ");
  224. else
  225. out.append("UserID=\"").append(jobInfo.queryUserID()).append("\" ");
  226. }
  227. #ifdef LOG_MSG_NEWLINE
  228. if(fields & MSGFIELD_allJobInfo) out.append("\n ");
  229. #endif
  230. if(fields & MSGFIELD_component) out.append("Component=\"").append(component).append("\" ");
  231. if((fields & MSGFIELD_code) && (msgCode != NoLogMsgCode))
  232. out.append("code=\"").append(msgCode).append("\" ");
  233. out.append("text=\"").append(text.str()).append("\" />\n");
  234. return out;
  235. }
  236. StringBuffer & LogMsg::toStringTable(StringBuffer & out, unsigned fields) const
  237. {
  238. out.ensureCapacity(LOG_MSG_FORMAT_BUFFER_LENGTH);
  239. if(fields & MSGFIELD_audience)
  240. out.append(LogMsgAudienceToFixString(category.queryAudience()));
  241. if(fields & MSGFIELD_class)
  242. out.append(LogMsgClassToFixString(category.queryClass()));
  243. if(fields & MSGFIELD_detail)
  244. out.appendf("%10d ", category.queryDetail());
  245. if(fields & MSGFIELD_msgID)
  246. out.appendf("%8X ", sysInfo.queryMsgID());
  247. if(fields & MSGFIELD_timeDate)
  248. {
  249. time_t timeNum = sysInfo.queryTime();
  250. char timeString[12];
  251. struct tm timeStruct;
  252. localtime_r(&timeNum, &timeStruct);
  253. if(fields & MSGFIELD_date)
  254. {
  255. strftime(timeString, 12, "%Y-%m-%d ", &timeStruct);
  256. out.append(timeString);
  257. }
  258. if(fields & MSGFIELD_microTime)
  259. {
  260. out.appendf("%02d:%02d:%02d.%06d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs());
  261. }
  262. else if(fields & MSGFIELD_milliTime)
  263. {
  264. out.appendf("%02d:%02d:%02d.%03d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs()/1000);
  265. }
  266. else if(fields & MSGFIELD_time)
  267. {
  268. strftime(timeString, 12, "%H:%M:%S ", &timeStruct);
  269. out.append(timeString);
  270. }
  271. }
  272. if(fields & MSGFIELD_process)
  273. out.appendf("%5d ",sysInfo.queryProcessID());
  274. if(fields & MSGFIELD_thread)
  275. out.appendf("%5d ",sysInfo.queryThreadID());
  276. if(fields & MSGFIELD_session)
  277. {
  278. if(sysInfo.querySessionID() == UnknownSession)
  279. out.append(" unknown ");
  280. else
  281. out.appendf("%20" I64F "u ", sysInfo.querySessionID());
  282. }
  283. if(fields & MSGFIELD_node)
  284. {
  285. size32_t len = out.length();
  286. sysInfo.queryNode()->getUrlStr(out);
  287. out.appendN(20 + len - out.length(), ' ');
  288. }
  289. if(fields & MSGFIELD_job)
  290. {
  291. if(jobInfo.queryJobID() == UnknownJob)
  292. out.append("unknown ");
  293. else
  294. out.appendf("%7" I64F "u ", jobInfo.queryJobID());
  295. }
  296. if(fields & MSGFIELD_user)
  297. {
  298. if(jobInfo.queryUserID() == UnknownUser)
  299. out.append("unknown ");
  300. else
  301. out.appendf("%7" I64F "u ", jobInfo.queryUserID());
  302. }
  303. if(fields & MSGFIELD_component)
  304. out.appendf("%6u ", component);
  305. if (fields & MSGFIELD_quote)
  306. out.append('"');
  307. if (fields & MSGFIELD_prefix)
  308. out.append(msgPrefix(category.queryClass()));
  309. if((fields & MSGFIELD_code) && (msgCode != NoLogMsgCode))
  310. out.append(msgCode).append(": ").append(text.str());
  311. else
  312. out.append(text.str());
  313. if (fields & MSGFIELD_quote)
  314. out.append('"');
  315. out.append('\n');
  316. return out;
  317. }
  318. StringBuffer & LogMsg::toStringTableHead(StringBuffer & out, unsigned fields)
  319. {
  320. if(fields & MSGFIELD_audience)
  321. out.append("Audience ");
  322. if(fields & MSGFIELD_class)
  323. out.append("Class ");
  324. if(fields & MSGFIELD_detail)
  325. out.append(" Detail ");
  326. if(fields & MSGFIELD_msgID)
  327. out.append(" MsgID ");
  328. if(fields & MSGFIELD_date)
  329. out.append(" Date ");
  330. if(fields & (MSGFIELD_microTime | MSGFIELD_milliTime | MSGFIELD_time))
  331. out.append(" Time ");
  332. if(fields & MSGFIELD_process)
  333. out.append(" PID ");
  334. if(fields & MSGFIELD_thread)
  335. out.append(" TID ");
  336. if(fields & MSGFIELD_session)
  337. out.append(" SessionID ");
  338. if(fields & MSGFIELD_node)
  339. out.append(" Node ");
  340. if(fields & MSGFIELD_job)
  341. out.append(" JobID ");
  342. if(fields & MSGFIELD_user)
  343. out.append(" UserID ");
  344. if(fields & MSGFIELD_component)
  345. out.append(" Compo ");
  346. out.append("\n\n");
  347. return out;
  348. }
  349. void LogMsg::fprintPlain(FILE * handle, unsigned fields) const
  350. {
  351. if(fields & MSGFIELD_audience)
  352. fprintf(handle, "aud=%s", LogMsgAudienceToVarString(category.queryAudience()));
  353. if(fields & MSGFIELD_class)
  354. fprintf(handle, "cls=%s", LogMsgClassToVarString(category.queryClass()));
  355. if(fields & MSGFIELD_detail)
  356. fprintf(handle, "det=%d ", category.queryDetail());
  357. if(fields & MSGFIELD_msgID)
  358. fprintf(handle, "id=%X ", sysInfo.queryMsgID());
  359. if(fields & MSGFIELD_timeDate)
  360. {
  361. time_t timeNum = sysInfo.queryTime();
  362. char timeString[12];
  363. struct tm timeStruct;
  364. localtime_r(&timeNum, &timeStruct);
  365. if(fields & MSGFIELD_date)
  366. {
  367. strftime(timeString, 12, "%Y-%m-%d ", &timeStruct);
  368. fputs(timeString, handle);
  369. }
  370. if(fields & MSGFIELD_microTime)
  371. {
  372. fprintf(handle, "%02d:%02d:%02d.%06d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs());
  373. }
  374. else if(fields & MSGFIELD_milliTime)
  375. {
  376. fprintf(handle, "%02d:%02d:%02d.%03d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs()/1000);
  377. }
  378. else if(fields & MSGFIELD_time)
  379. {
  380. strftime(timeString, 12, "%H:%M:%S ", &timeStruct);
  381. fputs(timeString, handle);
  382. }
  383. }
  384. if(fields & MSGFIELD_process)
  385. fprintf(handle, "pid=%d ",sysInfo.queryProcessID());
  386. if(fields & MSGFIELD_thread)
  387. fprintf(handle, "tid=%d ",sysInfo.queryThreadID());
  388. if(fields & MSGFIELD_session)
  389. {
  390. if(sysInfo.querySessionID() == UnknownSession)
  391. fprintf(handle, "sid=unknown ");
  392. else
  393. fprintf(handle, "sid=%" I64F "u ", sysInfo.querySessionID());
  394. }
  395. if(fields & MSGFIELD_node)
  396. {
  397. StringBuffer buff;
  398. sysInfo.queryNode()->getUrlStr(buff);
  399. fprintf(handle, "%s ", buff.str());
  400. }
  401. if(fields & MSGFIELD_job)
  402. {
  403. if(jobInfo.queryJobID() == UnknownJob)
  404. fprintf(handle, "job=unknown ");
  405. else
  406. fprintf(handle, "job=%" I64F "u ", jobInfo.queryJobID());
  407. }
  408. if(fields & MSGFIELD_user)
  409. {
  410. if(jobInfo.queryUserID() == UnknownUser)
  411. fprintf(handle, "usr=unknown ");
  412. else
  413. fprintf(handle, "usr=%" I64F "u ", jobInfo.queryUserID());
  414. }
  415. if(fields & MSGFIELD_component)
  416. fprintf(handle, "cmp=%u ", component);
  417. const char * quote = (fields & MSGFIELD_quote) ? "\"" : "";
  418. const char * prefix = (fields & MSGFIELD_prefix) ? msgPrefix(category.queryClass()) : "";
  419. if((fields & MSGFIELD_code) && (msgCode != NoLogMsgCode))
  420. fprintf(handle, "%s%s%d: %s%s", quote, prefix, msgCode, text.str(), quote);
  421. else
  422. fprintf(handle, "%s%s%s%s", quote, prefix, text.str(), quote);
  423. }
  424. void LogMsg::fprintXML(FILE * handle, unsigned fields) const
  425. {
  426. fprintf(handle, "<msg ");
  427. if(fields & MSGFIELD_audience)
  428. fprintf(handle, "Audience=\"%s\" ", LogMsgAudienceToVarString(category.queryAudience()));
  429. if(fields & MSGFIELD_class)
  430. fprintf(handle, "Class=\"%s\" ", LogMsgClassToVarString(category.queryClass()));
  431. if(fields & MSGFIELD_detail)
  432. fprintf(handle, "Detail=\"%d\" ", category.queryDetail());
  433. #ifdef LOG_MSG_NEWLINE
  434. if(fields & MSGFIELD_allCategory) fprintf(handle, "\n ");
  435. #endif
  436. if(fields & MSGFIELD_msgID)
  437. fprintf(handle, "MessageID=\"%d\" ",sysInfo.queryMsgID());
  438. if(fields & MSGFIELD_timeDate)
  439. {
  440. time_t timeNum = sysInfo.queryTime();
  441. char timeString[20];
  442. struct tm timeStruct;
  443. localtime_r(&timeNum, &timeStruct);
  444. if(fields & MSGFIELD_date)
  445. {
  446. strftime(timeString, 20, "date=\"%Y-%m-%d\" ", &timeStruct);
  447. fputs(timeString, handle);
  448. }
  449. if(fields & MSGFIELD_microTime)
  450. {
  451. fprintf(handle, "time=\"%02d:%02d:%02d.%06d\" ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs());
  452. }
  453. else if(fields & MSGFIELD_milliTime)
  454. {
  455. fprintf(handle, "time=\"%02d:%02d:%02d.%03d\" ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs()/1000);
  456. }
  457. else if(fields & MSGFIELD_time)
  458. {
  459. strftime(timeString, 20, "time=\"%H:%M:%S\" ", &timeStruct);
  460. fputs(timeString, handle);
  461. }
  462. }
  463. if(fields & MSGFIELD_process)
  464. fprintf(handle, "PID=\"%d\" ", sysInfo.queryProcessID());
  465. if(fields & MSGFIELD_thread)
  466. fprintf(handle, "TID=\"%d\" ", sysInfo.queryThreadID());
  467. if(fields & MSGFIELD_session)
  468. {
  469. if(sysInfo.querySessionID() == UnknownSession)
  470. fprintf(handle, "SessionID=\"unknown\" ");
  471. else
  472. fprintf(handle, "SessionID=\"%" I64F "u\" ", sysInfo.querySessionID());
  473. }
  474. if(fields & MSGFIELD_node)
  475. {
  476. StringBuffer buff;
  477. sysInfo.queryNode()->getUrlStr(buff);
  478. fprintf(handle, "Node=\"%s\" ", buff.str());
  479. }
  480. #ifdef LOG_MSG_NEWLINE
  481. if(fields & MSGFIELD_allSysInfo) fprintf(handle, "\n ");
  482. #endif
  483. if(fields & MSGFIELD_job)
  484. {
  485. if(jobInfo.queryJobID() == UnknownJob)
  486. fprintf(handle, "JobID=\"unknown\" ");
  487. else
  488. fprintf(handle, "JobID=\"%" I64F "u\" ", jobInfo.queryJobID());
  489. }
  490. if(fields & MSGFIELD_user)
  491. {
  492. if(jobInfo.queryUserID() == UnknownUser)
  493. fprintf(handle, "UserID=\"unknown\" ");
  494. else
  495. fprintf(handle, "UserID=\"%" I64F "u\" ", jobInfo.queryUserID());
  496. }
  497. if(fields & MSGFIELD_component)
  498. fprintf(handle, "Component=\"%6u\" ", component);
  499. #ifdef LOG_MSG_NEWLINE
  500. if(fields & MSGFIELD_allJobInfo) fprintf(handle, "\n ");
  501. #endif
  502. if((fields & MSGFIELD_code) && (msgCode != NoLogMsgCode))
  503. fprintf(handle, "code=\"%d\" ", msgCode);
  504. fprintf(handle, "text=\"%s\" />\n", text.str());
  505. }
  506. void LogMsg::fprintTable(FILE * handle, unsigned fields) const
  507. {
  508. if(fields & MSGFIELD_audience)
  509. fputs(LogMsgAudienceToFixString(category.queryAudience()), handle);
  510. if(fields & MSGFIELD_class)
  511. fputs(LogMsgClassToFixString(category.queryClass()), handle);
  512. if(fields & MSGFIELD_detail)
  513. fprintf(handle, "%10d ", category.queryDetail());
  514. if(fields & MSGFIELD_msgID)
  515. fprintf(handle, "%08X ", sysInfo.queryMsgID());
  516. if(fields & MSGFIELD_timeDate)
  517. {
  518. time_t timeNum = sysInfo.queryTime();
  519. char timeString[12];
  520. struct tm timeStruct;
  521. localtime_r(&timeNum, &timeStruct);
  522. if(fields & MSGFIELD_date)
  523. {
  524. strftime(timeString, 12, "%Y-%m-%d ", &timeStruct);
  525. fputs(timeString, handle);
  526. }
  527. if(fields & MSGFIELD_microTime)
  528. {
  529. fprintf(handle, "%02d:%02d:%02d.%06d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs());
  530. }
  531. else if(fields & MSGFIELD_milliTime)
  532. {
  533. fprintf(handle, "%02d:%02d:%02d.%03d ", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec, sysInfo.queryUSecs()/1000);
  534. }
  535. else if(fields & MSGFIELD_time)
  536. {
  537. strftime(timeString, 12, "%H:%M:%S ", &timeStruct);
  538. fputs(timeString, handle);
  539. }
  540. }
  541. if(fields & MSGFIELD_process)
  542. fprintf(handle, "%5d ",sysInfo.queryProcessID());
  543. if(fields & MSGFIELD_thread)
  544. fprintf(handle, "%5d ",sysInfo.queryThreadID());
  545. if(fields & MSGFIELD_session)
  546. {
  547. if(sysInfo.querySessionID() == UnknownSession)
  548. fprintf(handle, " unknown ");
  549. else
  550. fprintf(handle, "%20" I64F "u ", sysInfo.querySessionID());
  551. }
  552. if(fields & MSGFIELD_node)
  553. {
  554. StringBuffer buff;
  555. static const char * twenty_spaces = " ";
  556. sysInfo.queryNode()->getUrlStr(buff);
  557. fprintf(handle, "%s%s", buff.str(), (buff.length()<=20) ? twenty_spaces+buff.length() : "");
  558. }
  559. if(fields & MSGFIELD_job)
  560. {
  561. if(jobInfo.queryJobID() == UnknownJob)
  562. fprintf(handle, "unknown ");
  563. else
  564. fprintf(handle, "%7" I64F "u ", jobInfo.queryJobID());
  565. }
  566. if(fields & MSGFIELD_user)
  567. {
  568. if(jobInfo.queryUserID() == UnknownUser)
  569. fprintf(handle, "unknown ");
  570. else
  571. fprintf(handle, "%7" I64F "u ", jobInfo.queryUserID());
  572. }
  573. if(fields & MSGFIELD_component)
  574. fprintf(handle, "%6u ", component);
  575. const char * quote = (fields & MSGFIELD_quote) ? "\"" : "";
  576. const char * prefix = (fields & MSGFIELD_prefix) ? msgPrefix(category.queryClass()) : "";
  577. if((fields & MSGFIELD_code) && (msgCode != NoLogMsgCode))
  578. fprintf(handle, "%s%s%d: %s%s\n", quote, prefix, msgCode, text.str(), quote);
  579. else
  580. fprintf(handle, "%s%s%s%s\n", quote, prefix, text.str(), quote);
  581. }
  582. void LogMsg::fprintTableHead(FILE * handle, unsigned fields)
  583. {
  584. if(fields & MSGFIELD_audience)
  585. fprintf(handle, "Audience ");
  586. if(fields & MSGFIELD_class)
  587. fprintf(handle, "Class ");
  588. if(fields & MSGFIELD_detail)
  589. fprintf(handle, " Detail ");
  590. if(fields & MSGFIELD_msgID)
  591. fprintf(handle, " MsgID ");
  592. if(fields & MSGFIELD_date)
  593. fprintf(handle, " Date ");
  594. if(fields & MSGFIELD_time)
  595. fprintf(handle, " Time ");
  596. if(fields & MSGFIELD_process)
  597. fprintf(handle, " PID ");
  598. if(fields & MSGFIELD_thread)
  599. fprintf(handle, " TID ");
  600. if(fields & MSGFIELD_session)
  601. fprintf(handle, " SessionID ");
  602. if(fields & MSGFIELD_node)
  603. fprintf(handle, " Node ");
  604. if(fields & MSGFIELD_job)
  605. fprintf(handle, " JobID ");
  606. if(fields & MSGFIELD_user)
  607. fprintf(handle, " UserID ");
  608. if(fields & MSGFIELD_component)
  609. fprintf(handle, " Compo ");
  610. fprintf(handle, "\n\n");
  611. }
  612. // Implementations of ILogMsgFilter
  613. void PassAllLogMsgFilter::addToPTree(IPropertyTree * tree) const
  614. {
  615. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  616. filterTree->setProp("@type", "all");
  617. tree->addPropTree("filter", filterTree);
  618. }
  619. void PassLocalLogMsgFilter::addToPTree(IPropertyTree * tree) const
  620. {
  621. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  622. filterTree->setProp("@type", "local");
  623. tree->addPropTree("filter", filterTree);
  624. }
  625. void PassNoneLogMsgFilter::addToPTree(IPropertyTree * tree) const
  626. {
  627. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  628. filterTree->setProp("@type", "none");
  629. tree->addPropTree("filter", filterTree);
  630. }
  631. void CategoryLogMsgFilter::addToPTree(IPropertyTree * tree) const
  632. {
  633. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  634. filterTree->setProp("@type", "category");
  635. filterTree->setPropInt("@audience", audienceMask);
  636. filterTree->setPropInt("@class", classMask);
  637. filterTree->setPropInt("@detail", maxDetail);
  638. if(localFlag) filterTree->setPropInt("@local", 1);
  639. tree->addPropTree("filter", filterTree);
  640. }
  641. void PIDLogMsgFilter::addToPTree(IPropertyTree * tree) const
  642. {
  643. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  644. filterTree->setProp("@type", "pid");
  645. filterTree->setPropInt("@pid", pid);
  646. if(localFlag) filterTree->setPropInt("@local", 1);
  647. tree->addPropTree("filter", filterTree);
  648. }
  649. void TIDLogMsgFilter::addToPTree(IPropertyTree * tree) const
  650. {
  651. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  652. filterTree->setProp("@type", "tid");
  653. filterTree->setPropInt("@tid", tid);
  654. if(localFlag) filterTree->setPropInt("@local", 1);
  655. tree->addPropTree("filter", filterTree);
  656. }
  657. void NodeLogMsgFilter::addToPTree(IPropertyTree * tree) const
  658. {
  659. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  660. filterTree->setProp("@type", "node");
  661. StringBuffer buff;
  662. node.getIpText(buff);
  663. filterTree->setProp("@ip", buff.str());
  664. filterTree->setPropInt("@port", node.port);
  665. if(localFlag) filterTree->setPropInt("@local", 1);
  666. tree->addPropTree("filter", filterTree);
  667. }
  668. void IpLogMsgFilter::addToPTree(IPropertyTree * tree) const
  669. {
  670. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  671. filterTree->setProp("@type", "ip");
  672. StringBuffer buff;
  673. ip.getIpText(buff);
  674. filterTree->setProp("@ip", buff.str());
  675. if(localFlag) filterTree->setPropInt("@local", 1);
  676. tree->addPropTree("filter", filterTree);
  677. }
  678. void JobLogMsgFilter::addToPTree(IPropertyTree * tree) const
  679. {
  680. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  681. filterTree->setProp("@type", "job");
  682. filterTree->setPropInt("@job", (int)job);
  683. if(localFlag) filterTree->setPropInt("@local", 1);
  684. tree->addPropTree("filter", filterTree);
  685. }
  686. void UserLogMsgFilter::addToPTree(IPropertyTree * tree) const
  687. {
  688. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  689. filterTree->setProp("@type", "user");
  690. filterTree->setPropInt("@user", (int)user);
  691. if(localFlag) filterTree->setPropInt("@local", 1);
  692. tree->addPropTree("filter", filterTree);
  693. }
  694. void SessionLogMsgFilter::addToPTree(IPropertyTree * tree) const
  695. {
  696. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  697. filterTree->setProp("@type", "session");
  698. filterTree->setPropInt("@session", (int)session);
  699. if(localFlag) filterTree->setPropInt("@local", 1);
  700. tree->addPropTree("filter", filterTree);
  701. }
  702. void ComponentLogMsgFilter::addToPTree(IPropertyTree * tree) const
  703. {
  704. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  705. filterTree->setProp("@type", "component");
  706. filterTree->setPropInt("@component", component);
  707. if(localFlag) filterTree->setPropInt("@local", 1);
  708. tree->addPropTree("filter", filterTree);
  709. }
  710. bool RegexLogMsgFilter::includeMessage(const LogMsg & msg) const
  711. {
  712. if(localFlag && msg.queryRemoteFlag()) return false;
  713. SpinBlock b(lock);
  714. return const_cast<RegExpr &>(regex).find(msg.queryText()) != NULL;
  715. }
  716. void RegexLogMsgFilter::addToPTree(IPropertyTree * tree) const
  717. {
  718. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  719. filterTree->setProp("@type", "regex");
  720. filterTree->setProp("@regex", regexText);
  721. if(localFlag) filterTree->setPropInt("@local", 1);
  722. tree->addPropTree("filter", filterTree);
  723. }
  724. void NotLogMsgFilter::addToPTree(IPropertyTree * tree) const
  725. {
  726. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  727. filterTree->setProp("@type", "not");
  728. arg->addToPTree(filterTree);
  729. tree->addPropTree("filter", filterTree);
  730. }
  731. void AndLogMsgFilter::addToPTree(IPropertyTree * tree) const
  732. {
  733. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  734. filterTree->setProp("@type", "and");
  735. arg1->addToPTree(filterTree);
  736. arg2->addToPTree(filterTree);
  737. tree->addPropTree("filter", filterTree);
  738. }
  739. void OrLogMsgFilter::addToPTree(IPropertyTree * tree) const
  740. {
  741. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  742. filterTree->setProp("@type", "or");
  743. arg1->addToPTree(filterTree);
  744. arg2->addToPTree(filterTree);
  745. tree->addPropTree("filter", filterTree);
  746. }
  747. void SwitchLogMsgFilter::addToPTree(IPropertyTree * tree) const
  748. {
  749. IPropertyTree * filterTree = createPTree(ipt_caseInsensitive);
  750. filterTree->setProp("@type", "switch");
  751. cond->addToPTree(filterTree);
  752. yes->addToPTree(filterTree);
  753. no->addToPTree(filterTree);
  754. tree->addPropTree("filter", filterTree);
  755. }
  756. void CategoryLogMsgFilter::orWithFilter(const ILogMsgFilter * filter)
  757. {
  758. audienceMask |= filter->queryAudienceMask();
  759. classMask |= filter->queryClassMask();
  760. maxDetail = std::max(maxDetail, filter->queryMaxDetail());
  761. }
  762. void CategoryLogMsgFilter::reset()
  763. {
  764. audienceMask = 0;
  765. classMask = 0;
  766. maxDetail = 0;
  767. }
  768. // HandleLogMsgHandler
  769. void HandleLogMsgHandlerTable::addToPTree(IPropertyTree * tree) const
  770. {
  771. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  772. if(handle==stderr)
  773. handlerTree->setProp("@type", "stderr");
  774. else
  775. handlerTree->setProp("@type", "mischandle");
  776. handlerTree->setPropInt("@fields", messageFields);
  777. tree->addPropTree("handler", handlerTree);
  778. }
  779. void HandleLogMsgHandlerXML::addToPTree(IPropertyTree * tree) const
  780. {
  781. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  782. if(handle==stderr)
  783. handlerTree->setProp("@type", "stderr");
  784. else
  785. handlerTree->setProp("@type", "mischandle");
  786. handlerTree->setPropInt("@fields", messageFields);
  787. handlerTree->setProp("@writeXML", "true");
  788. tree->addPropTree("handler", handlerTree);
  789. }
  790. // FileLogMsgHandler
  791. FileLogMsgHandler::FileLogMsgHandler(const char * _filename, const char * _headerText, unsigned _fields, bool _append, bool _flushes)
  792. : messageFields(_fields), filename(_filename), headerText(_headerText), append(_append), flushes(_flushes)
  793. {
  794. recursiveCreateDirectoryForFile(filename);
  795. if(append)
  796. handle = fopen(filename, "a");
  797. else
  798. handle = fopen(filename, "w");
  799. if(!handle) {
  800. handle = getNullHandle();
  801. StringBuffer err;
  802. err.appendf("LOGGING: could not open file '%s' for output",filename.get());
  803. OERRLOG("%s",err.str()); // make sure doesn't get lost!
  804. throw MakeStringException(3000,"%s",err.str()); // 3000: internal error
  805. }
  806. if(headerText) fprintf(handle, "--- %s ---\n", (const char *)headerText);
  807. }
  808. static void closeAndDeleteEmpty(const char * filename, FILE *handle)
  809. {
  810. if (handle) {
  811. fpos_t pos;
  812. bool del = (fgetpos(handle, &pos)==0)&&
  813. #if defined( _WIN32) || defined(__FreeBSD__) || defined(__APPLE__)
  814. (pos==0);
  815. #else
  816. (pos.__pos==0);
  817. #endif
  818. fclose(handle);
  819. if (del)
  820. remove(filename);
  821. }
  822. }
  823. FileLogMsgHandler::~FileLogMsgHandler()
  824. {
  825. closeAndDeleteEmpty(filename,handle);
  826. }
  827. char const * FileLogMsgHandler::disable()
  828. {
  829. crit.enter();
  830. fclose(handle);
  831. handle = NULL;
  832. return filename;
  833. }
  834. void FileLogMsgHandler::enable()
  835. {
  836. recursiveCreateDirectoryForFile(filename);
  837. handle = fopen(filename, "a");
  838. if(!handle) {
  839. handle = getNullHandle();
  840. assertex(!"FileLogMsgHandler::enable : could not open file for output");
  841. }
  842. crit.leave();
  843. }
  844. void FileLogMsgHandlerTable::addToPTree(IPropertyTree * tree) const
  845. {
  846. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  847. handlerTree->setProp("@type", "file");
  848. handlerTree->setProp("@filename", filename.get());
  849. if(headerText) handlerTree->setProp("@headertext", headerText.get());
  850. handlerTree->setPropInt("@fields", messageFields);
  851. handlerTree->setProp("@writeTable", "true");
  852. if(append) handlerTree->setProp("@append", "true");
  853. if(flushes) handlerTree->setProp("@flushes", "true");
  854. tree->addPropTree("handler", handlerTree);
  855. }
  856. void FileLogMsgHandlerXML::addToPTree(IPropertyTree * tree) const
  857. {
  858. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  859. handlerTree->setProp("@type", "file");
  860. handlerTree->setProp("@filename", filename.get());
  861. if(headerText) handlerTree->setProp("@headertext", headerText.get());
  862. handlerTree->setPropInt("@fields", messageFields);
  863. if(append) handlerTree->setProp("@append", "true");
  864. if(flushes) handlerTree->setProp("@flushes", "true");
  865. tree->addPropTree("handler", handlerTree);
  866. }
  867. // RollingFileLogMsgHandler
  868. RollingFileLogMsgHandler::RollingFileLogMsgHandler(const char * _filebase, const char * _fileextn, unsigned _fields, bool _append, bool _flushes, const char *initialName, const char *_alias, bool daily)
  869. : handle(0), messageFields(_fields), alias(_alias), filebase(_filebase), fileextn(_fileextn), append(_append), flushes(_flushes)
  870. {
  871. time_t tNow;
  872. time(&tNow);
  873. localtime_r(&tNow, &startTime);
  874. doRollover(daily, initialName);
  875. }
  876. RollingFileLogMsgHandler::~RollingFileLogMsgHandler()
  877. {
  878. closeAndDeleteEmpty(filename,handle);
  879. }
  880. char const * RollingFileLogMsgHandler::disable()
  881. {
  882. crit.enter();
  883. fclose(handle);
  884. return filename;
  885. }
  886. void RollingFileLogMsgHandler::enable()
  887. {
  888. recursiveCreateDirectoryForFile(filename);
  889. handle = fopen(filename, "a");
  890. if(!handle) {
  891. handle = getNullHandle();
  892. assertex(!"RollingFileLogMsgHandler::enable : could not open file for output");
  893. }
  894. crit.leave();
  895. }
  896. void RollingFileLogMsgHandler::addToPTree(IPropertyTree * tree) const
  897. {
  898. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  899. handlerTree->setProp("@type", "rollingfile");
  900. handlerTree->setProp("@filebase", filebase.get());
  901. handlerTree->setProp("@fileextn", fileextn.get());
  902. handlerTree->setPropInt("@fields", messageFields);
  903. if(append) handlerTree->setProp("@append", "true");
  904. if(flushes) handlerTree->setProp("@flushes", "true");
  905. tree->addPropTree("handler", handlerTree);
  906. }
  907. #define ROLLOVER_PERIOD 86400
  908. void RollingFileLogMsgHandler::checkRollover() const
  909. {
  910. time_t tNow;
  911. time(&tNow);
  912. struct tm ltNow;
  913. localtime_r(&tNow, &ltNow);
  914. if(ltNow.tm_year != startTime.tm_year || ltNow.tm_yday != startTime.tm_yday)
  915. {
  916. localtime_r(&tNow, &startTime); // reset the start time for next rollover check
  917. doRollover(true);
  918. }
  919. }
  920. void RollingFileLogMsgHandler::doRollover(bool daily, const char *forceName) const
  921. {
  922. CriticalBlock block(crit);
  923. closeAndDeleteEmpty(filename,handle);
  924. handle = 0;
  925. filename.clear();
  926. if (forceName)
  927. filename.append(forceName);
  928. else
  929. {
  930. filename.clear().append(filebase.get());
  931. addFileTimestamp(filename, daily);
  932. filename.append(fileextn.get());
  933. }
  934. recursiveCreateDirectoryForFile(filename.str());
  935. handle = fopen(filename.str(), append ? "a" : "w");
  936. if (handle && alias && alias.length())
  937. {
  938. fclose(handle);
  939. handle = 0;
  940. remove(alias);
  941. try
  942. {
  943. createHardLink(alias, filename.str());
  944. }
  945. catch (IException *E)
  946. {
  947. recursiveCreateDirectoryForFile(filename.str());
  948. handle = fopen(filename.str(), append ? "a" : "w");
  949. EXCLOG(E); // Log the fact that we could not create the alias - probably it is locked (tail a bit unfortunate on windows).
  950. E->Release();
  951. }
  952. if (!handle)
  953. {
  954. recursiveCreateDirectoryForFile(filename.str());
  955. handle = fopen(filename.str(), append ? "a" : "w");
  956. }
  957. }
  958. if(!handle)
  959. {
  960. handle = getNullHandle();
  961. OWARNLOG("RollingFileLogMsgHandler::doRollover : could not open log file %s for output", filename.str());
  962. // actually this is pretty fatal
  963. }
  964. }
  965. // BinLogMsgHandler
  966. BinLogMsgHandler::BinLogMsgHandler(const char * _filename, bool _append) : filename(_filename), append(_append)
  967. {
  968. file.setown(createIFile(filename.get()));
  969. if(!file) assertex(!"BinLogMsgHandler::BinLogMsgHandler : Could not create IFile");
  970. if(append)
  971. fio.setown(file->open(IFOwrite));
  972. else
  973. fio.setown(file->open(IFOcreate));
  974. if(!fio) assertex(!"BinLogMsgHandler::BinLogMsgHandler : Could not create IFileIO");
  975. fstr.setown(createIOStream(fio));
  976. if(!fstr) assertex(!"BinLogMsgHandler::BinLogMsgHandler : Could not create IFileIOStream");
  977. if(append)
  978. fstr->seek(0, IFSend);
  979. }
  980. BinLogMsgHandler::~BinLogMsgHandler()
  981. {
  982. fstr.clear();
  983. fio.clear();
  984. file.clear();
  985. }
  986. void BinLogMsgHandler::handleMessage(const LogMsg & msg) const
  987. {
  988. CriticalBlock block(crit);
  989. mbuff.clear();
  990. msg.serialize(mbuff);
  991. msglen = mbuff.length();
  992. fstr->write(sizeof(msglen), &msglen);
  993. fstr->write(msglen, mbuff.toByteArray());
  994. }
  995. void BinLogMsgHandler::addToPTree(IPropertyTree * tree) const
  996. {
  997. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  998. handlerTree->setProp("@type", "binary");
  999. handlerTree->setProp("@filename", filename.get());
  1000. if(append) handlerTree->setProp("@append", "true");
  1001. tree->addPropTree("handler", handlerTree);
  1002. }
  1003. char const * BinLogMsgHandler::disable()
  1004. {
  1005. crit.enter();
  1006. fstr.clear();
  1007. fio.clear();
  1008. return filename.get();
  1009. }
  1010. void BinLogMsgHandler::enable()
  1011. {
  1012. fio.setown(file->open(IFOwrite));
  1013. if(!fio) assertex(!"BinLogMsgHandler::enable : Could not create IFileIO");
  1014. fstr.setown(createIOStream(fio));
  1015. if(!fstr) assertex(!"BinLogMsgHandler::enable : Could not create IFileIOStream");
  1016. fstr->seek(0, IFSend);
  1017. crit.leave();
  1018. }
  1019. // LogMsgComponentReporter
  1020. void LogMsgComponentReporter::report(const LogMsgCategory & cat, const char * format, ...)
  1021. {
  1022. va_list args;
  1023. va_start(args, format);
  1024. queryLogMsgManager()->report_va(component, cat, unknownJob, format, args);
  1025. va_end(args);
  1026. }
  1027. void LogMsgComponentReporter::report_va(const LogMsgCategory & cat, const char * format, va_list args)
  1028. {
  1029. queryLogMsgManager()->report_va(component, cat, unknownJob, format, args);
  1030. }
  1031. void LogMsgComponentReporter::report(const LogMsgCategory & cat, LogMsgCode code, const char * format, ...)
  1032. {
  1033. va_list args;
  1034. va_start(args, format);
  1035. queryLogMsgManager()->report_va(component, cat, unknownJob, code, format, args);
  1036. va_end(args);
  1037. }
  1038. void LogMsgComponentReporter::report_va(const LogMsgCategory & cat, LogMsgCode code, const char * format, va_list args)
  1039. {
  1040. queryLogMsgManager()->report_va(component, cat, unknownJob, code, format, args);
  1041. }
  1042. void LogMsgComponentReporter::report(const LogMsgCategory & cat, const IException * exception, const char * prefix)
  1043. {
  1044. StringBuffer buff;
  1045. if(prefix) buff.append(prefix).append(" : ");
  1046. exception->errorMessage(buff);
  1047. queryLogMsgManager()->report(component, cat, unknownJob, exception->errorCode(), "%s", buff.str());
  1048. }
  1049. void LogMsgComponentReporter::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, ...)
  1050. {
  1051. va_list args;
  1052. va_start(args, format);
  1053. queryLogMsgManager()->report_va(component, cat, job, format, args);
  1054. va_end(args);
  1055. }
  1056. void LogMsgComponentReporter::report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, va_list args)
  1057. {
  1058. queryLogMsgManager()->report_va(component, cat, job, format, args);
  1059. }
  1060. void LogMsgComponentReporter::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, ...)
  1061. {
  1062. va_list args;
  1063. va_start(args, format);
  1064. queryLogMsgManager()->report_va(component, cat, job, code, format, args);
  1065. va_end(args);
  1066. }
  1067. void LogMsgComponentReporter::report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, va_list args)
  1068. {
  1069. queryLogMsgManager()->report_va(component, cat, job, code, format, args);
  1070. }
  1071. void LogMsgComponentReporter::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const IException * exception, const char * prefix)
  1072. {
  1073. StringBuffer buff;
  1074. if(prefix) buff.append(prefix).append(" : ");
  1075. exception->errorMessage(buff);
  1076. queryLogMsgManager()->report(component, cat, job, exception->errorCode(), "%s", buff.str());
  1077. }
  1078. void LogMsgComponentReporter::report(const LogMsg & msg)
  1079. {
  1080. queryLogMsgManager()->report(msg);
  1081. }
  1082. // LogMsgPrepender
  1083. void LogMsgPrepender::report(const LogMsgCategory & cat, const char * format, ...)
  1084. {
  1085. StringBuffer buff;
  1086. buff.append(file).append("(").append(line).append(") : ").append(format);
  1087. va_list args;
  1088. va_start(args, format);
  1089. if(reporter)
  1090. reporter->report_va(cat, unknownJob, buff.str(), args);
  1091. else
  1092. queryLogMsgManager()->report_va(cat, unknownJob, buff.str(), args);
  1093. va_end(args);
  1094. }
  1095. void LogMsgPrepender::report_va(const LogMsgCategory & cat, const char * format, va_list args)
  1096. {
  1097. StringBuffer buff;
  1098. buff.append(file).append("(").append(line).append(") : ").append(format);
  1099. if(reporter)
  1100. reporter->report_va(cat, unknownJob, buff.str(), args);
  1101. else
  1102. queryLogMsgManager()->report_va(cat, unknownJob, buff.str(), args);
  1103. }
  1104. void LogMsgPrepender::report(const LogMsgCategory & cat, LogMsgCode code, const char * format, ...)
  1105. {
  1106. StringBuffer buff;
  1107. buff.append(file).append("(").append(line).append(") : ").append(format);
  1108. va_list args;
  1109. va_start(args, format);
  1110. if(reporter)
  1111. reporter->report_va(cat, unknownJob, buff.str(), args);
  1112. else
  1113. queryLogMsgManager()->report_va(cat, unknownJob, buff.str(), args);
  1114. va_end(args);
  1115. }
  1116. void LogMsgPrepender::report_va(const LogMsgCategory & cat, LogMsgCode code, const char * format, va_list args)
  1117. {
  1118. StringBuffer buff;
  1119. buff.append(file).append("(").append(line).append(") : ").append(format);
  1120. if(reporter)
  1121. reporter->report_va(cat, unknownJob, buff.str(), args);
  1122. else
  1123. queryLogMsgManager()->report_va(cat, unknownJob, buff.str(), args);
  1124. }
  1125. void LogMsgPrepender::report(const LogMsgCategory & cat, const IException * exception, const char * prefix)
  1126. {
  1127. StringBuffer buff;
  1128. buff.append(file).append("(").append(line).append(") : ");
  1129. if(prefix) buff.append(prefix).append(" : ");
  1130. exception->errorMessage(buff);
  1131. if(reporter)
  1132. reporter->report(cat, unknownJob, exception->errorCode(), "%s", buff.str());
  1133. else
  1134. queryLogMsgManager()->report(cat, unknownJob, exception->errorCode(), "%s", buff.str());
  1135. }
  1136. void LogMsgPrepender::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, ...)
  1137. {
  1138. StringBuffer buff;
  1139. buff.append(file).append("(").append(line).append(") : ").append(format);
  1140. va_list args;
  1141. va_start(args, format);
  1142. if(reporter)
  1143. reporter->report_va(cat, job, buff.str(), args);
  1144. else
  1145. queryLogMsgManager()->report_va(cat, job, buff.str(), args);
  1146. va_end(args);
  1147. }
  1148. void LogMsgPrepender::report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, va_list args)
  1149. {
  1150. StringBuffer buff;
  1151. buff.append(file).append("(").append(line).append(") : ").append(format);
  1152. if(reporter)
  1153. reporter->report_va(cat, job, buff.str(), args);
  1154. else
  1155. queryLogMsgManager()->report_va(cat, job, buff.str(), args);
  1156. }
  1157. void LogMsgPrepender::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, ...)
  1158. {
  1159. StringBuffer buff;
  1160. buff.append(file).append("(").append(line).append(") : ").append(format);
  1161. va_list args;
  1162. va_start(args, format);
  1163. if(reporter)
  1164. reporter->report_va(cat, job, buff.str(), args);
  1165. else
  1166. queryLogMsgManager()->report_va(cat, job, buff.str(), args);
  1167. va_end(args);
  1168. }
  1169. void LogMsgPrepender::report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, va_list args)
  1170. {
  1171. StringBuffer buff;
  1172. buff.append(file).append("(").append(line).append(") : ").append(format);
  1173. if(reporter)
  1174. reporter->report_va(cat, job, buff.str(), args);
  1175. else
  1176. queryLogMsgManager()->report_va(cat, job, buff.str(), args);
  1177. }
  1178. void LogMsgPrepender::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const IException * exception, const char * prefix)
  1179. {
  1180. StringBuffer txt;
  1181. if (prefix)
  1182. txt.append(prefix).append(" : ");
  1183. exception->errorMessage(txt);
  1184. if (reporter)
  1185. reporter->report(cat, job, exception->errorCode(), "%s(%d) : %s", file, line, txt.str());
  1186. else
  1187. queryLogMsgManager()->report(cat, job, exception->errorCode(), "%s(%d) : %s", file, line, txt.str());
  1188. }
  1189. IException * LogMsgPrepender::report(IException * e, const char * prefix, LogMsgClass cls)
  1190. {
  1191. report(MCexception(e, cls), unknownJob, e, prefix);
  1192. return e;
  1193. }
  1194. // LogMsgMonitor
  1195. void LogMsgMonitor::addToPTree(IPropertyTree * tree) const
  1196. {
  1197. IPropertyTree * monitorTree = createPTree(ipt_caseInsensitive);
  1198. handler->addToPTree(monitorTree);
  1199. filter->addToPTree(monitorTree);
  1200. tree->addPropTree("monitor", monitorTree);
  1201. }
  1202. // CLogMsgManager
  1203. void CLogMsgManager::MsgProcessor::push(LogMsg * msg)
  1204. {
  1205. //assertex(more); an assertex will just recurse here
  1206. if (!more) // we are effective stopped so don't bother even dropping (and leak parameter) as drop will involve
  1207. // interaction with the base class which is stopped and could easily crash (as this condition
  1208. // is expected not to occur - typically occurs if the user has incorrectly called exit on one thread
  1209. // while still in the process of logging on another)
  1210. // cf Bug #53695 for more discussion of the issue
  1211. return;
  1212. else if(droppingLimit && (q.ordinality() >= droppingLimit))
  1213. drop();
  1214. q.enqueue(msg);
  1215. }
  1216. int CLogMsgManager::MsgProcessor::run()
  1217. {
  1218. Owned<LogMsg> msg;
  1219. while(more)
  1220. {
  1221. msg.setown(q.dequeueAndNotify(this)); // notify locks mutex on non-null return
  1222. if(!msg)
  1223. break;
  1224. owner->doReport(*msg);
  1225. pullCycleMutex.unlock();
  1226. }
  1227. while(true)
  1228. {
  1229. msg.setown(q.dequeueNowAndNotify(this)); // notify locks mutex on non-null return
  1230. if(!msg)
  1231. break;
  1232. owner->doReport(*msg);
  1233. pullCycleMutex.unlock();
  1234. }
  1235. return 0;
  1236. }
  1237. void CLogMsgManager::MsgProcessor::notify(LogMsg *)
  1238. {
  1239. pullCycleMutex.lock();
  1240. }
  1241. void CLogMsgManager::MsgProcessor::setBlockingLimit(unsigned lim)
  1242. {
  1243. q.setLimit(lim);
  1244. droppingLimit = 0;
  1245. }
  1246. void CLogMsgManager::MsgProcessor::setDroppingLimit(unsigned lim, unsigned num)
  1247. {
  1248. numToDrop = num;
  1249. droppingLimit = lim;
  1250. q.setLimit(0);
  1251. }
  1252. void CLogMsgManager::MsgProcessor::resetLimit()
  1253. {
  1254. droppingLimit = 0;
  1255. q.setLimit(0);
  1256. }
  1257. void CLogMsgManager::MsgProcessor::stop()
  1258. {
  1259. more = false;
  1260. q.stop();
  1261. }
  1262. void CLogMsgManager::MsgProcessor::drop()
  1263. {
  1264. Owned<LogMsg> msg, lastMsg;
  1265. unsigned count;
  1266. unsigned prev = 0;
  1267. for(count = 0; count < numToDrop; count++)
  1268. {
  1269. msg.setown(q.dequeueTail(0));
  1270. if(!msg) break;
  1271. DropLogMsg * dmsg = dynamic_cast<DropLogMsg *>(msg.get());
  1272. if(dmsg) prev += dmsg->queryCount()-1;
  1273. lastMsg.setown(msg.getClear());
  1274. }
  1275. if(lastMsg)
  1276. q.enqueue(new DropLogMsg(owner, lastMsg->querySysInfo().queryMsgID(), count+prev));
  1277. }
  1278. bool CLogMsgManager::MsgProcessor::flush(unsigned timeout)
  1279. {
  1280. unsigned start = msTick();
  1281. if(!q.waitMaxOrdinality(0, timeout))
  1282. return false;
  1283. unsigned now = msTick();
  1284. if(now >= (start+timeout))
  1285. return false;
  1286. try
  1287. {
  1288. synchronized block(pullCycleMutex, timeout+start-now);
  1289. }
  1290. catch(IException * e)
  1291. {
  1292. e->Release();
  1293. return false;
  1294. }
  1295. return true;
  1296. }
  1297. CLogMsgManager::~CLogMsgManager()
  1298. {
  1299. CriticalBlock crit(modeLock);
  1300. if(processor)
  1301. {
  1302. processor->stop();
  1303. processor->join();
  1304. }
  1305. }
  1306. void CLogMsgManager::enterQueueingMode()
  1307. {
  1308. CriticalBlock crit(modeLock);
  1309. if(processor) return;
  1310. processor.setown(new MsgProcessor(this));
  1311. processor->setBlockingLimit(defaultMsgQueueLimit);
  1312. processor->start();
  1313. }
  1314. void CLogMsgManager::setQueueBlockingLimit(unsigned lim)
  1315. {
  1316. CriticalBlock crit(modeLock);
  1317. if(processor)
  1318. processor->setBlockingLimit(lim);
  1319. }
  1320. void CLogMsgManager::setQueueDroppingLimit(unsigned lim, unsigned numToDrop)
  1321. {
  1322. CriticalBlock crit(modeLock);
  1323. if(processor)
  1324. processor->setDroppingLimit(lim, numToDrop);
  1325. }
  1326. void CLogMsgManager::resetQueueLimit()
  1327. {
  1328. CriticalBlock crit(modeLock);
  1329. if(processor)
  1330. processor->resetLimit();
  1331. }
  1332. void CLogMsgManager::report(const LogMsgCategory & cat, const char * format, ...)
  1333. {
  1334. if(rejectsCategory(cat)) return;
  1335. va_list args;
  1336. va_start(args, format);
  1337. pushMsg(new LogMsg(cat, getNextID(), unknownJob, NoLogMsgCode, format, args, 0, port, session));
  1338. va_end(args);
  1339. }
  1340. void CLogMsgManager::report_va(const LogMsgCategory & cat, const char * format, va_list args)
  1341. {
  1342. if(rejectsCategory(cat)) return;
  1343. pushMsg(new LogMsg(cat, getNextID(), unknownJob, NoLogMsgCode, format, args, 0, port, session));
  1344. }
  1345. void CLogMsgManager::report(const LogMsgCategory & cat, LogMsgCode code, const char * format, ...)
  1346. {
  1347. if(rejectsCategory(cat)) return;
  1348. va_list args;
  1349. va_start(args, format);
  1350. pushMsg(new LogMsg(cat, getNextID(), unknownJob, code, format, args, 0, port, session));
  1351. va_end(args);
  1352. }
  1353. void CLogMsgManager::report_va(const LogMsgCategory & cat, LogMsgCode code, const char * format, va_list args)
  1354. {
  1355. if(rejectsCategory(cat)) return;
  1356. pushMsg(new LogMsg(cat, getNextID(), unknownJob, code, format, args, 0, port, session));
  1357. }
  1358. void CLogMsgManager::report(const LogMsgCategory & cat, const IException * exception, const char * prefix)
  1359. {
  1360. if(rejectsCategory(cat)) return;
  1361. StringBuffer buff;
  1362. if(prefix) buff.append(prefix).append(" : ");
  1363. exception->errorMessage(buff);
  1364. pushMsg(new LogMsg(cat, getNextID(), unknownJob, exception->errorCode(), buff.str(), 0, port, session));
  1365. }
  1366. void CLogMsgManager::report(unsigned compo, const LogMsgCategory & cat, const char * format, ...)
  1367. {
  1368. if(rejectsCategory(cat)) return;
  1369. va_list args;
  1370. va_start(args, format);
  1371. pushMsg(new LogMsg(cat, getNextID(), unknownJob, NoLogMsgCode, format, args, compo, port, session));
  1372. va_end(args);
  1373. }
  1374. void CLogMsgManager::report_va(unsigned compo, const LogMsgCategory & cat, const char * format, va_list args)
  1375. {
  1376. if(rejectsCategory(cat)) return;
  1377. pushMsg(new LogMsg(cat, getNextID(), unknownJob, NoLogMsgCode, format, args, compo, port, session));
  1378. }
  1379. void CLogMsgManager::report(unsigned compo, const LogMsgCategory & cat, LogMsgCode code, const char * format, ...)
  1380. {
  1381. if(rejectsCategory(cat)) return;
  1382. va_list args;
  1383. va_start(args, format);
  1384. pushMsg(new LogMsg(cat, getNextID(), unknownJob, code, format, args, compo, port, session));
  1385. va_end(args);
  1386. }
  1387. void CLogMsgManager::report_va(unsigned compo, const LogMsgCategory & cat, LogMsgCode code, const char * format, va_list args)
  1388. {
  1389. if(rejectsCategory(cat)) return;
  1390. pushMsg(new LogMsg(cat, getNextID(), unknownJob, code, format, args, compo, port, session));
  1391. }
  1392. void CLogMsgManager::report(unsigned compo, const LogMsgCategory & cat, const IException * exception, const char * prefix)
  1393. {
  1394. if(rejectsCategory(cat)) return;
  1395. StringBuffer buff;
  1396. if(prefix) buff.append(prefix).append(" : ");
  1397. exception->errorMessage(buff);
  1398. pushMsg(new LogMsg(cat, getNextID(), unknownJob, exception->errorCode(), buff.str(), compo, port, session));
  1399. }
  1400. void CLogMsgManager::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, ...)
  1401. {
  1402. if(rejectsCategory(cat)) return;
  1403. va_list args;
  1404. va_start(args, format);
  1405. pushMsg(new LogMsg(cat, getNextID(), job, NoLogMsgCode, format, args, 0, port, session));
  1406. va_end(args);
  1407. }
  1408. void CLogMsgManager::report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, va_list args)
  1409. {
  1410. if(rejectsCategory(cat)) return;
  1411. pushMsg(new LogMsg(cat, getNextID(), job, NoLogMsgCode, format, args, 0, port, session));
  1412. }
  1413. void CLogMsgManager::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, ...)
  1414. {
  1415. if(rejectsCategory(cat)) return;
  1416. va_list args;
  1417. va_start(args, format);
  1418. pushMsg(new LogMsg(cat, getNextID(), job, code, format, args, 0, port, session));
  1419. va_end(args);
  1420. }
  1421. void CLogMsgManager::report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, va_list args)
  1422. {
  1423. if(rejectsCategory(cat)) return;
  1424. pushMsg(new LogMsg(cat, getNextID(), job, code, format, args, 0, port, session));
  1425. }
  1426. void CLogMsgManager::report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const IException * exception, const char * prefix)
  1427. {
  1428. if(rejectsCategory(cat)) return;
  1429. StringBuffer buff;
  1430. if(prefix) buff.append(prefix).append(" : ");
  1431. exception->errorMessage(buff);
  1432. pushMsg(new LogMsg(cat, getNextID(), job, exception->errorCode(), buff.str(), 0, port, session));
  1433. }
  1434. void CLogMsgManager::report(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, ...)
  1435. {
  1436. if(rejectsCategory(cat)) return;
  1437. va_list args;
  1438. va_start(args, format);
  1439. pushMsg(new LogMsg(cat, getNextID(), job, NoLogMsgCode, format, args, compo, port, session));
  1440. va_end(args);
  1441. }
  1442. void CLogMsgManager::report_va(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, va_list args)
  1443. {
  1444. if(rejectsCategory(cat)) return;
  1445. pushMsg(new LogMsg(cat, getNextID(), job, NoLogMsgCode, format, args, compo, port, session));
  1446. }
  1447. void CLogMsgManager::report(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, ...)
  1448. {
  1449. if(rejectsCategory(cat)) return;
  1450. va_list args;
  1451. va_start(args, format);
  1452. pushMsg(new LogMsg(cat, getNextID(), job, code, format, args, compo, port, session));
  1453. va_end(args);
  1454. }
  1455. void CLogMsgManager::report_va(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, va_list args)
  1456. {
  1457. if(rejectsCategory(cat)) return;
  1458. pushMsg(new LogMsg(cat, getNextID(), job, code, format, args, compo, port, session));
  1459. }
  1460. void CLogMsgManager::report(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, const IException * exception, const char * prefix)
  1461. {
  1462. if(rejectsCategory(cat)) return;
  1463. StringBuffer buff;
  1464. if(prefix) buff.append(prefix).append(" : ");
  1465. exception->errorMessage(buff);
  1466. pushMsg(new LogMsg(cat, getNextID(), job, exception->errorCode(), buff.str(), compo, port, session));
  1467. }
  1468. void CLogMsgManager::pushMsg(LogMsg * _msg)
  1469. {
  1470. Owned<LogMsg> msg(_msg);
  1471. if(processor)
  1472. processor->push(msg.getLink());
  1473. else
  1474. doReport(*msg);
  1475. }
  1476. void CLogMsgManager::doReport(const LogMsg & msg) const
  1477. {
  1478. try
  1479. {
  1480. ReadLockBlock block(monitorLock);
  1481. ForEachItemIn(i, monitors)
  1482. monitors.item(i).processMessage(msg);
  1483. }
  1484. catch(IException * e)
  1485. {
  1486. StringBuffer err("exception reporting log message: ");
  1487. err.append(e->errorCode());
  1488. e->errorMessage(err);
  1489. panic(err.str());
  1490. e->Release();
  1491. }
  1492. catch(...)
  1493. {
  1494. panic("unknown exception reporting log message");
  1495. }
  1496. }
  1497. void CLogMsgManager::panic(char const * reason) const
  1498. {
  1499. fprintf(stderr, "%s", reason); // not sure there's anything more useful we can do here
  1500. }
  1501. offset_t CLogMsgManager::getLogPosition(StringBuffer &logFileName, const ILogMsgHandler * handler) const
  1502. {
  1503. if (processor)
  1504. processor->flush(10*1000);
  1505. WriteLockBlock block(monitorLock); // Prevents any incoming messages as we are doing this
  1506. return handler->getLogPosition(logFileName);
  1507. }
  1508. aindex_t CLogMsgManager::find(const ILogMsgHandler * handler) const
  1509. {
  1510. // N.B. Should be used inside critical block
  1511. ForEachItemIn(i, monitors)
  1512. if(monitors.item(i).queryHandler()==handler) return i;
  1513. return NotFound;
  1514. }
  1515. bool CLogMsgManager::addMonitor(ILogMsgHandler * handler, ILogMsgFilter * filter)
  1516. {
  1517. flushQueue(10*1000);
  1518. WriteLockBlock block(monitorLock);
  1519. if(find(handler) != NotFound) return false;
  1520. monitors.append(*(new LogMsgMonitor(filter, handler)));
  1521. prefilter.orWithFilter(filter);
  1522. sendFilterToChildren(true);
  1523. return true;
  1524. }
  1525. bool CLogMsgManager::addMonitorOwn(ILogMsgHandler * handler, ILogMsgFilter * filter)
  1526. {
  1527. bool ret = addMonitor(handler, filter);
  1528. filter->Release();
  1529. handler->Release();
  1530. return ret;
  1531. }
  1532. void CLogMsgManager::buildPrefilter()
  1533. {
  1534. // N.B. Should be used inside critical block
  1535. prefilter.reset();
  1536. ForEachItemIn(i, monitors)
  1537. prefilter.orWithFilter(monitors.item(i).queryFilter());
  1538. }
  1539. bool CLogMsgManager::removeMonitor(ILogMsgHandler * handler)
  1540. {
  1541. Linked<LogMsgMonitor> todelete;
  1542. {
  1543. WriteLockBlock block(monitorLock);
  1544. aindex_t pos = find(handler);
  1545. if(pos == NotFound) return false;
  1546. todelete.set(&monitors.item(pos));
  1547. monitors.remove(pos);
  1548. buildPrefilter();
  1549. sendFilterToChildren(true);
  1550. return true;
  1551. }
  1552. }
  1553. unsigned CLogMsgManager::removeMonitorsMatching(HandlerTest & test)
  1554. {
  1555. CIArrayOf<LogMsgMonitor> todelete; // delete outside monitorLock
  1556. unsigned count = 0;
  1557. {
  1558. WriteLockBlock block(monitorLock);
  1559. ForEachItemInRev(i, monitors)
  1560. if(test(monitors.item(i).queryHandler()))
  1561. {
  1562. LogMsgMonitor &it = monitors.item(i);
  1563. it.Link();
  1564. todelete.append(it);
  1565. monitors.remove(i);
  1566. ++count;
  1567. }
  1568. buildPrefilter();
  1569. sendFilterToChildren(true);
  1570. }
  1571. return count;
  1572. }
  1573. void CLogMsgManager::removeAllMonitors()
  1574. {
  1575. CIArrayOf<LogMsgMonitor> todelete; // delete outside monitorLock
  1576. {
  1577. WriteLockBlock block(monitorLock);
  1578. ForEachItemInRev(i, monitors) {
  1579. LogMsgMonitor &it = monitors.item(i);
  1580. it.Link();
  1581. todelete.append(it);
  1582. monitors.remove(i);
  1583. }
  1584. prefilter.reset();
  1585. sendFilterToChildren(true);
  1586. }
  1587. }
  1588. void CLogMsgManager::resetMonitors()
  1589. {
  1590. suspendChildren();
  1591. removeAllMonitors();
  1592. Owned<ILogMsgFilter> defaultFilter = getDefaultLogMsgFilter();
  1593. addMonitor(theStderrHandler, defaultFilter);
  1594. unsuspendChildren();
  1595. }
  1596. ILogMsgFilter * CLogMsgManager::queryMonitorFilter(const ILogMsgHandler * handler) const
  1597. {
  1598. ReadLockBlock block(monitorLock);
  1599. aindex_t pos = find(handler);
  1600. if(pos == NotFound) return 0;
  1601. return monitors.item(pos).queryFilter();
  1602. }
  1603. bool CLogMsgManager::changeMonitorFilter(const ILogMsgHandler * handler, ILogMsgFilter * newFilter)
  1604. {
  1605. WriteLockBlock block(monitorLock);
  1606. aindex_t pos = find(handler);
  1607. if(pos == NotFound) return 0;
  1608. monitors.item(pos).setFilter(newFilter);
  1609. buildPrefilter();
  1610. sendFilterToChildren(true);
  1611. return true;
  1612. }
  1613. void CLogMsgManager::prepAllHandlers() const
  1614. {
  1615. ReadLockBlock block(monitorLock);
  1616. ForEachItemIn(i, monitors)
  1617. if(monitors.item(i).queryHandler()->needsPrep()) monitors.item(i).queryHandler()->prep();
  1618. }
  1619. aindex_t CLogMsgManager::findChild(ILogMsgLinkToChild * child) const
  1620. {
  1621. ForEachItemIn(i, children)
  1622. if(&(children.item(i)) == child ) return i;
  1623. return NotFound;
  1624. }
  1625. ILogMsgFilter * CLogMsgManager::getCompoundFilter(bool locked) const
  1626. {
  1627. if(!locked) monitorLock.lockRead();
  1628. Owned<CategoryLogMsgFilter> categoryFilter = new CategoryLogMsgFilter(0, 0, 0, false);
  1629. Owned<ILogMsgFilter> otherFilters;
  1630. ILogMsgFilter * ifilter;
  1631. bool hadCat = false;
  1632. ForEachItemIn(i, monitors)
  1633. {
  1634. ifilter = monitors.item(i).queryFilter();
  1635. if(ifilter->queryLocalFlag()) continue;
  1636. if(ifilter->isCategoryFilter())
  1637. {
  1638. categoryFilter->orWithFilter(ifilter);
  1639. hadCat = true;
  1640. }
  1641. else
  1642. {
  1643. if(otherFilters)
  1644. otherFilters.setown(getOrLogMsgFilter(otherFilters, ifilter));
  1645. else
  1646. otherFilters.set(ifilter);
  1647. }
  1648. }
  1649. if(hadCat)
  1650. {
  1651. if(otherFilters)
  1652. otherFilters.setown(getOrLogMsgFilter(otherFilters, categoryFilter));
  1653. else
  1654. otherFilters.set(categoryFilter);
  1655. }
  1656. if(!locked) monitorLock.unlock();
  1657. if(!otherFilters)
  1658. return getPassNoneLogMsgFilter();
  1659. return otherFilters.getLink();
  1660. }
  1661. void CLogMsgManager::sendFilterToChildren(bool locked) const
  1662. {
  1663. if(suspendedChildren) return;
  1664. ReadLockBlock block(childLock);
  1665. if(children.length()==0) return;
  1666. ILogMsgFilter * filter = getCompoundFilter(locked);
  1667. ForEachItemIn(i, children)
  1668. children.item(i).sendFilter(filter);
  1669. filter->Release();
  1670. }
  1671. bool CLogMsgManager::addMonitorToPTree(const ILogMsgHandler * handler, IPropertyTree * tree) const
  1672. {
  1673. ReadLockBlock block(monitorLock);
  1674. aindex_t pos = find(handler);
  1675. if(pos == NotFound) return false;
  1676. monitors.item(pos).addToPTree(tree);
  1677. return true;
  1678. }
  1679. void CLogMsgManager::addAllMonitorsToPTree(IPropertyTree * tree) const
  1680. {
  1681. ReadLockBlock block(monitorLock);
  1682. ForEachItemIn(i, monitors)
  1683. monitors.item(i).addToPTree(tree);
  1684. }
  1685. bool CLogMsgManager::rejectsCategory(const LogMsgCategory & cat) const
  1686. {
  1687. if (!prefilter.includeCategory(cat))
  1688. return true;
  1689. ReadLockBlock block(monitorLock);
  1690. ForEachItemIn(i, monitors)
  1691. {
  1692. if (monitors.item(i).queryFilter()->mayIncludeCategory(cat))
  1693. return false;
  1694. }
  1695. return true;
  1696. }
  1697. // Helper functions
  1698. ILogMsgFilter * getDeserializedLogMsgFilter(MemoryBuffer & in)
  1699. {
  1700. unsigned type;
  1701. in.read(type);
  1702. switch(type)
  1703. {
  1704. case MSGFILTER_passall : return LINK(thePassAllFilter);
  1705. case MSGFILTER_passlocal : return LINK(thePassLocalFilter);
  1706. case MSGFILTER_passnone : return LINK(thePassNoneFilter);
  1707. case MSGFILTER_category : return new CategoryLogMsgFilter(in);
  1708. case MSGFILTER_pid : return new PIDLogMsgFilter(in);
  1709. case MSGFILTER_tid : return new TIDLogMsgFilter(in);
  1710. case MSGFILTER_node : return new NodeLogMsgFilter(in);
  1711. case MSGFILTER_ip : return new IpLogMsgFilter(in);
  1712. case MSGFILTER_job : return new JobLogMsgFilter(in);
  1713. case MSGFILTER_user : return new UserLogMsgFilter(in);
  1714. case MSGFILTER_session : return new SessionLogMsgFilter(in);
  1715. case MSGFILTER_component : return new ComponentLogMsgFilter(in);
  1716. case MSGFILTER_regex : return new RegexLogMsgFilter(in);
  1717. case MSGFILTER_not : return new NotLogMsgFilter(in);
  1718. case MSGFILTER_and : return new AndLogMsgFilter(in);
  1719. case MSGFILTER_or : return new OrLogMsgFilter(in);
  1720. case MSGFILTER_switch : return new SwitchLogMsgFilter(in);
  1721. default: assertex(!"getDeserializedLogMsgFilter: unrecognized LogMsgFilterType");
  1722. }
  1723. return 0;
  1724. }
  1725. ILogMsgFilter * getLogMsgFilterFromPTree(IPropertyTree * xml)
  1726. {
  1727. /* Note that several of these constructors use GetPropInt and GetPropInt64 to get unsigneds. I think this is OK? (all int64 internally)*/
  1728. StringBuffer type;
  1729. xml->getProp("@type", type);
  1730. if(strcmp(type.str(), "all")==0) return LINK(thePassAllFilter);
  1731. else if(strcmp(type.str(), "local")==0) return LINK(thePassLocalFilter);
  1732. else if(strcmp(type.str(), "none")==0) return LINK(thePassNoneFilter);
  1733. else if(strcmp(type.str(), "category")==0) return new CategoryLogMsgFilter(xml);
  1734. else if(strcmp(type.str(), "pid")==0) return new PIDLogMsgFilter(xml);
  1735. else if(strcmp(type.str(), "tid")==0) return new TIDLogMsgFilter(xml);
  1736. else if(strcmp(type.str(), "node")==0) return new NodeLogMsgFilter(xml);
  1737. else if(strcmp(type.str(), "ip")==0) return new IpLogMsgFilter(xml);
  1738. else if(strcmp(type.str(), "job")==0) return new JobLogMsgFilter(xml);
  1739. else if(strcmp(type.str(), "user")==0) return new UserLogMsgFilter(xml);
  1740. else if(strcmp(type.str(), "session")==0) return new SessionLogMsgFilter(xml);
  1741. else if(strcmp(type.str(), "component")==0) return new ComponentLogMsgFilter(xml);
  1742. else if(strcmp(type.str(), "regex")==0) return new RegexLogMsgFilter(xml);
  1743. else if(strcmp(type.str(), "not")==0) return new NotLogMsgFilter(xml);
  1744. else if(strcmp(type.str(), "and")==0) return new AndLogMsgFilter(xml);
  1745. else if(strcmp(type.str(), "or")==0) return new OrLogMsgFilter(xml);
  1746. else if(strcmp(type.str(), "filter")==0) return new SwitchLogMsgFilter(xml);
  1747. else assertex(!"getLogMsgFilterFromPTree : unrecognized LogMsgFilter type");
  1748. return getPassAllLogMsgFilter();
  1749. }
  1750. ILogMsgFilter * getDefaultLogMsgFilter()
  1751. {
  1752. return new CategoryLogMsgFilter(MSGAUD_all, MSGCLS_all, DefaultDetail, true);
  1753. }
  1754. ILogMsgFilter * getPassAllLogMsgFilter()
  1755. {
  1756. return LINK(thePassAllFilter);
  1757. }
  1758. ILogMsgFilter * getLocalLogMsgFilter()
  1759. {
  1760. return LINK(thePassLocalFilter);
  1761. }
  1762. ILogMsgFilter * getPassNoneLogMsgFilter()
  1763. {
  1764. return LINK(thePassNoneFilter);
  1765. }
  1766. ILogMsgFilter * queryPassAllLogMsgFilter()
  1767. {
  1768. return thePassAllFilter;
  1769. }
  1770. ILogMsgFilter * queryLocalLogMsgFilter()
  1771. {
  1772. return thePassLocalFilter;
  1773. }
  1774. ILogMsgFilter * queryPassNoneLogMsgFilter()
  1775. {
  1776. return thePassNoneFilter;
  1777. }
  1778. ILogMsgFilter * getCategoryLogMsgFilter(unsigned audiences, unsigned classes, LogMsgDetail maxDetail, bool local)
  1779. {
  1780. if((audiences==MSGAUD_all) && (classes==MSGCLS_all) && (maxDetail==TopDetail))
  1781. {
  1782. if(local)
  1783. return LINK(thePassLocalFilter);
  1784. else
  1785. return LINK(thePassAllFilter);
  1786. }
  1787. return new CategoryLogMsgFilter(audiences, classes, maxDetail, local);
  1788. }
  1789. ILogMsgFilter * getPIDLogMsgFilter(unsigned pid, bool local)
  1790. {
  1791. return new PIDLogMsgFilter(pid, local);
  1792. }
  1793. ILogMsgFilter * getTIDLogMsgFilter(unsigned tid, bool local)
  1794. {
  1795. return new TIDLogMsgFilter(tid, local);
  1796. }
  1797. ILogMsgFilter * getNodeLogMsgFilter(const char * name, unsigned port, bool local)
  1798. {
  1799. return new NodeLogMsgFilter(name, port, local);
  1800. }
  1801. ILogMsgFilter * getNodeLogMsgFilter(const IpAddress & ip, unsigned port, bool local)
  1802. {
  1803. return new NodeLogMsgFilter(ip, port, local);
  1804. }
  1805. ILogMsgFilter * getNodeLogMsgFilter(unsigned port, bool local)
  1806. {
  1807. return new NodeLogMsgFilter(port, local);
  1808. }
  1809. ILogMsgFilter * getIpLogMsgFilter(const char * name, bool local)
  1810. {
  1811. return new IpLogMsgFilter(name, local);
  1812. }
  1813. ILogMsgFilter * getIpLogMsgFilter(const IpAddress & ip, bool local)
  1814. {
  1815. return new IpLogMsgFilter(ip, local);
  1816. }
  1817. ILogMsgFilter * getIpLogMsgFilter(bool local)
  1818. {
  1819. return new IpLogMsgFilter(local);
  1820. }
  1821. ILogMsgFilter * getJobLogMsgFilter(LogMsgJobId job, bool local)
  1822. {
  1823. return new JobLogMsgFilter(job, local);
  1824. }
  1825. ILogMsgFilter * getUserLogMsgFilter(LogMsgUserId user, bool local)
  1826. {
  1827. return new UserLogMsgFilter(user, local);
  1828. }
  1829. ILogMsgFilter * getSessionLogMsgFilter(LogMsgSessionId session, bool local)
  1830. {
  1831. return new SessionLogMsgFilter(session, local);
  1832. }
  1833. ILogMsgFilter * getComponentLogMsgFilter(unsigned component, bool local)
  1834. {
  1835. return new ComponentLogMsgFilter(component, local);
  1836. }
  1837. ILogMsgFilter * getRegexLogMsgFilter(const char *regex, bool local)
  1838. {
  1839. return new RegexLogMsgFilter(regex, local);
  1840. }
  1841. ILogMsgFilter * getNotLogMsgFilter(ILogMsgFilter * arg)
  1842. {
  1843. return new NotLogMsgFilter(arg);
  1844. }
  1845. ILogMsgFilter * getNotLogMsgFilterOwn(ILogMsgFilter * arg)
  1846. {
  1847. ILogMsgFilter * ret = new NotLogMsgFilter(arg);
  1848. arg->Release();
  1849. return ret;
  1850. }
  1851. ILogMsgFilter * getAndLogMsgFilter(ILogMsgFilter * arg1, ILogMsgFilter * arg2)
  1852. {
  1853. return new AndLogMsgFilter(arg1, arg2);
  1854. }
  1855. ILogMsgFilter * getAndLogMsgFilterOwn(ILogMsgFilter * arg1, ILogMsgFilter * arg2)
  1856. {
  1857. ILogMsgFilter * ret = new AndLogMsgFilter(arg1, arg2);
  1858. arg1->Release();
  1859. arg2->Release();
  1860. return ret;
  1861. }
  1862. ILogMsgFilter * getOrLogMsgFilter(ILogMsgFilter * arg1, ILogMsgFilter * arg2)
  1863. {
  1864. return new OrLogMsgFilter(arg1, arg2);
  1865. }
  1866. ILogMsgFilter * getOrLogMsgFilterOwn(ILogMsgFilter * arg1, ILogMsgFilter * arg2)
  1867. {
  1868. ILogMsgFilter * ret = new OrLogMsgFilter(arg1, arg2);
  1869. arg1->Release();
  1870. arg2->Release();
  1871. return ret;
  1872. }
  1873. ILogMsgFilter * getSwitchLogMsgFilterOwn(ILogMsgFilter * switchFilter, ILogMsgFilter * yesFilter, ILogMsgFilter * noFilter)
  1874. {
  1875. ILogMsgFilter * ret = new SwitchLogMsgFilter(switchFilter, yesFilter, noFilter);
  1876. switchFilter->Release();
  1877. yesFilter->Release();
  1878. noFilter->Release();
  1879. return ret;
  1880. }
  1881. ILogMsgHandler * getHandleLogMsgHandler(FILE * handle, unsigned fields, bool writeXML)
  1882. {
  1883. if(writeXML)
  1884. return new HandleLogMsgHandlerXML(handle, fields);
  1885. return new HandleLogMsgHandlerTable(handle, fields);
  1886. }
  1887. ILogMsgHandler * getFileLogMsgHandler(const char * filename, const char * headertext, unsigned fields, bool writeXML, bool append, bool flushes)
  1888. {
  1889. if(writeXML)
  1890. return new FileLogMsgHandlerXML(filename, headertext, fields, append, flushes);
  1891. return new FileLogMsgHandlerTable(filename, headertext, fields, append, flushes);
  1892. }
  1893. ILogMsgHandler * getRollingFileLogMsgHandler(const char * filebase, const char * fileextn, unsigned fields, bool append, bool flushes, const char *initialName, const char *alias, bool daily)
  1894. {
  1895. return new RollingFileLogMsgHandler(filebase, fileextn, fields, append, flushes, initialName, alias, daily);
  1896. }
  1897. ILogMsgHandler * getBinLogMsgHandler(const char * filename, bool append)
  1898. {
  1899. return new BinLogMsgHandler(filename, append);
  1900. }
  1901. void installLogMsgFilterSwitch(ILogMsgHandler * handler, ILogMsgFilter * switchFilter, ILogMsgFilter * newFilter)
  1902. {
  1903. queryLogMsgManager()->changeMonitorFilterOwn(handler, getSwitchLogMsgFilterOwn(switchFilter, newFilter, queryLogMsgManager()->getMonitorFilter(handler)));
  1904. }
  1905. ILogMsgHandler * getLogMsgHandlerFromPTree(IPropertyTree * tree)
  1906. {
  1907. StringBuffer type;
  1908. tree->getProp("@type", type);
  1909. unsigned fields = MSGFIELD_all;
  1910. char const * fstr = tree->queryProp("@fields");
  1911. if(fstr)
  1912. {
  1913. if(isdigit(fstr[0]))
  1914. fields = atoi(fstr);
  1915. else
  1916. fields = LogMsgFieldsFromAbbrevs(fstr);
  1917. }
  1918. if(strcmp(type.str(), "stderr")==0)
  1919. return getHandleLogMsgHandler(stderr, fields, tree->hasProp("@writeXML"));
  1920. else if(strcmp(type.str(), "file")==0)
  1921. {
  1922. StringBuffer filename;
  1923. tree->getProp("@filename", filename);
  1924. if(tree->hasProp("@headertext"))
  1925. {
  1926. StringBuffer headertext;
  1927. tree->getProp("@headertext", headertext);
  1928. return getFileLogMsgHandler(filename.str(), headertext.str(), fields, !(tree->hasProp("@writeTable")), tree->hasProp("@append"), tree->hasProp("@flushes"));
  1929. }
  1930. else
  1931. return getFileLogMsgHandler(filename.str(), 0, fields, !(tree->hasProp("@writeTable")), tree->hasProp("@append"), tree->hasProp("@flushes"));
  1932. }
  1933. else if(strcmp(type.str(), "binary")==0)
  1934. {
  1935. StringBuffer filename;
  1936. tree->getProp("@filename", filename);
  1937. return getBinLogMsgHandler(filename.str(), tree->hasProp("@append"));
  1938. }
  1939. else assertex(!"getLogMsgFilterFromPTree : unrecognized LogMsgHandler type");
  1940. return LINK(theStderrHandler);
  1941. }
  1942. ILogMsgHandler * attachStandardFileLogMsgMonitor(const char * filename, const char * headertext, unsigned fields, unsigned audiences, unsigned classes, LogMsgDetail detail, bool writeXML, bool append, bool flushes, bool local)
  1943. {
  1944. #ifdef FILE_LOG_ENABLES_QUEUEUING
  1945. queryLogMsgManager()->enterQueueingMode();
  1946. #endif
  1947. ILogMsgFilter * filter = getCategoryLogMsgFilter(audiences, classes, detail, local);
  1948. ILogMsgHandler * handler = getFileLogMsgHandler(filename, headertext, fields, writeXML, append, flushes);
  1949. queryLogMsgManager()->addMonitorOwn(handler, filter);
  1950. return handler;
  1951. }
  1952. ILogMsgHandler * attachStandardBinLogMsgMonitor(const char * filename, unsigned audiences, unsigned classes, LogMsgDetail detail, bool append, bool local)
  1953. {
  1954. #ifdef FILE_LOG_ENABLES_QUEUEUING
  1955. queryLogMsgManager()->enterQueueingMode();
  1956. #endif
  1957. ILogMsgFilter * filter = getCategoryLogMsgFilter(audiences, classes, detail, local);
  1958. ILogMsgHandler * handler = getBinLogMsgHandler(filename, append);
  1959. queryLogMsgManager()->addMonitorOwn(handler, filter);
  1960. return handler;
  1961. }
  1962. ILogMsgHandler * attachStandardHandleLogMsgMonitor(FILE * handle, unsigned fields, unsigned audiences, unsigned classes, LogMsgDetail detail, bool writeXML, bool local)
  1963. {
  1964. ILogMsgFilter * filter = getCategoryLogMsgFilter(audiences, classes, detail, local);
  1965. ILogMsgHandler * handler = getHandleLogMsgHandler(handle, fields, writeXML);
  1966. queryLogMsgManager()->addMonitorOwn(handler, filter);
  1967. return handler;
  1968. }
  1969. ILogMsgHandler * attachLogMsgMonitorFromPTree(IPropertyTree * tree)
  1970. {
  1971. Owned<IPropertyTree> handlertree = tree->getPropTree("handler");
  1972. Owned<IPropertyTree> filtertree = tree->getPropTree("filter");
  1973. ILogMsgHandler * handler = getLogMsgHandlerFromPTree(handlertree);
  1974. ILogMsgFilter * filter = getLogMsgFilterFromPTree(filtertree);
  1975. queryLogMsgManager()->addMonitorOwn(handler, filter);
  1976. return handler;
  1977. }
  1978. void attachManyLogMsgMonitorsFromPTree(IPropertyTree * tree)
  1979. {
  1980. Owned<IPropertyTreeIterator> iter = tree->getElements("monitor");
  1981. ForEach(*iter)
  1982. attachLogMsgMonitorFromPTree(&(iter->query()));
  1983. }
  1984. const LogMsgJobInfo unknownJob(UnknownJob, UnknownUser);
  1985. // Calls to make, remove, and return the manager, standard handler, pass all/none filters, reporter array
  1986. PassAllLogMsgFilter * thePassAllFilter;
  1987. PassLocalLogMsgFilter * thePassLocalFilter;
  1988. PassNoneLogMsgFilter * thePassNoneFilter;
  1989. HandleLogMsgHandlerTable * theStderrHandler;
  1990. CLogMsgManager * theManager;
  1991. CSysLogEventLogger * theSysLogEventLogger;
  1992. LogMsgComponentReporter * theReporters[MSGCOMP_NUMBER];
  1993. MODULE_INIT(INIT_PRIORITY_JLOG)
  1994. {
  1995. thePassAllFilter = new PassAllLogMsgFilter();
  1996. thePassLocalFilter = new PassLocalLogMsgFilter();
  1997. thePassNoneFilter = new PassNoneLogMsgFilter();
  1998. theStderrHandler = new HandleLogMsgHandlerTable(stderr, MSGFIELD_STANDARD);
  1999. theSysLogEventLogger = new CSysLogEventLogger;
  2000. theManager = new CLogMsgManager();
  2001. theManager->resetMonitors();
  2002. for(unsigned compo = 0; compo<MSGCOMP_NUMBER; compo++)
  2003. theReporters[compo] = new LogMsgComponentReporter(compo);
  2004. return true;
  2005. }
  2006. MODULE_EXIT()
  2007. {
  2008. for(unsigned compo = 0; compo<MSGCOMP_NUMBER; compo++)
  2009. {
  2010. delete theReporters[compo];
  2011. theReporters[compo] = NULL;
  2012. }
  2013. delete theManager;
  2014. delete theSysLogEventLogger;
  2015. delete theStderrHandler;
  2016. delete thePassNoneFilter;
  2017. delete thePassLocalFilter;
  2018. delete thePassAllFilter;
  2019. theManager = NULL;
  2020. theSysLogEventLogger = NULL;
  2021. theStderrHandler = NULL;
  2022. thePassNoneFilter = NULL;
  2023. thePassLocalFilter = NULL;
  2024. thePassAllFilter = NULL;
  2025. }
  2026. ILogMsgManager * queryLogMsgManager()
  2027. {
  2028. return theManager;
  2029. }
  2030. ILogMsgHandler * queryStderrLogMsgHandler()
  2031. {
  2032. return theStderrHandler;
  2033. }
  2034. LogMsgComponentReporter * queryLogMsgComponentReporter(unsigned compo)
  2035. {
  2036. return theReporters[compo];
  2037. }
  2038. ILogMsgManager * createLogMsgManager() // use with care! (needed by mplog listener facility)
  2039. {
  2040. return new CLogMsgManager();
  2041. }
  2042. // Event Logging
  2043. ISysLogEventLogger * querySysLogEventLogger()
  2044. {
  2045. return theSysLogEventLogger;
  2046. }
  2047. ILogMsgHandler * getSysLogMsgHandler(unsigned fields)
  2048. {
  2049. return new SysLogMsgHandler(theSysLogEventLogger, fields);
  2050. }
  2051. #ifdef _WIN32
  2052. #include <WINNT.H>
  2053. #include "jelog.h"
  2054. struct AuditTypeWin32Data
  2055. {
  2056. public:
  2057. unsigned eventtype;
  2058. unsigned categoryid;
  2059. unsigned eventid;
  2060. };
  2061. #define CATEGORY_AUDIT_FUNCTION_REQUIRED
  2062. #define AUDIT_TYPES_BEGIN AuditTypeWin32Data auditTypeDataMap[NUM_AUDIT_TYPES+1] = {
  2063. #define MAKE_AUDIT_TYPE(name, type, categoryid, eventid, level) {type, categoryid, eventid},
  2064. #define AUDIT_TYPES_END {0, 0, 0} };
  2065. #include "jelogtype.hpp"
  2066. #undef CATEGORY_AUDIT_FUNCTION_REQUIRED
  2067. #undef AUDIT_TYPES_BEGIN
  2068. #undef MAKE_AUDIT_TYPE
  2069. #undef AUDIT_TYPES_END
  2070. CSysLogEventLogger::CSysLogEventLogger() : hEventLog(0)
  2071. {
  2072. }
  2073. bool CSysLogEventLogger::log(AuditType auditType, char const * msg, size32_t datasize, void const * data)
  2074. {
  2075. assertex(auditType < NUM_AUDIT_TYPES);
  2076. AuditTypeWin32Data const & typeData = auditTypeDataMap[auditType];
  2077. return win32Report(typeData.eventtype, typeData.categoryid, typeData.eventid, msg, datasize, data);
  2078. }
  2079. bool CSysLogEventLogger::win32Report(unsigned eventtype, unsigned category, unsigned eventid, const char * msg, size32_t datasize, const void * data)
  2080. {
  2081. if (hEventLog==0) {
  2082. // MORE - this doesn't work on Vista/Win7 as can't copy to system32...
  2083. // Perhaps we should just kill this code
  2084. char path[_MAX_PATH+1];
  2085. GetEnvironmentVariable("SystemRoot",path,sizeof(path));
  2086. strcat(path,"\\System32\\JELOG.dll");
  2087. Owned<IFile> file = createIFile(path);
  2088. try {
  2089. if (!file->exists()) {
  2090. char src[_MAX_PATH+1];
  2091. LPTSTR tail;
  2092. DWORD res = SearchPath(NULL,"JELOG.DLL",NULL,sizeof(src),src,&tail);
  2093. if (res>0)
  2094. copyFile(path,src);
  2095. else
  2096. throw makeOsException(GetLastError());
  2097. }
  2098. }
  2099. catch (IException *e)
  2100. {
  2101. EXCLOG(e, "reportEventLog: Could not install JELOG.DLL");
  2102. hEventLog=(HANDLE)-1;
  2103. e->Release();
  2104. return false;
  2105. }
  2106. HKEY hk;
  2107. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\Seisint",
  2108. NULL, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, NULL)==0) {
  2109. DWORD sizedata = 0;
  2110. DWORD type = REG_EXPAND_SZ;
  2111. if ((RegQueryValueEx(hk,"EventMessageFile",NULL, &type, NULL, &sizedata)!=0)||!sizedata) {
  2112. StringAttr str("%SystemRoot%\\System32\\JELOG.dll");
  2113. RegSetValueEx(hk,"EventMessageFile", 0, REG_EXPAND_SZ, (LPBYTE) str.get(), (DWORD)str.length() + 1);
  2114. RegSetValueEx(hk,"CategoryMessageFile", 0, REG_EXPAND_SZ, (LPBYTE) str.get(), (DWORD)str.length() + 1);
  2115. DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE;
  2116. RegSetValueEx(hk, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwData, sizeof(DWORD));
  2117. dwData = 16;
  2118. RegSetValueEx(hk, "CategoryCount", 0, REG_DWORD, (LPBYTE) &dwData, sizeof(DWORD));
  2119. }
  2120. RegCloseKey(hk);
  2121. }
  2122. hEventLog = RegisterEventSource(NULL,"Seisint");
  2123. if (!hEventLog) {
  2124. OERRLOG("reportEventLog: Could not register Seisint event source");
  2125. hEventLog=(HANDLE)-1;
  2126. return false;
  2127. }
  2128. }
  2129. if (hEventLog==(HANDLE)-1)
  2130. return false;
  2131. assertex((unsigned)eventtype<=16);
  2132. if (!data)
  2133. datasize = 0;
  2134. else if (!datasize)
  2135. data = NULL;
  2136. #if 1 //useful for debugging...
  2137. ReportEvent(hEventLog, eventtype, category, eventid, NULL, 1, datasize, &msg, (LPVOID)data);
  2138. #else
  2139. if(datasize)
  2140. {
  2141. char * buff = (char *)malloc(datasize*3+1);
  2142. unsigned char const * cdata = (unsigned char *)data;
  2143. unsigned i;
  2144. for(i=0; i<datasize; i++)
  2145. sprintf(buff+i*3, "%02X ", cdata[i]);
  2146. buff[datasize*3-1] = 0;
  2147. DBGLOG("ReportEvent: type=%X categoryid=%X eventid=%X msg='%s' data=[%s]", eventtype, category, eventid, msg, buff);
  2148. free(buff);
  2149. }
  2150. else
  2151. DBGLOG("ReportEvent: type=%X categoryid=%X eventid=%X msg='%s'", eventtype, category, eventid, msg);
  2152. #endif
  2153. return true;
  2154. }
  2155. CSysLogEventLogger::~CSysLogEventLogger()
  2156. {
  2157. if (hEventLog!=0)
  2158. DeregisterEventSource(hEventLog);
  2159. }
  2160. #else
  2161. #include <syslog.h>
  2162. #define CATEGORY_AUDIT_FUNCTION_REQUIRED
  2163. #define AUDIT_TYPES_BEGIN int auditTypeDataMap[NUM_AUDIT_TYPES+1] = {
  2164. #define MAKE_AUDIT_TYPE(name, type, categoryid, eventid, level) level,
  2165. #define AUDIT_TYPES_END 0 };
  2166. #include "jelogtype.hpp"
  2167. #undef CATEGORY_AUDIT_FUNCTION_REQUIRED
  2168. #undef AUDIT_TYPES_BEGIN
  2169. #undef MAKE_AUDIT_TYPE
  2170. #undef AUDIT_TYPES_END
  2171. CSysLogEventLogger::CSysLogEventLogger() : dataLogUsed(false), dataLogName(0), dataLogFile(-1)
  2172. {
  2173. StringBuffer folder;
  2174. const char * processName = splitDirTail(queryCurrentProcessPath(), folder);
  2175. if (!processName||!*processName)
  2176. processName = "hpcc";
  2177. openlog(processName, LOG_PID, LOG_USER);
  2178. }
  2179. CSysLogEventLogger::~CSysLogEventLogger()
  2180. {
  2181. if(dataLogFile != -1)
  2182. close(dataLogFile);
  2183. if(dataLogName)
  2184. delete [] dataLogName;
  2185. closelog();
  2186. }
  2187. bool CSysLogEventLogger::log(AuditType auditType, const char *msg, size32_t datasize, const void * data)
  2188. {
  2189. assertex(auditType < NUM_AUDIT_TYPES);
  2190. int level = auditTypeDataMap[auditType];
  2191. return linuxReport(level, msg, datasize, data);
  2192. }
  2193. bool CSysLogEventLogger::linuxReport(int level, const char * msg, size32_t datasize, const void * data)
  2194. {
  2195. if (!data)
  2196. datasize = 0;
  2197. else if (!datasize)
  2198. data = NULL;
  2199. bool ret = true;
  2200. #if 1 //useful for debugging...
  2201. if(data)
  2202. {
  2203. if(!dataLogUsed)
  2204. openDataLog();
  2205. if(dataLogFile != -1)
  2206. {
  2207. int fpos = writeDataLog(datasize, (byte const *)data);
  2208. if(fpos != -1)
  2209. syslog(level, "%s [0x%X bytes of data at %s byte 0x%X]", msg, datasize, dataLogName, fpos);
  2210. else
  2211. syslog(level, "%s [could not write 0x%X bytes of data to %s]", msg, datasize, dataLogName);
  2212. }
  2213. else
  2214. {
  2215. ret = false;
  2216. syslog(level, "%s [could not open file of form %s to write data]", msg, AUDIT_DATA_LOG_TEMPLATE);
  2217. }
  2218. }
  2219. else
  2220. {
  2221. syslog(level, "%s", msg);
  2222. }
  2223. #else
  2224. if(datasize)
  2225. {
  2226. char * buff = (char *)malloc(datasize*3+1);
  2227. unsigned char const * cdata = (unsigned char *)data;
  2228. unsigned i;
  2229. for(i=0; i<datasize; i++)
  2230. sprintf(buff+i*3, "%02X ", cdata[i]);
  2231. buff[datasize*3-1] = 0;
  2232. DBGLOG("syslog: priority=%X msg='%s' data=[%s]", level, msg, buff);
  2233. free(buff);
  2234. }
  2235. else
  2236. DBGLOG("syslog: priority=%X msg='%s'", level, msg);
  2237. #endif
  2238. return ret;
  2239. }
  2240. void CSysLogEventLogger::openDataLog()
  2241. {
  2242. CriticalBlock block(dataLogLock);
  2243. dataLogUsed = true;
  2244. unsigned len = strlen(AUDIT_DATA_LOG_TEMPLATE);
  2245. dataLogName = new char[len+1];
  2246. strcpy(dataLogName, AUDIT_DATA_LOG_TEMPLATE);
  2247. dataLogFile = mkstemp(dataLogName);
  2248. }
  2249. int CSysLogEventLogger::writeDataLog(size32_t datasize, byte const * data)
  2250. {
  2251. CriticalBlock block(dataLogLock);
  2252. off_t fpos = lseek(dataLogFile, 0, SEEK_CUR);
  2253. while(datasize > 0)
  2254. {
  2255. ssize_t written = write(dataLogFile, data, datasize);
  2256. if (written == -1)
  2257. return -1;
  2258. data += written;
  2259. datasize -= written;
  2260. }
  2261. #ifndef _WIN32
  2262. #ifdef F_FULLFSYNC
  2263. fcntl(dataLogFile, F_FULLFSYNC);
  2264. #else
  2265. fdatasync(dataLogFile);
  2266. #endif
  2267. #ifdef POSIX_FADV_DONTNEED
  2268. posix_fadvise(dataLogFile, 0, 0, POSIX_FADV_DONTNEED);
  2269. #endif
  2270. #endif
  2271. return fpos;
  2272. }
  2273. #endif
  2274. void SysLogMsgHandler::handleMessage(const LogMsg & msg) const
  2275. {
  2276. AuditType type = categoryToAuditType(msg.queryCategory());
  2277. StringBuffer text;
  2278. msg.toStringPlain(text, fields);
  2279. logger->log(type, text.str());
  2280. }
  2281. void SysLogMsgHandler::addToPTree(IPropertyTree * tree) const
  2282. {
  2283. IPropertyTree * handlerTree = createPTree(ipt_caseInsensitive);
  2284. handlerTree->setProp("@type", "audit");
  2285. tree->addPropTree("handler", handlerTree);
  2286. }
  2287. // Default implementations of the functions in IContextLogger interface
  2288. void IContextLogger::CTXLOG(const char *format, ...) const
  2289. {
  2290. va_list args;
  2291. va_start(args, format);
  2292. CTXLOGva(format, args);
  2293. va_end(args);
  2294. }
  2295. void IContextLogger::logOperatorException(IException *E, const char *file, unsigned line, const char *format, ...) const
  2296. {
  2297. va_list args;
  2298. va_start(args, format);
  2299. logOperatorExceptionVA(E, file, line, format, args);
  2300. va_end(args);
  2301. }
  2302. class DummyLogCtx : implements IContextLogger
  2303. {
  2304. private:
  2305. StringAttr globalId;
  2306. StringAttr callerId;
  2307. StringBuffer localId;
  2308. StringAttr globalIdHeader;
  2309. StringAttr callerIdHeader;
  2310. public:
  2311. // It's a static object - we don't want to actually link-count it...
  2312. virtual void Link() const {}
  2313. virtual bool Release() const { return false; }
  2314. virtual void CTXLOGva(const char *format, va_list args) const __attribute__((format(printf,2,0)))
  2315. {
  2316. StringBuffer ss;
  2317. ss.valist_appendf(format, args);
  2318. DBGLOG("%s", ss.str());
  2319. }
  2320. virtual void logOperatorExceptionVA(IException *E, const char *file, unsigned line, const char *format, va_list args) const __attribute__((format(printf,5,0)))
  2321. {
  2322. StringBuffer ss;
  2323. ss.append("ERROR");
  2324. if (E)
  2325. ss.append(": ").append(E->errorCode());
  2326. if (file)
  2327. ss.appendf(": %s(%d) ", sanitizeSourceFile(file), line);
  2328. if (E)
  2329. E->errorMessage(ss.append(": "));
  2330. if (format)
  2331. ss.append(": ").valist_appendf(format, args);
  2332. LOG(MCoperatorProgress, unknownJob, "%s", ss.str());
  2333. }
  2334. virtual void noteStatistic(StatisticKind kind, unsigned __int64 value) const
  2335. {
  2336. }
  2337. virtual void mergeStats(const CRuntimeStatisticCollection &from) const
  2338. {
  2339. }
  2340. virtual unsigned queryTraceLevel() const
  2341. {
  2342. return 0;
  2343. }
  2344. virtual void setGlobalId(const char *id, SocketEndpoint &ep, unsigned pid) override
  2345. {
  2346. globalId.set(id);
  2347. appendGloballyUniqueId(localId.clear());
  2348. }
  2349. virtual void setCallerId(const char *id) override
  2350. {
  2351. callerId.set(id);
  2352. }
  2353. virtual const char *queryGlobalId() const
  2354. {
  2355. return globalId.get();
  2356. }
  2357. virtual const char *queryCallerId() const override
  2358. {
  2359. return callerId.str();
  2360. }
  2361. virtual const char *queryLocalId() const
  2362. {
  2363. return localId.str();
  2364. }
  2365. virtual void setHttpIdHeaders(const char *global, const char *caller)
  2366. {
  2367. if (global && *global)
  2368. globalIdHeader.set(global);
  2369. if (caller && *caller)
  2370. callerIdHeader.set(caller);
  2371. }
  2372. virtual const char *queryGlobalIdHttpHeader() const
  2373. {
  2374. return globalIdHeader.str();
  2375. }
  2376. virtual const char *queryCallerIdHttpHeader() const
  2377. {
  2378. return callerIdHeader.str();
  2379. }
  2380. } dummyContextLogger;
  2381. extern jlib_decl const IContextLogger &queryDummyContextLogger()
  2382. {
  2383. return dummyContextLogger;
  2384. }
  2385. extern jlib_decl IContextLogger &updateDummyContextLogger()
  2386. {
  2387. return dummyContextLogger;
  2388. }
  2389. extern jlib_decl StringBuffer &appendGloballyUniqueId(StringBuffer &s)
  2390. {
  2391. string uid = createUniqueIdString();
  2392. return s.append(uid.c_str());
  2393. }
  2394. extern jlib_decl void UseSysLogForOperatorMessages(bool use)
  2395. {
  2396. static ILogMsgHandler *msgHandler=NULL;
  2397. if (use==(msgHandler!=NULL))
  2398. return;
  2399. if (use) {
  2400. msgHandler = getSysLogMsgHandler();
  2401. ILogMsgFilter * operatorFilter = getCategoryLogMsgFilter(MSGAUD_operator, MSGCLS_all, DefaultDetail, true);
  2402. queryLogMsgManager()->addMonitorOwn(msgHandler, operatorFilter);
  2403. }
  2404. else {
  2405. queryLogMsgManager()->removeMonitor(msgHandler);
  2406. msgHandler = NULL;
  2407. }
  2408. }
  2409. extern jlib_decl void AuditSystemAccess(const char *userid, bool success, char const * msg,...)
  2410. {
  2411. va_list args;
  2412. va_start(args, msg);
  2413. VStringBuffer s("User %s: ", userid);
  2414. SYSLOG((success) ? AUDIT_TYPE_ACCESS_SUCCESS : AUDIT_TYPE_ACCESS_FAILURE, s.valist_appendf(msg, args).str());
  2415. va_end(args);
  2416. }
  2417. //--------------------------------------------------------------
  2418. class jlib_decl CComponentLogFileCreator : implements IComponentLogFileCreator, public CInterface
  2419. {
  2420. private:
  2421. StringBuffer component;
  2422. //filename parts
  2423. StringBuffer prefix;
  2424. StringBuffer name;
  2425. StringBuffer postfix;
  2426. StringBuffer extension;
  2427. StringBuffer fullFileSpec;
  2428. bool createAlias;
  2429. StringBuffer aliasName;
  2430. StringBuffer logDirSubdir;
  2431. bool rolling;
  2432. //ILogMsgHandler fields
  2433. bool append;
  2434. bool flushes;
  2435. unsigned msgFields;
  2436. //ILogMsgFilter fields
  2437. unsigned msgAudiences;
  2438. unsigned msgClasses;
  2439. LogMsgDetail maxDetail;
  2440. bool local;
  2441. //available after logging started
  2442. StringBuffer logDir; //access via queryLogDir()
  2443. StringBuffer aliasFileSpec; //access via queryAliasFileSpec()
  2444. StringBuffer expandedLogSpec;//access via queryLogFileSpec()
  2445. private:
  2446. void setDefaults()
  2447. {
  2448. rolling = true;
  2449. append = true;
  2450. flushes = true;
  2451. const char *logFields = queryEnvironmentConf().queryProp("logfields");
  2452. if (!isEmptyString(logFields))
  2453. msgFields = LogMsgFieldsFromAbbrevs(logFields);
  2454. else
  2455. msgFields = MSGFIELD_STANDARD;
  2456. msgAudiences = MSGAUD_all;
  2457. msgClasses = MSGCLS_all;
  2458. maxDetail = DefaultDetail;
  2459. name.set(component); //logfile defaults to component name. Change via setName(), setPrefix() and setPostfix()
  2460. extension.set(".log");
  2461. local = false;
  2462. createAlias = true;
  2463. }
  2464. public:
  2465. IMPLEMENT_IINTERFACE;
  2466. CComponentLogFileCreator(IPropertyTree * _properties, const char *_component) : component(_component)
  2467. {
  2468. setDefaults();
  2469. if (_properties && !getConfigurationDirectory(_properties->queryPropTree("Directories"), "log", _component, _properties->queryProp("@name"), logDir))
  2470. _properties->getProp("@logDir", logDir);
  2471. }
  2472. CComponentLogFileCreator(const char *_logDir, const char *_component) : component(_component), logDir(_logDir)
  2473. {
  2474. setDefaults();
  2475. }
  2476. CComponentLogFileCreator(const char *_component) : component(_component)
  2477. {
  2478. setDefaults();
  2479. if (!getConfigurationDirectory(NULL, "log", _component, _component, logDir))
  2480. {
  2481. appendCurrentDirectory(logDir,false);
  2482. }
  2483. }
  2484. //set methods
  2485. void setExtension(const char * _ext) { extension.set(_ext); }
  2486. void setPrefix(const char * _prefix) { prefix.set(_prefix); }
  2487. void setName(const char * _name) { name.set(_name); }
  2488. void setCompleteFilespec(const char * _fs){fullFileSpec.set(_fs); setExtension(NULL); setRolling(false);}
  2489. void setPostfix(const char * _postfix) { postfix.set(_postfix); }
  2490. void setCreateAliasFile(bool _create) { createAlias = _create; }
  2491. void setAliasName(const char * _aliasName) { aliasName.set(_aliasName); }
  2492. void setLogDirSubdir(const char * _subdir) { logDirSubdir.set(_subdir); }
  2493. void setRolling(const bool _rolls) { rolling = _rolls; }
  2494. //ILogMsgHandler fields
  2495. void setAppend(const bool _append) { append = _append; }
  2496. void setFlushes(const bool _flushes) { flushes = _flushes; }
  2497. void setMsgFields(const unsigned _fields){ msgFields = _fields; }
  2498. //ILogMsgFilter fields
  2499. void setMsgAudiences(const unsigned _audiences){ msgAudiences = _audiences; }
  2500. void setMsgClasses(const unsigned _classes) { msgClasses = _classes; }
  2501. void setMaxDetail(const LogMsgDetail _maxDetail) { maxDetail = _maxDetail; }
  2502. void setLocal(const bool _local) { local = _local; }
  2503. //query methods (not valid until logging started)
  2504. const char * queryLogDir() const { return logDir.str(); }
  2505. const char * queryLogFileSpec() const { return expandedLogSpec.str(); }
  2506. const char * queryAliasFileSpec() const { return aliasFileSpec.str(); }
  2507. ILogMsgHandler * beginLogging()
  2508. {
  2509. //build directory path
  2510. StringBuffer logFileSpec;
  2511. if (!fullFileSpec.length())//user specify complete logfile specification?
  2512. {
  2513. if (!logDir.length())
  2514. {
  2515. appendCurrentDirectory(logDir,false).append(PATHSEPSTR).append("logs");
  2516. OWARNLOG("No logfile directory specified - logs will be written locally to %s", logDir.str());
  2517. }
  2518. makeAbsolutePath(logDir);
  2519. //build log file name (without date string or extension)
  2520. StringBuffer logFileName;
  2521. if (prefix.length())
  2522. logFileName.append(prefix).append(".");
  2523. logFileName.append(name);
  2524. if (postfix.length())
  2525. logFileName.append(".").append(postfix);
  2526. //build log file spec
  2527. if (logDirSubdir.length())
  2528. logDir.append(PATHSEPCHAR).append(logDirSubdir);//user specified subfolder
  2529. logFileSpec.append(logDir).append(PATHSEPCHAR).append(logFileName);
  2530. //build alias file spec
  2531. if (createAlias)
  2532. {
  2533. if (aliasName.length()==0)
  2534. aliasName.set(logFileName);
  2535. aliasFileSpec.append(logDir).append(PATHSEPCHAR).append(aliasName).append(extension);
  2536. }
  2537. }
  2538. else
  2539. makeAbsolutePath(fullFileSpec);
  2540. ILogMsgHandler * lmh;
  2541. if (rolling)
  2542. {
  2543. lmh = getRollingFileLogMsgHandler(logFileSpec.str(), extension, msgFields, append, flushes, NULL, aliasFileSpec.str(), true);
  2544. }
  2545. else
  2546. {
  2547. StringBuffer lfs;
  2548. if (fullFileSpec.length())
  2549. lfs.set(fullFileSpec);
  2550. else
  2551. lfs.set(logFileSpec.append(extension).str());
  2552. lmh = getFileLogMsgHandler(lfs.str(), NULL, msgFields, false);
  2553. }
  2554. lmh->getLogName(expandedLogSpec);
  2555. queryLogMsgManager()->addMonitorOwn( lmh, getCategoryLogMsgFilter(msgAudiences, msgClasses, maxDetail, local));
  2556. return lmh;
  2557. }
  2558. };
  2559. IComponentLogFileCreator * createComponentLogFileCreator(IPropertyTree * _properties, const char *_component)
  2560. {
  2561. return new CComponentLogFileCreator(_properties, _component);
  2562. }
  2563. IComponentLogFileCreator * createComponentLogFileCreator(const char *_logDir, const char *_component)
  2564. {
  2565. return new CComponentLogFileCreator(_logDir, _component);
  2566. }
  2567. IComponentLogFileCreator * createComponentLogFileCreator(const char *_component)
  2568. {
  2569. return new CComponentLogFileCreator(_component);
  2570. }