jlog.cpp 91 KB

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