jlog.ipp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. #ifndef JLOG_IPP
  15. #define JLOG_IPP
  16. #include <algorithm>
  17. #include "jmutex.hpp"
  18. #include "jlog.hpp"
  19. #include "jiface.hpp"
  20. #include "jarray.hpp"
  21. #include "jsocket.hpp"
  22. #include "jptree.hpp"
  23. #include "jfile.hpp"
  24. #include "jqueue.tpp"
  25. #include "jregexp.hpp"
  26. static unsigned const defaultMsgQueueLimit = 256;
  27. static LogMsgCategory const dropWarningCategory(MSGAUD_operator, MSGCLS_error, 0);
  28. // Initial size of StringBuffer used to build output in LogMsg::toString methods
  29. #define LOG_MSG_FORMAT_BUFFER_LENGTH 1024
  30. // Enum used when serializing IFilter to show derived class
  31. enum
  32. {
  33. MSGFILTER_passall,
  34. MSGFILTER_passlocal,
  35. MSGFILTER_passnone,
  36. MSGFILTER_category,
  37. MSGFILTER_pid,
  38. MSGFILTER_tid,
  39. MSGFILTER_node,
  40. MSGFILTER_ip,
  41. MSGFILTER_job,
  42. MSGFILTER_user,
  43. MSGFILTER_session,
  44. MSGFILTER_component,
  45. MSGFILTER_not,
  46. MSGFILTER_and,
  47. MSGFILTER_or,
  48. MSGFILTER_switch,
  49. MSGFILTER_regex
  50. };
  51. // Implementations of filter which pass all or no messages
  52. //MORE: This would benefit from more code moved into this base class
  53. class CLogMsgFilter : implements ILogMsgFilter, public CInterface
  54. {
  55. public:
  56. IMPLEMENT_IINTERFACE;
  57. };
  58. class PassAllLogMsgFilter : public CLogMsgFilter
  59. {
  60. public:
  61. bool includeMessage(const LogMsg & msg) const { return true; }
  62. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  63. unsigned queryAudienceMask() const { return MSGAUD_all; }
  64. unsigned queryClassMask() const { return MSGCLS_all; }
  65. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  66. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_passall); }
  67. void addToPTree(IPropertyTree * tree) const;
  68. bool queryLocalFlag() const { return false; }
  69. };
  70. class PassLocalLogMsgFilter : public CLogMsgFilter
  71. {
  72. public:
  73. bool includeMessage(const LogMsg & msg) const { return !msg.queryRemoteFlag(); }
  74. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  75. unsigned queryAudienceMask() const { return MSGAUD_all; }
  76. unsigned queryClassMask() const { return MSGCLS_all; }
  77. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  78. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(preserveLocal ? MSGFILTER_passlocal : MSGFILTER_passall); }
  79. void addToPTree(IPropertyTree * tree) const;
  80. bool queryLocalFlag() const { return true; }
  81. };
  82. class PassNoneLogMsgFilter : public CLogMsgFilter
  83. {
  84. public:
  85. bool includeMessage(const LogMsg & msg) const { return false; }
  86. bool mayIncludeCategory(const LogMsgCategory & cat) const { return false; }
  87. unsigned queryAudienceMask() const { return 0; }
  88. unsigned queryClassMask() const { return 0; }
  89. LogMsgDetail queryMaxDetail() const { return 0; }
  90. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_passnone); }
  91. void addToPTree(IPropertyTree * tree) const;
  92. bool queryLocalFlag() const { return true; }
  93. };
  94. // Implementation of filter which passes messages by category masks
  95. class CategoryLogMsgFilter : public CLogMsgFilter
  96. {
  97. public:
  98. CategoryLogMsgFilter(unsigned _aMask, unsigned _cMask, LogMsgDetail _dMax, bool local) : audienceMask(_aMask), classMask(_cMask), maxDetail(_dMax), localFlag(local) {}
  99. CategoryLogMsgFilter(MemoryBuffer & in) { in.read(audienceMask); in.read(classMask); in.read(maxDetail); in.read(localFlag); }
  100. CategoryLogMsgFilter(IPropertyTree * tree) { audienceMask = tree->getPropInt("@audience", MSGAUD_all); classMask = tree->getPropInt("@class", MSGCLS_all); maxDetail = tree->getPropInt("@detail", TopDetail); localFlag = tree->hasProp("@local"); }
  101. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return includeCategory(msg.queryCategory()); }
  102. bool mayIncludeCategory(const LogMsgCategory & cat) const { return includeCategory(cat); }
  103. unsigned queryAudienceMask() const { return audienceMask; }
  104. unsigned queryClassMask() const { return classMask; }
  105. LogMsgDetail queryMaxDetail() const { return maxDetail; }
  106. bool isCategoryFilter() const { return true; }
  107. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_category).append(audienceMask).append(classMask).append(maxDetail); out.append(localFlag && preserveLocal); }
  108. void addToPTree(IPropertyTree * tree) const;
  109. void orWithFilter(const ILogMsgFilter * filter);
  110. void reset();
  111. bool includeCategory(const LogMsgCategory & category) const { return (category.queryAudience() & audienceMask) && (category.queryClass() & classMask) && (category.queryDetail() <= maxDetail); }
  112. bool queryLocalFlag() const { return localFlag; }
  113. protected:
  114. unsigned audienceMask;
  115. unsigned classMask;
  116. LogMsgDetail maxDetail;
  117. bool localFlag;
  118. };
  119. // Implementations of filters using sysInfo
  120. class PIDLogMsgFilter : public CLogMsgFilter
  121. {
  122. public:
  123. PIDLogMsgFilter(unsigned _pid, bool local) : pid(_pid), localFlag(local) {}
  124. PIDLogMsgFilter(MemoryBuffer & in) { in.read(pid); in.read(localFlag); }
  125. PIDLogMsgFilter(IPropertyTree * tree) { pid = tree->getPropInt("@pid", 0); localFlag = tree->hasProp("@local"); }
  126. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.querySysInfo().queryProcessID() == pid; }
  127. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  128. unsigned queryAudienceMask() const { return MSGAUD_all; }
  129. unsigned queryClassMask() const { return MSGCLS_all; }
  130. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  131. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_pid).append(pid).append(localFlag && preserveLocal); }
  132. void addToPTree(IPropertyTree * tree) const;
  133. bool queryLocalFlag() const { return localFlag; }
  134. private:
  135. unsigned pid;
  136. bool localFlag;
  137. };
  138. class TIDLogMsgFilter : public CLogMsgFilter
  139. {
  140. public:
  141. TIDLogMsgFilter(unsigned _tid, bool local) : tid(_tid), localFlag(local) {}
  142. TIDLogMsgFilter(MemoryBuffer & in) { in.read(tid); in.read(localFlag); }
  143. TIDLogMsgFilter(IPropertyTree * tree) { tid = tree->getPropInt("@tid", 0); localFlag = tree->hasProp("@local"); }
  144. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.querySysInfo().queryThreadID() == tid; }
  145. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  146. unsigned queryAudienceMask() const { return MSGAUD_all; }
  147. unsigned queryClassMask() const { return MSGCLS_all; }
  148. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  149. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_tid).append(tid).append(localFlag && preserveLocal); }
  150. void addToPTree(IPropertyTree * tree) const;
  151. bool queryLocalFlag() const { return localFlag; }
  152. private:
  153. unsigned tid;
  154. bool localFlag;
  155. };
  156. class NodeLogMsgFilter : public CLogMsgFilter
  157. {
  158. public:
  159. NodeLogMsgFilter(const char * name, unsigned port, bool local) : node(name, port), localFlag(local) {}
  160. NodeLogMsgFilter(const IpAddress & ip, unsigned port, bool local) : node(port, ip), localFlag(local) {}
  161. NodeLogMsgFilter(unsigned port, bool local) : node(port), localFlag(local) {}
  162. NodeLogMsgFilter(MemoryBuffer & in) { node.deserialize(in); in.read(localFlag); }
  163. NodeLogMsgFilter(IPropertyTree * tree)
  164. {
  165. StringBuffer buff;
  166. tree->getProp("@ip", buff);
  167. node.set(buff.str(), tree->getPropInt("@port", 0));
  168. localFlag = tree->hasProp("@local");
  169. }
  170. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.querySysInfo().queryNode()->equals(node); }
  171. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  172. unsigned queryAudienceMask() const { return MSGAUD_all; }
  173. unsigned queryClassMask() const { return MSGCLS_all; }
  174. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  175. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_node); node.serialize(out); out.append(localFlag && preserveLocal); }
  176. void addToPTree(IPropertyTree * tree) const;
  177. bool queryLocalFlag() const { return localFlag; }
  178. private:
  179. SocketEndpoint node;
  180. bool localFlag;
  181. };
  182. class IpLogMsgFilter : public CLogMsgFilter
  183. {
  184. public:
  185. IpLogMsgFilter(const char * name, bool local) : ip(name), localFlag(local) {}
  186. IpLogMsgFilter(const IpAddress & _ip, bool local) : localFlag(local), ip(_ip)
  187. {
  188. }
  189. IpLogMsgFilter(bool local) : localFlag(local) { GetHostIp(ip); }
  190. IpLogMsgFilter(MemoryBuffer & in) { ip.ipdeserialize(in); in.read(localFlag); }
  191. IpLogMsgFilter(IPropertyTree * tree) : ip(tree->queryProp("@ip")) { localFlag = tree->hasProp("@local"); }
  192. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.querySysInfo().queryNode()->ipequals(ip); }
  193. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  194. unsigned queryAudienceMask() const { return MSGAUD_all; }
  195. unsigned queryClassMask() const { return MSGCLS_all; }
  196. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  197. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_ip); ip.ipserialize(out); out.append(localFlag && preserveLocal); }
  198. void addToPTree(IPropertyTree * tree) const;
  199. bool queryLocalFlag() const { return localFlag; }
  200. private:
  201. IpAddress ip;
  202. bool localFlag;
  203. };
  204. class SessionLogMsgFilter : public CLogMsgFilter
  205. {
  206. public:
  207. SessionLogMsgFilter(LogMsgSessionId _session, bool local) : session(_session), localFlag(local) {}
  208. SessionLogMsgFilter(MemoryBuffer & in) { in.read(session); in.read(localFlag); }
  209. SessionLogMsgFilter(IPropertyTree * tree) { session = tree->getPropInt64("@session", UnknownSession); localFlag = tree->hasProp("@local"); }
  210. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.querySysInfo().querySessionID() == session; }
  211. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  212. unsigned queryAudienceMask() const { return MSGAUD_all; }
  213. unsigned queryClassMask() const { return MSGCLS_all; }
  214. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  215. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_session).append(session).append(localFlag && preserveLocal); }
  216. void addToPTree(IPropertyTree * tree) const;
  217. bool queryLocalFlag() const { return localFlag; }
  218. private:
  219. LogMsgSessionId session;
  220. bool localFlag;
  221. };
  222. // Implementations of filters using job info
  223. class JobLogMsgFilter : public CLogMsgFilter
  224. {
  225. public:
  226. JobLogMsgFilter(LogMsgJobId _job, bool local) : job(_job), localFlag(local) {}
  227. JobLogMsgFilter(MemoryBuffer & in) { in.read(job); in.read(localFlag); }
  228. JobLogMsgFilter(IPropertyTree * tree) { job = tree->getPropInt64("@job", UnknownJob); localFlag = tree->hasProp("@local"); }
  229. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.queryJobInfo().queryJobID() == job; }
  230. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  231. unsigned queryAudienceMask() const { return MSGAUD_all; }
  232. unsigned queryClassMask() const { return MSGCLS_all; }
  233. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  234. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_job).append(job).append(localFlag && preserveLocal); }
  235. void addToPTree(IPropertyTree * tree) const;
  236. bool queryLocalFlag() const { return localFlag; }
  237. private:
  238. LogMsgJobId job;
  239. bool localFlag;
  240. };
  241. class UserLogMsgFilter : public CLogMsgFilter
  242. {
  243. public:
  244. UserLogMsgFilter(LogMsgUserId _user, bool local) : user(_user), localFlag(local) {}
  245. UserLogMsgFilter(MemoryBuffer & in) { in.read(user); in.read(localFlag); }
  246. UserLogMsgFilter(IPropertyTree * tree) { user = tree->getPropInt64("@user", UnknownUser); localFlag = tree->hasProp("@local"); }
  247. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.queryJobInfo().queryUserID() == user; }
  248. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  249. unsigned queryAudienceMask() const { return MSGAUD_all; }
  250. unsigned queryClassMask() const { return MSGCLS_all; }
  251. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  252. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_user).append(user).append(localFlag && preserveLocal); }
  253. void addToPTree(IPropertyTree * tree) const;
  254. bool queryLocalFlag() const { return localFlag; }
  255. private:
  256. LogMsgUserId user;
  257. bool localFlag;
  258. };
  259. // Implementation of filter using component
  260. class ComponentLogMsgFilter : public CLogMsgFilter
  261. {
  262. public:
  263. ComponentLogMsgFilter(unsigned _compo, bool local) : component(_compo), localFlag(local) {}
  264. ComponentLogMsgFilter(MemoryBuffer & in) { in.read(component); in.read(localFlag); }
  265. ComponentLogMsgFilter(IPropertyTree * tree) { component = tree->getPropInt("@component", 0); localFlag = tree->hasProp("@local"); }
  266. bool includeMessage(const LogMsg & msg) const { if(localFlag && msg.queryRemoteFlag()) return false; return msg.queryComponent() == component; }
  267. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  268. unsigned queryAudienceMask() const { return MSGAUD_all; }
  269. unsigned queryClassMask() const { return MSGCLS_all; }
  270. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  271. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_component).append(component).append(localFlag && preserveLocal); }
  272. void addToPTree(IPropertyTree * tree) const;
  273. bool queryLocalFlag() const { return localFlag; }
  274. private:
  275. unsigned component;
  276. bool localFlag;
  277. };
  278. // Implementation of filter using regex
  279. class RegexLogMsgFilter : public CLogMsgFilter
  280. {
  281. public:
  282. RegexLogMsgFilter(const char *_regexText, bool local) : regexText(_regexText), regex(_regexText), localFlag(local) {}
  283. RegexLogMsgFilter(MemoryBuffer & in) { in.read(regexText); in.read(localFlag); regex.init(regexText);}
  284. RegexLogMsgFilter(IPropertyTree * tree) { regexText.set(tree->queryProp("@regex")); localFlag = tree->hasProp("@local"); regex.init(regexText);}
  285. bool includeMessage(const LogMsg & msg) const;
  286. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; }
  287. unsigned queryAudienceMask() const { return MSGAUD_all; }
  288. unsigned queryClassMask() const { return MSGCLS_all; }
  289. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  290. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_regex).append(regexText).append(localFlag && preserveLocal); }
  291. void addToPTree(IPropertyTree * tree) const;
  292. bool queryLocalFlag() const { return localFlag; }
  293. private:
  294. mutable SpinLock lock; // Regexpr is not threadsafe when called from multiple threads
  295. StringAttr regexText;
  296. RegExpr regex;
  297. bool localFlag;
  298. };
  299. // Implementations of filters to do logic
  300. class NotLogMsgFilter : public CLogMsgFilter
  301. {
  302. public:
  303. NotLogMsgFilter(ILogMsgFilter * _arg) : arg(_arg) {}
  304. NotLogMsgFilter(MemoryBuffer & in) { arg.setown(getDeserializedLogMsgFilter(in)); }
  305. NotLogMsgFilter(IPropertyTree * tree) { Owned<IPropertyTree> nottree = tree->getPropTree("filter"); arg.setown(getLogMsgFilterFromPTree(nottree)); }
  306. bool includeMessage(const LogMsg & msg) const { return !(arg->includeMessage(msg)); }
  307. bool mayIncludeCategory(const LogMsgCategory & cat) const { return true; } // can't just invert
  308. unsigned queryAudienceMask() const { return MSGAUD_all; }
  309. unsigned queryClassMask() const { return MSGCLS_all; }
  310. LogMsgDetail queryMaxDetail() const { return TopDetail; }
  311. void serialize(MemoryBuffer & out, bool preserveLocal) const
  312. {
  313. if(preserveLocal)
  314. {
  315. out.append(MSGFILTER_not);
  316. arg->serialize(out, true);
  317. }
  318. else
  319. out.append(MSGFILTER_passall); // sadly have to lose data here, could transmit a few too many messages because of this
  320. }
  321. void addToPTree(IPropertyTree * tree) const;
  322. bool queryLocalFlag() const { return false; }
  323. private:
  324. Linked<ILogMsgFilter> arg;
  325. };
  326. class AndLogMsgFilter : public CLogMsgFilter
  327. {
  328. public:
  329. AndLogMsgFilter(ILogMsgFilter * _arg1, ILogMsgFilter * _arg2) : arg1(_arg1), arg2(_arg2) {}
  330. AndLogMsgFilter(MemoryBuffer & in) { arg1.setown(getDeserializedLogMsgFilter(in)); arg2.setown(getDeserializedLogMsgFilter(in)); }
  331. AndLogMsgFilter(IPropertyTree * tree)
  332. {
  333. Owned <IPropertyTreeIterator> iter = tree->getElements("filter");
  334. ForEach(*iter)
  335. {
  336. ILogMsgFilter *filter = getLogMsgFilterFromPTree(&(iter->query()));
  337. if (!arg1.get())
  338. arg1.setown(filter);
  339. else if (!arg2.get())
  340. arg2.setown(filter);
  341. else
  342. arg2.setown(getAndLogMsgFilterOwn(arg2.getClear(), filter));
  343. }
  344. }
  345. bool includeMessage(const LogMsg & msg) const { return (arg1->includeMessage(msg)) && (arg2->includeMessage(msg)); }
  346. bool mayIncludeCategory(const LogMsgCategory & cat) const { return (arg1->mayIncludeCategory(cat)) && (arg2->mayIncludeCategory(cat)); }
  347. unsigned queryAudienceMask() const { return arg1->queryAudienceMask() & arg2->queryAudienceMask(); }
  348. unsigned queryClassMask() const { return arg1->queryClassMask() & arg2->queryClassMask(); }
  349. LogMsgDetail queryMaxDetail() const { return std::min(arg1->queryMaxDetail(), arg2->queryMaxDetail()); }
  350. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_and); arg1->serialize(out, preserveLocal); arg2->serialize(out, preserveLocal); }
  351. void addToPTree(IPropertyTree * tree) const;
  352. bool queryLocalFlag() const { return arg1->queryLocalFlag() || arg2->queryLocalFlag(); }
  353. private:
  354. Linked<ILogMsgFilter> arg1;
  355. Linked<ILogMsgFilter> arg2;
  356. };
  357. class OrLogMsgFilter : public CLogMsgFilter
  358. {
  359. public:
  360. OrLogMsgFilter(ILogMsgFilter * _arg1, ILogMsgFilter * _arg2) : arg1(_arg1), arg2(_arg2) {}
  361. OrLogMsgFilter(MemoryBuffer & in) { arg1.setown(getDeserializedLogMsgFilter(in)); arg2.setown(getDeserializedLogMsgFilter(in)); }
  362. OrLogMsgFilter(IPropertyTree * tree)
  363. {
  364. Owned <IPropertyTreeIterator> iter = tree->getElements("filter");
  365. ForEach(*iter)
  366. {
  367. ILogMsgFilter *filter = getLogMsgFilterFromPTree(&(iter->query()));
  368. if (!arg1.get())
  369. arg1.setown(filter);
  370. else if (!arg2.get())
  371. arg2.setown(filter);
  372. else
  373. arg2.setown(getOrLogMsgFilterOwn(arg2.getClear(), filter));
  374. }
  375. }
  376. bool includeMessage(const LogMsg & msg) const { return (arg1->includeMessage(msg)) || (arg2->includeMessage(msg)); }
  377. bool mayIncludeCategory(const LogMsgCategory & cat) const { return (arg1->mayIncludeCategory(cat)) || (arg2->mayIncludeCategory(cat)); }
  378. unsigned queryAudienceMask() const { return arg1->queryAudienceMask() | arg2->queryAudienceMask(); }
  379. unsigned queryClassMask() const { return arg1->queryClassMask() | arg2->queryClassMask(); }
  380. LogMsgDetail queryMaxDetail() const { return std::max(arg1->queryMaxDetail(), arg2->queryMaxDetail()); }
  381. void serialize(MemoryBuffer & out, bool preserveLocal) const { out.append(MSGFILTER_or); arg1->serialize(out, preserveLocal); arg2->serialize(out, preserveLocal); }
  382. void addToPTree(IPropertyTree * tree) const;
  383. bool queryLocalFlag() const { return arg1->queryLocalFlag() && arg2->queryLocalFlag(); }
  384. private:
  385. Linked<ILogMsgFilter> arg1;
  386. Linked<ILogMsgFilter> arg2;
  387. };
  388. class SwitchLogMsgFilter : public CLogMsgFilter
  389. {
  390. public:
  391. SwitchLogMsgFilter(ILogMsgFilter * _cond, ILogMsgFilter * _yes, ILogMsgFilter * _no) : cond(_cond), yes(_yes), no(_no) {}
  392. SwitchLogMsgFilter(MemoryBuffer & in)
  393. {
  394. cond.setown(getDeserializedLogMsgFilter(in));
  395. yes.setown(getDeserializedLogMsgFilter(in));
  396. no.setown(getDeserializedLogMsgFilter(in));
  397. }
  398. SwitchLogMsgFilter(IPropertyTree * tree)
  399. {
  400. cond.setown(getLogMsgFilterFromPTree(tree->queryPropTree("filter[1]")));
  401. yes.setown(getLogMsgFilterFromPTree(tree->queryPropTree("filter[2]")));
  402. no.setown(getLogMsgFilterFromPTree(tree->queryPropTree("filter[3]")));
  403. }
  404. bool includeMessage(const LogMsg & msg) const
  405. {
  406. bool swtch = cond->includeMessage(msg);
  407. return swtch ? yes->includeMessage(msg) : no->includeMessage(msg);
  408. }
  409. bool mayIncludeCategory(const LogMsgCategory & cat) const
  410. {
  411. return yes->mayIncludeCategory(cat) || no->mayIncludeCategory(cat);
  412. }
  413. unsigned queryAudienceMask() const { return yes->queryAudienceMask() | no->queryAudienceMask(); }
  414. unsigned queryClassMask() const { return yes->queryClassMask() | no->queryClassMask(); }
  415. LogMsgDetail queryMaxDetail() const { return std::max(yes->queryMaxDetail(), no->queryMaxDetail()); }
  416. void serialize(MemoryBuffer & out, bool preserveLocal) const
  417. {
  418. if(preserveLocal)
  419. {
  420. out.append(MSGFILTER_switch);
  421. cond->serialize(out, true);
  422. yes->serialize(out, true);
  423. no->serialize(out, true);
  424. }
  425. else
  426. {
  427. out.append(MSGFILTER_or);
  428. out.append(MSGFILTER_and);
  429. cond->serialize(out, false);
  430. yes->serialize(out, false);
  431. no->serialize(out, false);
  432. }
  433. }
  434. void addToPTree(IPropertyTree * tree) const;
  435. bool queryLocalFlag() const { return yes->queryLocalFlag() && no->queryLocalFlag(); }
  436. private:
  437. Linked<ILogMsgFilter> cond;
  438. Linked<ILogMsgFilter> yes;
  439. Linked<ILogMsgFilter> no;
  440. };
  441. // Implementations of handlers which writes selected fields to file handle (XML and table output)
  442. class HandleLogMsgHandler : public ILogMsgHandler
  443. {
  444. public:
  445. HandleLogMsgHandler(FILE * _handle, unsigned _fields) : handle(_handle), messageFields(_fields) {}
  446. virtual ~HandleLogMsgHandler() { flush(); }
  447. unsigned queryMessageFields() const { return messageFields; }
  448. void setMessageFields(unsigned _fields) { messageFields = _fields; }
  449. int flush() { CriticalBlock block(crit); return fflush(handle); }
  450. char const * disable() { crit.enter(); return "HANDLER"; }
  451. void enable() { crit.leave(); }
  452. bool getLogName(StringBuffer &name) const { return false; }
  453. protected:
  454. FILE * handle;
  455. unsigned messageFields;
  456. mutable CriticalSection crit;
  457. };
  458. class HandleLogMsgHandlerXML : public CInterface, implements HandleLogMsgHandler
  459. {
  460. public:
  461. HandleLogMsgHandlerXML(FILE * _handle, unsigned _fields) : HandleLogMsgHandler(_handle, _fields) {}
  462. IMPLEMENT_IINTERFACE;
  463. void handleMessage(const LogMsg & msg) const { CriticalBlock block(crit); msg.fprintXML(handle, messageFields); }
  464. bool needsPrep() const { return false; }
  465. void prep() {}
  466. void addToPTree(IPropertyTree * tree) const;
  467. };
  468. class HandleLogMsgHandlerTable : public CInterface, implements HandleLogMsgHandler
  469. {
  470. public:
  471. HandleLogMsgHandlerTable(FILE * _handle, unsigned _fields) : HandleLogMsgHandler(_handle, _fields), prepped(false) {}
  472. IMPLEMENT_IINTERFACE;
  473. void handleMessage(const LogMsg & msg) const { CriticalBlock block(crit); msg.fprintTable(handle, messageFields); }
  474. bool needsPrep() const { return !prepped; }
  475. void prep() { CriticalBlock block(crit); LogMsg::fprintTableHead(handle, messageFields); prepped = true; }
  476. void addToPTree(IPropertyTree * tree) const;
  477. private:
  478. bool prepped;
  479. };
  480. // Implementations of handlers which writes selected fields to named file (XML and table output)
  481. class FileLogMsgHandler : public ILogMsgHandler
  482. {
  483. public:
  484. FileLogMsgHandler(const char * _filename, const char * _headerText = 0, unsigned _fields = MSGFIELD_all, bool _append = false, bool _flushes = true);
  485. virtual ~FileLogMsgHandler();
  486. unsigned queryMessageFields() const { return messageFields; }
  487. void setMessageFields(unsigned _fields) { messageFields = _fields; }
  488. int flush() { CriticalBlock block(crit); return fflush(handle); }
  489. char const * disable();
  490. void enable();
  491. bool getLogName(StringBuffer &name) const { name.append(filename); return true; }
  492. protected:
  493. FILE * handle;
  494. unsigned messageFields;
  495. StringAttr filename;
  496. StringAttr headerText;
  497. bool append;
  498. bool flushes;
  499. mutable CriticalSection crit;
  500. };
  501. class FileLogMsgHandlerXML : public CInterface, implements FileLogMsgHandler
  502. {
  503. public:
  504. FileLogMsgHandlerXML(const char * _filename, const char * _headerText = 0, unsigned _fields = MSGFIELD_all, bool _append = false, bool _flushes = true) : FileLogMsgHandler(_filename, _headerText, _fields, _append, _flushes) {}
  505. IMPLEMENT_IINTERFACE;
  506. void handleMessage(const LogMsg & msg) const { CriticalBlock block(crit); msg.fprintXML(handle, messageFields); if(flushes) fflush(handle); }
  507. bool needsPrep() const { return false; }
  508. void prep() {}
  509. void addToPTree(IPropertyTree * tree) const;
  510. };
  511. class FileLogMsgHandlerTable : public CInterface, implements FileLogMsgHandler
  512. {
  513. public:
  514. FileLogMsgHandlerTable(const char * _filename, const char * _headerText = 0, unsigned _fields = MSGFIELD_all, bool _append = false, bool _flushes = true) : FileLogMsgHandler(_filename, _headerText, _fields, _append, _flushes), prepped(false) {}
  515. IMPLEMENT_IINTERFACE;
  516. void handleMessage(const LogMsg & msg) const { CriticalBlock block(crit); msg.fprintTable(handle, messageFields); if(flushes) fflush(handle); }
  517. bool needsPrep() const { return !prepped; }
  518. void prep() { CriticalBlock block(crit); LogMsg::fprintTableHead(handle, messageFields); prepped = true; }
  519. void addToPTree(IPropertyTree * tree) const;
  520. private:
  521. bool prepped;
  522. };
  523. class RollingFileLogMsgHandler : public CInterface, implements ILogMsgHandler
  524. {
  525. public:
  526. RollingFileLogMsgHandler(const char * _filebase, const char * _fileextn, unsigned _fields = MSGFIELD_all, bool _append = false, bool _flushes = true, const char *initialName = NULL, const char *alias = NULL, bool daily = false);
  527. virtual ~RollingFileLogMsgHandler();
  528. IMPLEMENT_IINTERFACE;
  529. void handleMessage(const LogMsg & msg) const
  530. {
  531. CriticalBlock block(crit);
  532. checkRollover();
  533. msg.fprintTable(handle, messageFields);
  534. if(flushes) fflush(handle);
  535. }
  536. bool needsPrep() const { return false; }
  537. void prep() {}
  538. unsigned queryMessageFields() const { return messageFields; }
  539. void setMessageFields(unsigned _fields) { messageFields = _fields; }
  540. void addToPTree(IPropertyTree * tree) const;
  541. int flush() { CriticalBlock block(crit); return fflush(handle); }
  542. char const * disable();
  543. void enable();
  544. bool getLogName(StringBuffer &name) const { name.append(filename); return true; }
  545. protected:
  546. void checkRollover() const;
  547. void doRollover(bool daily, const char *forceName = NULL) const;
  548. protected:
  549. mutable FILE * handle;
  550. unsigned messageFields;
  551. StringAttr alias;
  552. StringAttr filebase;
  553. StringAttr fileextn;
  554. mutable StringBuffer filename;
  555. bool append;
  556. bool flushes;
  557. mutable CriticalSection crit;
  558. mutable struct tm startTime;
  559. };
  560. // Implementation of handler which writes message to file in binary form
  561. class BinLogMsgHandler : public CInterface, implements ILogMsgHandler
  562. {
  563. public:
  564. BinLogMsgHandler(const char * _filename, bool _append = false);
  565. virtual ~BinLogMsgHandler();
  566. IMPLEMENT_IINTERFACE;
  567. void handleMessage(const LogMsg & msg) const;
  568. bool needsPrep() const { return false; }
  569. void prep() {}
  570. void addToPTree(IPropertyTree * tree) const;
  571. unsigned queryMessageFields() const { return MSGFIELD_all; }
  572. void setMessageFields(unsigned _fields) {}
  573. int flush() { return 0; }
  574. char const * disable();
  575. void enable();
  576. bool getLogName(StringBuffer &name) const { name.append(filename); return true; }
  577. protected:
  578. StringAttr filename;
  579. bool append;
  580. OwnedIFile file;
  581. OwnedIFileIO fio;
  582. OwnedIFileIOStream fstr;
  583. mutable MemoryBuffer mbuff;
  584. mutable size32_t msglen;
  585. mutable CriticalSection crit;
  586. };
  587. // Implementation of handler which uses the audit event logger
  588. class SysLogMsgHandler : public CInterface, implements ILogMsgHandler
  589. {
  590. public:
  591. SysLogMsgHandler(ISysLogEventLogger * _logger, unsigned _fields) : logger(_logger), fields(_fields) {}
  592. IMPLEMENT_IINTERFACE;
  593. void handleMessage(const LogMsg & msg) const;
  594. bool needsPrep() const { return false; }
  595. void prep() {}
  596. void addToPTree(IPropertyTree * tree) const;
  597. unsigned queryMessageFields() const { return fields; }
  598. void setMessageFields(unsigned _fields) { fields = _fields; }
  599. int flush() { return 0; }
  600. char const * disable() { return "Audit"; }
  601. void enable() {}
  602. bool getLogName(StringBuffer &name) const { return false; }
  603. protected:
  604. ISysLogEventLogger * logger;
  605. unsigned fields;
  606. };
  607. // Monitor to watch for messages --- pairs up a filter with a handler
  608. class LogMsgMonitor : public CInterface
  609. {
  610. public:
  611. LogMsgMonitor(ILogMsgFilter * _filter, ILogMsgHandler * _handler) : filter(_filter), handler(_handler) {}
  612. void processMessage(const LogMsg & msg) const { if(filter->includeMessage(msg)) handler->handleMessage(msg); }
  613. ILogMsgFilter * queryFilter() const { return filter; }
  614. ILogMsgFilter * getFilter() const { return LINK(filter); }
  615. ILogMsgHandler * queryHandler() const { return handler; }
  616. ILogMsgHandler * getHandler() const { return LINK(handler); }
  617. void setFilter(ILogMsgFilter * newFilter) { filter.set(newFilter); }
  618. void setFilterOwn(ILogMsgFilter * newFilter) { filter.setown(newFilter); }
  619. void addToPTree(IPropertyTree * tree) const;
  620. private:
  621. Linked<ILogMsgFilter> filter;
  622. Linked<ILogMsgHandler> handler;
  623. };
  624. class DropLogMsg;
  625. // Implementation of logging manager
  626. class CLogMsgManager : public ILogMsgManager, public CInterface
  627. {
  628. private:
  629. class MsgProcessor : public Thread
  630. {
  631. public:
  632. MsgProcessor(CLogMsgManager * _owner) : Thread("CLogMsgManager::MsgProcessor"), owner(_owner), more(true), droppingLimit(0) {}
  633. void push(LogMsg * msg);
  634. virtual int run();
  635. void notify(LogMsg * msg);
  636. void stop();
  637. void setBlockingLimit(unsigned lim);
  638. void setDroppingLimit(unsigned lim, unsigned num);
  639. void resetLimit();
  640. bool flush(unsigned timeout);
  641. private:
  642. void drop();
  643. private:
  644. CLogMsgManager * owner;
  645. bool more;
  646. CallbackInterThreadQueueOf<LogMsg, MsgProcessor, false> q;
  647. unsigned droppingLimit;
  648. unsigned numToDrop;
  649. Mutex pullCycleMutex;
  650. };
  651. Owned<MsgProcessor> processor;
  652. friend class MsgProcessor;
  653. friend class DropLogMsg;
  654. public:
  655. CLogMsgManager() : prefilter(0, 0, 0, false), suspendedChildren(false), port(0), session(UnknownSession) { atomic_set(&nextID, 0); }
  656. ~CLogMsgManager();
  657. IMPLEMENT_IINTERFACE;
  658. void enterQueueingMode();
  659. void setQueueBlockingLimit(unsigned lim);
  660. void setQueueDroppingLimit(unsigned lim, unsigned numToDrop);
  661. void resetQueueLimit();
  662. bool flushQueue(unsigned timeout) { if(processor) return processor->flush(timeout); else return true; }
  663. void report(const LogMsgCategory & cat, const char * format, ...);
  664. void report_va(const LogMsgCategory & cat, const char * format, va_list args);
  665. void report(const LogMsgCategory & cat, LogMsgCode code, const char * format, ...);
  666. void report_va(const LogMsgCategory & cat, LogMsgCode code, const char * format, va_list args);
  667. void report(const LogMsgCategory & cat, const IException * e, const char * prefix = NULL);
  668. void report(unsigned compo, const LogMsgCategory & cat, const char * format, ...);
  669. void report_va(unsigned compo, const LogMsgCategory & cat, const char * format, va_list args);
  670. void report(unsigned compo, const LogMsgCategory & cat, LogMsgCode code, const char * format, ...);
  671. void report_va(unsigned compo, const LogMsgCategory & cat, LogMsgCode code, const char * format, va_list args);
  672. void report(unsigned compo, const LogMsgCategory & cat, const IException * e, const char * prefix = NULL);
  673. void report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, ...);
  674. void report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, va_list args);
  675. void report(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, ...);
  676. void report_va(const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, va_list args);
  677. void report(const LogMsgCategory & cat, const LogMsgJobInfo & job, const IException * e, const char * prefix = NULL);
  678. void report(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, ...);
  679. void report_va(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, const char * format, va_list args);
  680. void report(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, ...);
  681. void report_va(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, LogMsgCode code, const char * format, va_list args);
  682. void report(unsigned compo, const LogMsgCategory & cat, const LogMsgJobInfo & job, const IException * e, const char * prefix = NULL);
  683. void report(const LogMsg & msg) const { if(prefilter.includeCategory(msg.queryCategory())) doReport(msg); }
  684. bool addMonitor(ILogMsgHandler * handler, ILogMsgFilter * filter);
  685. bool addMonitorOwn(ILogMsgHandler * handler, ILogMsgFilter * filter);
  686. bool removeMonitor(ILogMsgHandler * handler);
  687. unsigned removeMonitorsMatching(HandlerTest & test);
  688. void removeAllMonitors();
  689. void resetMonitors();
  690. ILogMsgFilter * queryMonitorFilter(const ILogMsgHandler * handler) const;
  691. ILogMsgFilter * getMonitorFilter(const ILogMsgHandler * handler) const { return LINK(queryMonitorFilter(handler)); }
  692. bool isActiveMonitor(const ILogMsgHandler * handler) const { return (find(handler) != NotFound); }
  693. bool changeMonitorFilter(const ILogMsgHandler * handler, ILogMsgFilter * newFilter);
  694. bool changeMonitorFilterOwn(const ILogMsgHandler * handler, ILogMsgFilter * newFilter) { bool ret = changeMonitorFilter(handler, newFilter); newFilter->Release(); return ret; }
  695. LogMsgId getNextID() { return static_cast<LogMsgId>(atomic_add_exchange(&nextID, 1)); }
  696. void prepAllHandlers() const;
  697. void addChildOwn(ILogMsgLinkToChild * child) { WriteLockBlock block(childLock); children.append(*child); }
  698. void removeChild(ILogMsgLinkToChild * child) { WriteLockBlock block(childLock); children.remove(findChild(child)); }
  699. void removeAllChildren() { WriteLockBlock block(childLock); children.kill(); }
  700. ILogMsgFilter * getCompoundFilter(bool locked = false) const;
  701. void suspendChildren() { suspendedChildren = true; }
  702. void unsuspendChildren() { suspendedChildren = false; sendFilterToChildren(); }
  703. bool addMonitorToPTree(const ILogMsgHandler * handler, IPropertyTree * tree) const;
  704. void addAllMonitorsToPTree(IPropertyTree * tree) const;
  705. void setPort(unsigned _port) { port = _port; }
  706. unsigned queryPort() const { return port; }
  707. void setSession(LogMsgSessionId _session) { session = _session; }
  708. LogMsgSessionId querySession() const { return session; }
  709. bool rejectsCategory(const LogMsgCategory & cat) const;
  710. private:
  711. void sendFilterToChildren(bool locked = false) const;
  712. aindex_t find(const ILogMsgHandler * handler) const;
  713. void buildPrefilter();
  714. void pushMsg(LogMsg * msg);
  715. void doReport(const LogMsg & msg) const;
  716. void panic(char const * reason) const;
  717. aindex_t findChild(ILogMsgLinkToChild * child) const;
  718. private:
  719. CIArrayOf<LogMsgMonitor> monitors;
  720. mutable ReadWriteLock monitorLock;
  721. CategoryLogMsgFilter prefilter;
  722. atomic_t nextID;
  723. IArrayOf<ILogMsgLinkToChild> children;
  724. mutable ReadWriteLock childLock;
  725. bool suspendedChildren;
  726. unsigned port;
  727. LogMsgSessionId session;
  728. CriticalSection modeLock;
  729. };
  730. // Message indicating messages have been dropped
  731. class DropLogMsg : public LogMsg
  732. {
  733. public:
  734. DropLogMsg(CLogMsgManager * owner, LogMsgId id, unsigned _count) : LogMsg(dropWarningCategory, id, unknownJob, NoLogMsgCode, "MISSING LOG MESSAGES: ", 0, owner->port, owner->session), count(_count)
  735. {
  736. text.append("message queue length exceeded, dropped ").append(count).append(" messages");
  737. }
  738. unsigned queryCount() const { return count; }
  739. private:
  740. unsigned count;
  741. };
  742. class CSysLogEventLogger : implements ISysLogEventLogger, public CInterface
  743. {
  744. public:
  745. CSysLogEventLogger();
  746. ~CSysLogEventLogger();
  747. IMPLEMENT_IINTERFACE;
  748. virtual bool log(AuditType auditType, char const * msg) { return log(auditType, msg, 0, 0); }
  749. virtual bool log(AuditType auditType, char const * msg, size32_t datasize, void const * data);
  750. private:
  751. #ifdef _WIN32
  752. bool win32Report(unsigned eventtype, unsigned category, unsigned eventid, const char * msg, size32_t datasize, const void * data);
  753. HANDLE hEventLog;
  754. #else
  755. bool linuxReport(int level, const char * msg, size32_t datasize, const void * data);
  756. void openDataLog();
  757. int writeDataLog(size32_t datasize, byte const * data);
  758. bool dataLogUsed;
  759. char * dataLogName;
  760. int dataLogFile;
  761. CriticalSection dataLogLock;
  762. #endif
  763. };
  764. // Standard filters, handlers, manager, and audit event logger
  765. extern PassAllLogMsgFilter * thePassAllFilter;
  766. extern PassLocalLogMsgFilter * thePassLocalFilter;
  767. extern PassNoneLogMsgFilter * thePassNoneFilter;
  768. extern HandleLogMsgHandlerTable * theStderrHandler;
  769. extern CLogMsgManager * theManager;
  770. extern CSysLogEventLogger * theSysLogEventLogger;
  771. #endif