loggingagentbase.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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. enum ESPLogContentGroup
  23. {
  24. ESPLCGESPContext = 0,
  25. ESPLCGUserContext = 1,
  26. ESPLCGUserReq = 2,
  27. ESPLCGUserResp = 3,
  28. ESPLCGLogDatasets = 4,
  29. ESPLCGBackEndReq = 5,
  30. ESPLCGBackEndResp = 5,
  31. ESPLCGAll = 6
  32. };
  33. static const char * const espLogContentGroupNames[] = { "ESPContext", "UserContext", "UserRequest", "UserResponse",
  34. "LogDatasets", "BackEndRequest", "BackEndResponse", "", NULL };
  35. #define UPDATELOGTHREADWAITINGTIME 3000
  36. //The 'TransactionXYZ' is expected for the following key strings
  37. //used in CTransIDBuilder::getTransID() -> add().
  38. static const char* sTransactionDateTime = "TransactionDateTime";
  39. static const char* sTransactionMethod = "TransactionMethod";
  40. static const char* sTransactionIdentifier = "TransactionIdentifier";
  41. class CTransIDBuilder : public CInterface, implements IInterface
  42. {
  43. StringAttr seed, seedType;
  44. bool localSeed;
  45. unsigned __int64 seq = 0;
  46. unsigned maxLength = 0;
  47. unsigned maxSeq = 0;
  48. unsigned seedExpiredSeconds = 0;
  49. time_t createTime;
  50. void add(StringAttrMapping* transIDFields, const char* key, StringBuffer& id)
  51. {
  52. StringAttr* value = transIDFields->getValue(key);
  53. if (value)
  54. id.append(value->get()).append('-');
  55. else
  56. {
  57. const char* ptr = key;
  58. if (strlen(key) > 11) //skip the "transaction" prefix of the key
  59. ptr += 11;
  60. id.append('?').append(ptr).append('-');
  61. }
  62. }
  63. public:
  64. IMPLEMENT_IINTERFACE;
  65. CTransIDBuilder(const char* _seed, bool _localSeed, const char* _seedType, unsigned _maxLength, unsigned _maxSeq, unsigned _seedExpiredSeconds)
  66. : seed(_seed), localSeed(_localSeed), seedType(_seedType), maxLength(_maxLength), maxSeq(_maxSeq), seedExpiredSeconds(_seedExpiredSeconds)
  67. {
  68. CDateTime now;
  69. now.setNow();
  70. createTime = now.getSimple();
  71. };
  72. virtual ~CTransIDBuilder() {};
  73. bool checkMaxSequenceNumber() { return (maxSeq == 0) || (seq < maxSeq); };
  74. bool checkMaxLength(unsigned length) { return (maxLength == 0) || (length <= maxLength); };
  75. bool checkTimeout()
  76. {
  77. if (seedExpiredSeconds ==0)
  78. return true;
  79. CDateTime now;
  80. now.setNow();
  81. return now.getSimple() < createTime + seedExpiredSeconds;
  82. };
  83. bool isLocalSeed() { return localSeed; };
  84. void resetTransSeed(const char* newSeed, const char* newSeedType)
  85. {
  86. if (isEmptyString(newSeed))
  87. throw MakeStringException(EspLoggingErrors::GetTransactionSeedFailed, "TransactionSeed cannot be empty.");
  88. seed.set(newSeed);
  89. seedType.set(newSeedType);
  90. seq = 0;
  91. CDateTime now;
  92. now.setNow();
  93. createTime = now.getSimple();
  94. };
  95. virtual const char* getTransSeed() { return seed.get(); };
  96. virtual void getTransID(StringAttrMapping* transIDFields, StringBuffer& id)
  97. {
  98. id.clear();
  99. if (transIDFields)
  100. {
  101. add(transIDFields, sTransactionDateTime, id);
  102. add(transIDFields, sTransactionMethod, id);
  103. add(transIDFields, sTransactionIdentifier, id);
  104. }
  105. id.append(seed.get());
  106. if (seedType.length())
  107. id.append(seedType.get());
  108. id.append(++seq);
  109. };
  110. };
  111. interface IEspUpdateLogRequestWrap : extends IInterface
  112. {
  113. virtual const char* getGUID()=0;
  114. virtual const char* getOption()=0;
  115. virtual const char* getUpdateLogRequest()=0;
  116. virtual IPropertyTree* getESPContext()=0;
  117. virtual IPropertyTree* getUserContext()=0;
  118. virtual IPropertyTree* getUserRequest()=0;
  119. virtual IPropertyTree* getLogRequestTree()=0;
  120. virtual IInterface* getExtraLog()=0;
  121. virtual const char* getBackEndRequest()=0;
  122. virtual const char* getBackEndResponse()=0;
  123. virtual const char* getUserResponse()=0;
  124. virtual const char* getLogDatasets()=0;
  125. virtual const bool getNoResend()=0;
  126. virtual void setGUID(const char* val)=0;
  127. virtual void setOption(const char* val)=0;
  128. virtual void setUpdateLogRequest(const char* val)=0;
  129. virtual void setESPContext(IPropertyTree* val)=0;
  130. virtual void setUserContext(IPropertyTree* val)=0;
  131. virtual void setUserRequest(IPropertyTree* val)=0;
  132. virtual void setLogRequestTree(IPropertyTree* val)=0;
  133. virtual void setExtraLog(IInterface* val)=0;
  134. virtual void setBackEndRequest(const char* val)=0;
  135. virtual void setBackEndResponse(const char* val)=0;
  136. virtual void setUserResponse(const char* val)=0;
  137. virtual void setLogDatasets(const char* val)=0;
  138. virtual unsigned incrementRetryCount() = 0;
  139. virtual void setNoResend(bool val)=0;
  140. virtual void clearOriginalContent() = 0;
  141. };
  142. class CUpdateLogRequestWrap : implements IEspUpdateLogRequestWrap, public CInterface
  143. {
  144. StringAttr GUID;
  145. StringAttr option;
  146. StringAttr updateLogRequest;
  147. Owned<IPropertyTree> espContext;
  148. Owned<IPropertyTree> userContext;
  149. Owned<IPropertyTree> userRequest;
  150. Owned<IPropertyTree> logRequestTree;
  151. Owned<IInterface> extraLog;
  152. StringAttr backEndRequest, backEndResponse;
  153. StringAttr userResponse;
  154. StringAttr logDatasets;
  155. unsigned retryCount;
  156. bool noResend = false;;
  157. public:
  158. IMPLEMENT_IINTERFACE;
  159. CUpdateLogRequestWrap(const char* _GUID, const char* _option, const char* _updateLogRequest)
  160. : GUID(_GUID), option(_option), updateLogRequest(_updateLogRequest), retryCount(0) {};
  161. CUpdateLogRequestWrap(const char* _GUID, const char* _option, IPropertyTree* _espContext,
  162. IPropertyTree*_userContext, IPropertyTree*_userRequest, const char *_backEndRequest,
  163. const char *_backEndResponse, const char *_userResponse, const char *_logDatasets)
  164. : GUID(_GUID), option(_option), backEndRequest(_backEndRequest), backEndResponse(_backEndResponse),
  165. userResponse(_userResponse), logDatasets(_logDatasets), retryCount(0)
  166. {
  167. userContext.setown(_userContext);
  168. espContext.setown(_espContext);
  169. userRequest.setown(_userRequest);
  170. };
  171. CUpdateLogRequestWrap(const char* _GUID, const char* _option, IPropertyTree* _logInfo,
  172. IInterface* _extraLog) : GUID(_GUID), option(_option), retryCount(0)
  173. {
  174. logRequestTree.setown(_logInfo);
  175. extraLog.setown(_extraLog);
  176. };
  177. void clearOriginalContent()
  178. {
  179. espContext.clear();
  180. userRequest.clear();
  181. userContext.clear();
  182. userResponse.clear();
  183. logDatasets.clear();
  184. backEndRequest.clear();
  185. backEndResponse.clear();
  186. updateLogRequest.clear();
  187. logRequestTree.clear();
  188. extraLog.clear();
  189. };
  190. const char* getGUID() {return GUID.get();};
  191. const char* getOption() {return option.get();};
  192. const char* getUpdateLogRequest() {return updateLogRequest.get();};
  193. IPropertyTree* getESPContext() {return espContext.getLink();};
  194. IPropertyTree* getUserContext() {return userContext.getLink();};
  195. IPropertyTree* getUserRequest() {return userRequest.getLink();};
  196. IPropertyTree* getLogRequestTree() {return logRequestTree.getLink();};
  197. IInterface* getExtraLog() {return extraLog.getLink();};
  198. const char* getBackEndRequest() {return backEndRequest.get();};
  199. const char* getBackEndResponse() {return backEndResponse.get();};
  200. const char* getUserResponse() {return userResponse.get();};
  201. const char* getLogDatasets() {return logDatasets.get();};
  202. const bool getNoResend() {return noResend;};
  203. void setGUID(const char* val) {GUID.set(val);};
  204. void setOption(const char* val) {option.set(val);};
  205. void setUpdateLogRequest(const char* val) {updateLogRequest.set(val);};
  206. void setESPContext(IPropertyTree* val) {espContext.setown(val);};
  207. void setUserContext(IPropertyTree* val) {userContext.setown(val);};
  208. void setUserRequest(IPropertyTree* val) {userRequest.setown(val);};
  209. void setLogRequestTree(IPropertyTree* val) {logRequestTree.setown(val);};
  210. void setExtraLog(IInterface* val) {extraLog.setown(val);};
  211. void setBackEndRequest(const char* val) {backEndRequest.set(val);};
  212. void setBackEndResponse(const char* val) {backEndResponse.set(val);};
  213. void setUserResponse(const char* val) {userResponse.set(val);};
  214. void setLogDatasets(const char* val) {logDatasets.set(val);};
  215. unsigned incrementRetryCount() { retryCount++; return retryCount;};
  216. void setNoResend(bool val) { noResend = val; };
  217. };
  218. interface IEspLogAgent : extends IInterface
  219. {
  220. virtual bool init(const char * name, const char * type, IPropertyTree * cfg, const char * process) = 0;
  221. virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp) = 0;
  222. virtual void getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID) = 0;
  223. virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp) = 0;
  224. virtual bool hasService(LOGServiceType service) = 0;
  225. virtual IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req) = 0;
  226. };
  227. class CESPLogContentGroupFilters : public CInterface, implements IInterface
  228. {
  229. ESPLogContentGroup group;
  230. StringArray filters;
  231. public:
  232. IMPLEMENT_IINTERFACE;
  233. CESPLogContentGroupFilters(ESPLogContentGroup _group) : group(_group) {};
  234. ESPLogContentGroup getGroup() { return group; };
  235. StringArray& getFilters() { return filters; };
  236. void clearFilters() { filters.clear(); };
  237. unsigned getFilterCount() { return filters.length(); };
  238. void addFilter(const char* filter)
  239. {
  240. if (filter && *filter)
  241. filters.append(filter);
  242. };
  243. };
  244. class LOGGINGCOMMON_API CLogContentFilter : public CInterface
  245. {
  246. bool logBackEndReq = true;
  247. bool logBackEndResp = true;
  248. StringArray logContentFilters;
  249. CIArrayOf<CESPLogContentGroupFilters> groupFilters;
  250. bool readLogFilters(IPropertyTree* cfg, unsigned groupID);
  251. void filterLogContentTree(StringArray& filters, IPropertyTree* originalContentTree, IPropertyTree* newLogContentTree, bool& logContentEmpty);
  252. void filterAndAddLogContentBranch(StringArray& branchNamesInFilter, unsigned idx, StringArray& branchNamesInLogContent,
  253. IPropertyTree* in, IPropertyTree* updateLogRequestTree, bool& logContentEmpty);
  254. void addLogContentBranch(StringArray& branchNames, IPropertyTree* contentToLogBranch, IPropertyTree* updateLogRequestTree);
  255. public:
  256. IMPLEMENT_IINTERFACE;
  257. CLogContentFilter() {};
  258. void readAllLogFilters(IPropertyTree* cfg);
  259. IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req);
  260. };
  261. class LOGGINGCOMMON_API CLogAgentBase : public CInterface, implements IEspLogAgent
  262. {
  263. protected:
  264. StringAttr agentName;
  265. LOGServiceType services[MAXLOGSERVICES];
  266. bool hasService(LOGServiceType service)
  267. {
  268. unsigned int i = 0;
  269. while (services[i] != LGSTterm)
  270. {
  271. if (services[i] == service)
  272. return true;
  273. i++;
  274. }
  275. return false;
  276. }
  277. void setServices(const char* servicesConfig)
  278. {
  279. StringArray serviceArray;
  280. serviceArray.appendListUniq(servicesConfig, ",");
  281. unsigned i=0;
  282. ForEachItemIn(s, serviceArray)
  283. {
  284. const char* service = serviceArray.item(s);
  285. if (service && strieq(service, "UpdateLOG"))
  286. services[i++] = LGSTUpdateLOG;
  287. else if (service && strieq(service, "GetTransactionSeed"))
  288. services[i++] = LGSTGetTransactionSeed;
  289. else if (service && strieq(service, "GetTransactionID"))
  290. services[i++] = LGSTGetTransactionID;
  291. }
  292. services[i] = LGSTterm;
  293. };
  294. public:
  295. IMPLEMENT_IINTERFACE;
  296. CLogAgentBase() { services[0] = LGSTterm; };
  297. virtual ~CLogAgentBase() {};
  298. };
  299. class LOGGINGCOMMON_API CDBLogAgentBase : public CLogAgentBase
  300. {
  301. protected:
  302. StringBuffer defaultDB, transactionTable, loggingTransactionSeed;
  303. StringAttr defaultLogGroup, defaultTransactionApp, loggingTransactionApp, logSourcePath;
  304. unsigned logSourceCount, loggingTransactionCount, maxTriesGTS;
  305. MapStringToMyClass<CLogGroup> logGroups;
  306. MapStringToMyClass<CLogSource> logSources;
  307. void readDBCfg(IPropertyTree* cfg, StringBuffer& server, StringBuffer& dbUser, StringBuffer& dbPassword);
  308. void readTransactionCfg(IPropertyTree* cfg);
  309. bool buildUpdateLogStatement(IPropertyTree* logRequest, const char* logDB, CLogTable& table, StringBuffer& logID, StringBuffer& cqlStatement);
  310. void appendFieldInfo(const char* field, StringBuffer& value, StringBuffer& fields, StringBuffer& values, bool quoted);
  311. void addMissingFields(CIArrayOf<CLogField>& logFields, BoolHash& HandledFields, StringBuffer& fields, StringBuffer& values);
  312. CLogGroup* checkLogSource(IPropertyTree* logRequest, StringBuffer& source, StringBuffer& logDB);
  313. void getLoggingTransactionID(StringBuffer& id);
  314. virtual void addField(CLogField& logField, const char* name, StringBuffer& value, StringBuffer& fields, StringBuffer& values) = 0;
  315. virtual void queryTransactionSeed(const char* appName, StringBuffer& seed) = 0;
  316. virtual void executeUpdateLogStatement(StringBuffer& statement) = 0;
  317. virtual void setUpdateLogStatement(const char* dbName, const char* tableName,
  318. const char* fields, const char* values, StringBuffer& statement) = 0;
  319. public:
  320. IMPLEMENT_IINTERFACE;
  321. CDBLogAgentBase() {};
  322. virtual ~CDBLogAgentBase() {};
  323. virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp);
  324. virtual void getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID);
  325. virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp);
  326. virtual IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req);
  327. };
  328. #endif //_LOGGINGAGENT_HPP__