jlog.ipp 46 KB

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