loggingagentbase.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2014 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. #pragma warning (disable : 4786)
  14. #ifndef _LOGGINGAGENT_HPP__
  15. #define _LOGGINGAGENT_HPP__
  16. #include "jiface.hpp"
  17. #include "esp.hpp"
  18. #include "datafieldmap.hpp"
  19. #include "ws_loggingservice_esp.ipp"
  20. #include "loggingcommon.hpp"
  21. #include "LoggingErrors.hpp"
  22. #include <set>
  23. #define LOGREQUEST "LogRequest"
  24. #define LOGREQUEST_GUID "GUID"
  25. #define LOGREQUEST_OPTION "option"
  26. #define LOGCONTENTINFILE "LogContentInFile"
  27. #define LOGCONTENTINFILE_FILENAME "FileName"
  28. #define LOGCONTENTINFILE_FILEPOS "Pos"
  29. #define LOGCONTENTINFILE_FILESIZE "Size"
  30. enum ESPLogContentGroup
  31. {
  32. ESPLCGESPContext = 0,
  33. ESPLCGUserContext = 1,
  34. ESPLCGUserReq = 2,
  35. ESPLCGUserResp = 3,
  36. ESPLCGLogDatasets = 4,
  37. ESPLCGBackEndReq = 5,
  38. ESPLCGBackEndResp = 6,
  39. ESPLCGAll = 7
  40. };
  41. static const char * const espLogContentGroupNames[] = { "ESPContext", "UserContext", "UserRequest", "UserResponse",
  42. "LogDatasets", "BackEndRequest", "BackEndResponse", "", NULL };
  43. #define UPDATELOGTHREADWAITINGTIME 3000
  44. //The 'TransactionXYZ' is expected for the following key strings
  45. //used in CTransIDBuilder::getTransID() -> add().
  46. static const char* sTransactionDateTime = "TransactionDateTime";
  47. static const char* sTransactionMethod = "TransactionMethod";
  48. static const char* sTransactionIdentifier = "TransactionIdentifier";
  49. class CTransIDBuilder : public CInterface, implements IInterface
  50. {
  51. StringAttr seed, seedType;
  52. bool localSeed;
  53. unsigned __int64 seq = 0;
  54. unsigned maxLength = 0;
  55. unsigned maxSeq = 0;
  56. unsigned seedExpiredSeconds = 0;
  57. time_t createTime;
  58. void add(StringAttrMapping* transIDFields, const char* key, StringBuffer& id)
  59. {
  60. StringAttr* value = transIDFields->getValue(key);
  61. if (value)
  62. id.append(value->get()).append('-');
  63. else
  64. {
  65. const char* ptr = key;
  66. if (strlen(key) > 11) //skip the "transaction" prefix of the key
  67. ptr += 11;
  68. id.append('?').append(ptr).append('-');
  69. }
  70. }
  71. public:
  72. IMPLEMENT_IINTERFACE;
  73. CTransIDBuilder(const char* _seed, bool _localSeed, const char* _seedType, unsigned _maxLength, unsigned _maxSeq, unsigned _seedExpiredSeconds)
  74. : seed(_seed), localSeed(_localSeed), seedType(_seedType), maxLength(_maxLength), maxSeq(_maxSeq), seedExpiredSeconds(_seedExpiredSeconds)
  75. {
  76. CDateTime now;
  77. now.setNow();
  78. createTime = now.getSimple();
  79. };
  80. virtual ~CTransIDBuilder() {};
  81. bool checkMaxSequenceNumber() { return (maxSeq == 0) || (seq < maxSeq); };
  82. bool checkMaxLength(unsigned length) { return (maxLength == 0) || (length <= maxLength); };
  83. bool checkTimeout()
  84. {
  85. if (seedExpiredSeconds ==0)
  86. return true;
  87. CDateTime now;
  88. now.setNow();
  89. return now.getSimple() < createTime + seedExpiredSeconds;
  90. };
  91. bool isLocalSeed() { return localSeed; };
  92. void resetTransSeed(const char* newSeed, const char* newSeedType)
  93. {
  94. if (isEmptyString(newSeed))
  95. throw MakeStringException(EspLoggingErrors::GetTransactionSeedFailed, "TransactionSeed cannot be empty.");
  96. seed.set(newSeed);
  97. seedType.set(newSeedType);
  98. seq = 0;
  99. CDateTime now;
  100. now.setNow();
  101. createTime = now.getSimple();
  102. };
  103. virtual const char* getTransSeed() { return seed.get(); };
  104. virtual void getTransID(StringAttrMapping* transIDFields, StringBuffer& id)
  105. {
  106. id.clear();
  107. if (transIDFields)
  108. {
  109. add(transIDFields, sTransactionDateTime, id);
  110. add(transIDFields, sTransactionMethod, id);
  111. add(transIDFields, sTransactionIdentifier, id);
  112. }
  113. id.append(seed.get());
  114. if (seedType.length())
  115. id.append(seedType.get());
  116. id.append(++seq);
  117. };
  118. };
  119. interface IEspUpdateLogRequestWrap : extends IInterface
  120. {
  121. virtual const char* getGUID()=0;
  122. virtual const char* getOption()=0;
  123. virtual const char* getUpdateLogRequest()=0;
  124. virtual IPropertyTree* getESPContext()=0;
  125. virtual IPropertyTree* getUserContext()=0;
  126. virtual IPropertyTree* getUserRequest()=0;
  127. virtual IPropertyTree* getLogRequestTree()=0;
  128. virtual IPropertyTree* getScriptValuesTree()=0;
  129. virtual IInterface* getExtraLog()=0;
  130. virtual const char* getBackEndRequest()=0;
  131. virtual const char* getBackEndResponse()=0;
  132. virtual const char* getUserResponse()=0;
  133. virtual const char* getLogDatasets()=0;
  134. virtual const bool getNoResend()=0;
  135. virtual void setGUID(const char* val)=0;
  136. virtual void setOption(const char* val)=0;
  137. virtual void setUpdateLogRequest(const char* val)=0;
  138. virtual void setESPContext(IPropertyTree* val)=0;
  139. virtual void setUserContext(IPropertyTree* val)=0;
  140. virtual void setUserRequest(IPropertyTree* val)=0;
  141. virtual void setLogRequestTree(IPropertyTree* val)=0;
  142. virtual void setScriptValuesTree(IPropertyTree* val)=0;
  143. virtual void setExtraLog(IInterface* val)=0;
  144. virtual void setBackEndRequest(const char* val)=0;
  145. virtual void setBackEndResponse(const char* val)=0;
  146. virtual void setUserResponse(const char* val)=0;
  147. virtual void setLogDatasets(const char* val)=0;
  148. virtual unsigned incrementRetryCount() = 0;
  149. virtual void setNoResend(bool val)=0;
  150. virtual void clearOriginalContent() = 0;
  151. };
  152. class CUpdateLogRequestWrap : implements IEspUpdateLogRequestWrap, public CInterface
  153. {
  154. StringAttr GUID;
  155. StringAttr option;
  156. StringAttr updateLogRequest;
  157. Owned<IPropertyTree> espContext;
  158. Owned<IPropertyTree> userContext;
  159. Owned<IPropertyTree> userRequest;
  160. Owned<IPropertyTree> logRequestTree;
  161. Owned<IPropertyTree> scriptValuesTree;
  162. Owned<IInterface> extraLog;
  163. StringAttr backEndRequest, backEndResponse;
  164. StringAttr userResponse;
  165. StringAttr logDatasets;
  166. unsigned retryCount;
  167. bool noResend = false;;
  168. public:
  169. IMPLEMENT_IINTERFACE;
  170. CUpdateLogRequestWrap(const char* _GUID, const char* _option, const char* _updateLogRequest)
  171. : GUID(_GUID), option(_option), updateLogRequest(_updateLogRequest), retryCount(0) {};
  172. CUpdateLogRequestWrap(const char* _GUID, const char* _option, IPropertyTree* _espContext,
  173. IPropertyTree*_userContext, IPropertyTree*_userRequest, const char *_backEndRequest,
  174. const char *_backEndResponse, const char *_userResponse, const char *_logDatasets)
  175. : GUID(_GUID), option(_option), backEndRequest(_backEndRequest), backEndResponse(_backEndResponse),
  176. userResponse(_userResponse), logDatasets(_logDatasets), retryCount(0)
  177. {
  178. userContext.setown(_userContext);
  179. espContext.setown(_espContext);
  180. userRequest.setown(_userRequest);
  181. };
  182. CUpdateLogRequestWrap(const char* _GUID, const char* _option, IPropertyTree* _logInfo,
  183. IInterface* _extraLog) : GUID(_GUID), option(_option), retryCount(0)
  184. {
  185. logRequestTree.setown(_logInfo);
  186. extraLog.setown(_extraLog);
  187. };
  188. void clearOriginalContent()
  189. {
  190. espContext.clear();
  191. userRequest.clear();
  192. userContext.clear();
  193. userResponse.clear();
  194. logDatasets.clear();
  195. backEndRequest.clear();
  196. backEndResponse.clear();
  197. updateLogRequest.clear();
  198. logRequestTree.clear();
  199. scriptValuesTree.clear();
  200. extraLog.clear();
  201. };
  202. const char* getGUID() {return GUID.get();};
  203. const char* getOption() {return option.get();};
  204. const char* getUpdateLogRequest() {return updateLogRequest.get();};
  205. IPropertyTree* getESPContext() {return espContext.getLink();};
  206. IPropertyTree* getUserContext() {return userContext.getLink();};
  207. IPropertyTree* getUserRequest() {return userRequest.getLink();};
  208. IPropertyTree* getLogRequestTree() {return logRequestTree.getLink();};
  209. IPropertyTree* getScriptValuesTree() override {return scriptValuesTree.getLink();};
  210. IInterface* getExtraLog() {return extraLog.getLink();};
  211. const char* getBackEndRequest() {return backEndRequest.get();};
  212. const char* getBackEndResponse() {return backEndResponse.get();};
  213. const char* getUserResponse() {return userResponse.get();};
  214. const char* getLogDatasets() {return logDatasets.get();};
  215. const bool getNoResend() {return noResend;};
  216. void setGUID(const char* val) {GUID.set(val);};
  217. void setOption(const char* val) {option.set(val);};
  218. void setUpdateLogRequest(const char* val) {updateLogRequest.set(val);};
  219. void setESPContext(IPropertyTree* val) {espContext.setown(val);};
  220. void setUserContext(IPropertyTree* val) {userContext.setown(val);};
  221. void setUserRequest(IPropertyTree* val) {userRequest.setown(val);};
  222. void setLogRequestTree(IPropertyTree* val) {logRequestTree.setown(val);};
  223. void setScriptValuesTree(IPropertyTree* val) override {scriptValuesTree.setown(val);};
  224. void setExtraLog(IInterface* val) {extraLog.setown(val);};
  225. void setBackEndRequest(const char* val) {backEndRequest.set(val);};
  226. void setBackEndResponse(const char* val) {backEndResponse.set(val);};
  227. void setUserResponse(const char* val) {userResponse.set(val);};
  228. void setLogDatasets(const char* val) {logDatasets.set(val);};
  229. unsigned incrementRetryCount() { retryCount++; return retryCount;};
  230. void setNoResend(bool val) { noResend = val; };
  231. };
  232. interface IEspLogAgentVariant : extends IInterface
  233. {
  234. virtual const char* getName() const = 0;
  235. virtual const char* getType() const = 0;
  236. virtual const char* getGroup() const = 0;
  237. };
  238. struct IEspLogAgentVariantComparator
  239. {
  240. // Implement alternative to std::less for potential set ordering
  241. bool operator () (const Owned<const IEspLogAgentVariant>& lhs, const Owned<const IEspLogAgentVariant>& rhs) const
  242. {
  243. return (*this)(lhs.get(), rhs.get());
  244. }
  245. bool operator () (const IEspLogAgentVariant* lhs, const IEspLogAgentVariant* rhs) const
  246. {
  247. return compare(lhs, rhs) < 0;
  248. }
  249. private:
  250. int compare(const IEspLogAgentVariant* lhs, const IEspLogAgentVariant* rhs) const
  251. {
  252. if (lhs == rhs)
  253. return 0;
  254. if (nullptr == lhs)
  255. return 1;
  256. if (nullptr == rhs)
  257. return -1;
  258. int relation = compare(lhs->getName(), rhs->getName());
  259. if (0 == relation)
  260. {
  261. relation = compare(lhs->getType(), rhs->getType());
  262. if (0 == relation)
  263. relation = compare(lhs->getGroup(), rhs->getGroup());
  264. }
  265. return relation;
  266. }
  267. int compare(const char* lhs, const char* rhs) const
  268. {
  269. if (lhs == rhs)
  270. return 0;
  271. if (nullptr == lhs)
  272. return 1;
  273. if (nullptr == rhs)
  274. return -1;
  275. return stricmp(lhs, rhs);
  276. }
  277. };
  278. interface IEspLogAgentVariantIterator : extends IIteratorOf<const IEspLogAgentVariant> {};
  279. interface IEspLogAgent : extends IInterface
  280. {
  281. virtual const char * getName() = 0;
  282. virtual bool init(const char * name, const char * type, IPropertyTree * cfg, const char * process) = 0;
  283. virtual bool initVariants(IPropertyTree* cfg) = 0;
  284. virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp) = 0;
  285. virtual void getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID) = 0;
  286. virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp) = 0;
  287. virtual bool hasService(LOGServiceType service) = 0;
  288. virtual IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req) = 0;
  289. virtual IEspLogAgentVariantIterator* getVariants() const = 0;
  290. };
  291. class CESPLogContentGroupFilters : public CInterface, implements IInterface
  292. {
  293. ESPLogContentGroup group;
  294. StringArray filters;
  295. public:
  296. IMPLEMENT_IINTERFACE;
  297. CESPLogContentGroupFilters(ESPLogContentGroup _group) : group(_group) {};
  298. ESPLogContentGroup getGroup() { return group; };
  299. StringArray& getFilters() { return filters; };
  300. void clearFilters() { filters.clear(); };
  301. unsigned getFilterCount() { return filters.length(); };
  302. void addFilter(const char* filter)
  303. {
  304. if (filter && *filter)
  305. filters.append(filter);
  306. };
  307. };
  308. class LOGGINGCOMMON_API CLogContentFilter : public CInterface
  309. {
  310. bool logBackEndReq = true;
  311. bool logBackEndResp = true;
  312. StringArray logContentFilters;
  313. CIArrayOf<CESPLogContentGroupFilters> groupFilters;
  314. bool readLogFilters(IPropertyTree* cfg, unsigned groupID);
  315. void filterLogContentTree(StringArray& filters, IPropertyTree* originalContentTree, IPropertyTree* newLogContentTree, bool& logContentEmpty);
  316. void filterAndAddLogContentBranch(StringArray& branchNamesInFilter, unsigned idx, StringArray& branchNamesInLogContent,
  317. IPropertyTree* in, IPropertyTree* updateLogRequestTree, bool& logContentEmpty);
  318. void addLogContentBranch(StringArray& branchNames, IPropertyTree* contentToLogBranch, IPropertyTree* updateLogRequestTree);
  319. public:
  320. IMPLEMENT_IINTERFACE;
  321. CLogContentFilter() {};
  322. void readAllLogFilters(IPropertyTree* cfg);
  323. IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req);
  324. };
  325. class LOGGINGCOMMON_API CLogAgentBase : public CInterface, implements IEspLogAgent
  326. {
  327. protected:
  328. StringAttr agentName;
  329. LOGServiceType services[MAXLOGSERVICES];
  330. bool hasService(LOGServiceType service)
  331. {
  332. unsigned int i = 0;
  333. while (services[i] != LGSTterm)
  334. {
  335. if (services[i] == service)
  336. return true;
  337. i++;
  338. }
  339. return false;
  340. }
  341. void setServices(const char* servicesConfig)
  342. {
  343. StringArray serviceArray;
  344. serviceArray.appendListUniq(servicesConfig, ",");
  345. unsigned i=0;
  346. ForEachItemIn(s, serviceArray)
  347. {
  348. const char* service = serviceArray.item(s);
  349. if (service && strieq(service, "UpdateLOG"))
  350. services[i++] = LGSTUpdateLOG;
  351. else if (service && strieq(service, "GetTransactionSeed"))
  352. services[i++] = LGSTGetTransactionSeed;
  353. else if (service && strieq(service, "GetTransactionID"))
  354. services[i++] = LGSTGetTransactionID;
  355. }
  356. services[i] = LGSTterm;
  357. };
  358. public:
  359. IMPLEMENT_IINTERFACE;
  360. CLogAgentBase() { services[0] = LGSTterm; };
  361. virtual ~CLogAgentBase() {};
  362. virtual const char * getName() { return agentName.get(); };
  363. bool initVariants(IPropertyTree* cfg) override;
  364. IEspLogAgentVariantIterator* getVariants() const override;
  365. protected:
  366. class CVariant : implements CInterfaceOf<IEspLogAgentVariant>
  367. {
  368. public:
  369. CVariant(const char* name, const char* type, const char* group);
  370. const char* getName() const override { return m_name->str(); }
  371. const char* getType() const override { return m_type->str(); }
  372. const char* getGroup() const override { return m_group->str(); }
  373. private:
  374. String* normalize(const char* token);
  375. Owned<String> m_name;
  376. Owned<String> m_type;
  377. Owned<String> m_group;
  378. };
  379. using Variants = std::set<Owned<CVariant>, IEspLogAgentVariantComparator>;
  380. Variants agentVariants;
  381. class CVariantIterator : implements CInterfaceOf<const IEspLogAgentVariantIterator>
  382. {
  383. public:
  384. CVariantIterator(const CLogAgentBase& agent);
  385. ~CVariantIterator();
  386. bool first() override;
  387. bool next() override;
  388. bool isValid() override;
  389. const IEspLogAgentVariant& query() override;
  390. protected:
  391. Linked<const CLogAgentBase> m_agent;
  392. Variants::const_iterator m_variantIt;
  393. };
  394. };
  395. class LOGGINGCOMMON_API CDBLogAgentBase : public CLogAgentBase
  396. {
  397. protected:
  398. StringBuffer defaultDB, transactionTable, loggingTransactionSeed;
  399. StringAttr defaultLogGroup, defaultTransactionApp, loggingTransactionApp, logSourcePath;
  400. unsigned logSourceCount, loggingTransactionCount, maxTriesGTS;
  401. MapStringToMyClass<CLogGroup> logGroups;
  402. MapStringToMyClass<CLogSource> logSources;
  403. void readDBCfg(IPropertyTree* cfg, StringBuffer& server, StringBuffer& dbUser, StringBuffer& dbPassword);
  404. void readTransactionCfg(IPropertyTree* cfg);
  405. bool buildUpdateLogStatement(IPropertyTree* logRequest, const char* logDB, CLogTable& table, StringBuffer& logID, StringBuffer& cqlStatement);
  406. void appendFieldInfo(const char* field, StringBuffer& value, StringBuffer& fields, StringBuffer& values, bool quoted);
  407. void addMissingFields(CIArrayOf<CLogField>& logFields, BoolHash& HandledFields, StringBuffer& fields, StringBuffer& values);
  408. CLogGroup* checkLogSource(IPropertyTree* logRequest, StringBuffer& source, StringBuffer& logDB);
  409. void getLoggingTransactionID(StringBuffer& id);
  410. virtual void addField(CLogField& logField, const char* name, StringBuffer& value, StringBuffer& fields, StringBuffer& values) = 0;
  411. virtual void queryTransactionSeed(const char* appName, StringBuffer& seed) = 0;
  412. virtual void executeUpdateLogStatement(StringBuffer& statement) = 0;
  413. virtual void setUpdateLogStatement(const char* dbName, const char* tableName,
  414. const char* fields, const char* values, StringBuffer& statement) = 0;
  415. public:
  416. IMPLEMENT_IINTERFACE;
  417. CDBLogAgentBase() {};
  418. virtual ~CDBLogAgentBase() {};
  419. virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp);
  420. virtual void getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID);
  421. virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp);
  422. virtual IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req);
  423. };
  424. #endif //_LOGGINGAGENT_HPP__