|
@@ -31,6 +31,10 @@ static const char* const PropServerWaitingSeconds = "MaxServerWaitingSeconds";
|
|
|
static const char* const PropMaxTransIDLength = "MaxTransIDLength";
|
|
|
static const char* const PropMaxTransIDSequenceNumber = "MaxTransIDSequenceNumber";
|
|
|
static const char* const PropMaxTransSeedTimeoutMinutes = "MaxTransSeedTimeoutMinutes";
|
|
|
+static const char* const PropTransactionSeedType = "TransactionSeedType";
|
|
|
+static const char* const PropAlternativeTransactionSeedType = "AlternativeTransactionSeedType";
|
|
|
+static const char* const DefaultTransactionSeedType = "-";
|
|
|
+static const char* const DefaultAlternativeTransactionSeedType = "-X"; //local
|
|
|
static const char* const MaxTriesGTS = "MaxTriesGTS";
|
|
|
static const char* const appESPServerLoggingAgent = "ESPServerLoggingAgent";
|
|
|
|
|
@@ -57,6 +61,11 @@ bool CESPServerLoggingAgent::init(const char * name, const char * type, IPropert
|
|
|
maxServerWaitingSeconds = cfg->getPropInt(PropServerWaitingSeconds);
|
|
|
maxGTSRetries = cfg->getPropInt(MaxTriesGTS, DefaultMaxTriesGTS);
|
|
|
|
|
|
+ transactionSeedType.set(cfg->hasProp(PropTransactionSeedType) ? cfg->queryProp(PropTransactionSeedType) :
|
|
|
+ DefaultTransactionSeedType);
|
|
|
+ alternativeTransactionSeedType.set(cfg->hasProp(PropAlternativeTransactionSeedType) ?
|
|
|
+ cfg->queryProp(PropAlternativeTransactionSeedType) : DefaultAlternativeTransactionSeedType);
|
|
|
+
|
|
|
BoolHash uniqueGroupNames;
|
|
|
StringBuffer sourceName, groupName, dbName, localTransactionSeed;
|
|
|
Owned<IPropertyTreeIterator> iter = cfg->getElements("LogSourceMap/LogSource");
|
|
@@ -89,7 +98,7 @@ bool CESPServerLoggingAgent::init(const char * name, const char * type, IPropert
|
|
|
getTransactionSeed(groupName.str(), transactionSeed, statusMessage);
|
|
|
if (transactionSeed.length() > 0)
|
|
|
{
|
|
|
- Owned<CTransIDBuilder> entry = new CTransIDBuilder(transactionSeed.str(), false,
|
|
|
+ Owned<CTransIDBuilder> entry = new CTransIDBuilder(transactionSeed.str(), false, transactionSeedType.get(),
|
|
|
maxLength, maxSeq, seedExpiredSeconds);
|
|
|
transIDMap.setValue(groupName.str(), entry);
|
|
|
if (iter->query().getPropBool("@default", false))
|
|
@@ -99,85 +108,18 @@ bool CESPServerLoggingAgent::init(const char * name, const char * type, IPropert
|
|
|
PROGLOG("Failed to get TransactionSeed for <%s>", groupName.str());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
createLocalTransactionSeed(localTransactionSeed);
|
|
|
- Owned<CTransIDBuilder> localTransactionEntry = new CTransIDBuilder(localTransactionSeed.str(), true,
|
|
|
+ Owned<CTransIDBuilder> localTransactionEntry = new CTransIDBuilder(localTransactionSeed.str(), true, alternativeTransactionSeedType.get(),
|
|
|
cfg->getPropInt(PropMaxTransIDLength, 0), cfg->getPropInt(PropMaxTransIDSequenceNumber, 0),
|
|
|
60 * cfg->getPropInt(PropMaxTransSeedTimeoutMinutes, 0));
|
|
|
transIDMap.setValue(appESPServerLoggingAgent, localTransactionEntry);
|
|
|
|
|
|
- readAllLogFilters(cfg);
|
|
|
+ logContentFilter.readAllLogFilters(cfg);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-void CESPServerLoggingAgent::readAllLogFilters(IPropertyTree* cfg)
|
|
|
-{
|
|
|
- bool groupFilterRead = false;
|
|
|
- VStringBuffer xpath("Filters/Filter[@type='%s']", espLogContentGroupNames[ESPLCGBackEndResp]);
|
|
|
- IPropertyTree* filter = cfg->queryBranch(xpath.str());
|
|
|
- if (filter && filter->hasProp("@value"))
|
|
|
- {
|
|
|
- logBackEndResp = filter->getPropBool("@value");
|
|
|
- groupFilterRead = true;
|
|
|
- }
|
|
|
-
|
|
|
- for (unsigned i = 0; i < ESPLCGBackEndResp; i++)
|
|
|
- {
|
|
|
- if (readLogFilters(cfg, i))
|
|
|
- groupFilterRead = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (!groupFilterRead)
|
|
|
- {
|
|
|
- groupFilters.clear();
|
|
|
- readLogFilters(cfg, ESPLCGAll);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-bool CESPServerLoggingAgent::readLogFilters(IPropertyTree* cfg, unsigned groupID)
|
|
|
-{
|
|
|
- Owned<CESPLogContentGroupFilters> espLogContentGroupFilters = new CESPLogContentGroupFilters((ESPLogContentGroup) groupID);
|
|
|
- StringBuffer xpath;
|
|
|
- if (groupID != ESPLCGAll)
|
|
|
- xpath.appendf("Filters/Filter[@type='%s']", espLogContentGroupNames[groupID]);
|
|
|
- else
|
|
|
- xpath.append("Filters/Filter");
|
|
|
- Owned<IPropertyTreeIterator> filters = cfg->getElements(xpath.str());
|
|
|
- ForEach(*filters)
|
|
|
- {
|
|
|
- IPropertyTree &filter = filters->query();
|
|
|
- StringBuffer value = filter.queryProp("@value");
|
|
|
- if (!value.length())
|
|
|
- continue;
|
|
|
-
|
|
|
- //clean "//"
|
|
|
- unsigned idx = value.length()-1;
|
|
|
- while (idx)
|
|
|
- {
|
|
|
- if ((value.charAt(idx-1) == '/') && (value.charAt(idx) == '/'))
|
|
|
- value.remove(idx, 1);
|
|
|
- idx--;
|
|
|
- }
|
|
|
-
|
|
|
- //clean "/*" at the end
|
|
|
- while ((value.length() > 1) && (value.charAt(value.length()-2) == '/') && (value.charAt(value.length()-1) == '*'))
|
|
|
- value.setLength(value.length() - 2);
|
|
|
-
|
|
|
- if (value.length() && !streq(value.str(), "*") && !streq(value.str(), "/") && !streq(value.str(), "*/"))
|
|
|
- {
|
|
|
- espLogContentGroupFilters->addFilter(value.str());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- espLogContentGroupFilters->clearFilters();
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- bool hasFilter = espLogContentGroupFilters->getFilterCount() > 0;
|
|
|
- if (hasFilter)
|
|
|
- groupFilters.append(*espLogContentGroupFilters.getClear());
|
|
|
- return hasFilter;
|
|
|
-}
|
|
|
|
|
|
void CESPServerLoggingAgent::createLocalTransactionSeed(StringBuffer& transactionSeed)
|
|
|
{
|
|
@@ -282,7 +224,7 @@ void CESPServerLoggingAgent::resetTransSeed(CTransIDBuilder *builder, const char
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- builder->resetTransSeed(transactionSeed.str());
|
|
|
+ builder->resetTransSeed(transactionSeed.str(), builder->isLocalSeed() ? alternativeTransactionSeedType.get() : transactionSeedType.get());
|
|
|
};
|
|
|
|
|
|
void CESPServerLoggingAgent::getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID)
|
|
@@ -361,204 +303,9 @@ bool CESPServerLoggingAgent::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdate
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-void CESPServerLoggingAgent::addLogContentBranch(StringArray& branchNames, IPropertyTree* contentToLogBranch, IPropertyTree* updateLogRequestTree)
|
|
|
-{
|
|
|
- IPropertyTree* pTree = updateLogRequestTree;
|
|
|
- unsigned numOfBranchNames = branchNames.length();
|
|
|
- if (numOfBranchNames > 0)
|
|
|
- {
|
|
|
- unsigned i = 0;
|
|
|
- while (i < numOfBranchNames)
|
|
|
- {
|
|
|
- const char* branchName = branchNames.item(i);
|
|
|
- if (branchName && *branchName)
|
|
|
- pTree = ensurePTree(pTree, branchName);
|
|
|
- i++;
|
|
|
- }
|
|
|
- }
|
|
|
- pTree->addPropTree(contentToLogBranch->queryName(), LINK(contentToLogBranch));
|
|
|
-}
|
|
|
-
|
|
|
-void CESPServerLoggingAgent::filterAndAddLogContentBranch(StringArray& branchNamesInFilter, unsigned idx,
|
|
|
- StringArray& branchNamesInLogContent, IPropertyTree* originalLogContentBranch, IPropertyTree* updateLogRequestTree, bool& logContentEmpty)
|
|
|
-{
|
|
|
- Owned<IPropertyTreeIterator> contentItr = originalLogContentBranch->getElements(branchNamesInFilter.item(idx));
|
|
|
- ForEach(*contentItr)
|
|
|
- {
|
|
|
- IPropertyTree& contentToLogBranch = contentItr->query();
|
|
|
- if (idx == branchNamesInFilter.length() - 1)
|
|
|
- {
|
|
|
- addLogContentBranch(branchNamesInLogContent, &contentToLogBranch, updateLogRequestTree);
|
|
|
- logContentEmpty = false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- branchNamesInLogContent.append(contentToLogBranch.queryName());
|
|
|
- filterAndAddLogContentBranch(branchNamesInFilter, idx+1, branchNamesInLogContent, &contentToLogBranch,
|
|
|
- updateLogRequestTree, logContentEmpty);
|
|
|
- branchNamesInLogContent.remove(branchNamesInLogContent.length() - 1);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void CESPServerLoggingAgent::filterLogContentTree(StringArray& filters, IPropertyTree* originalContentTree, IPropertyTree* newLogContentTree, bool& logContentEmpty)
|
|
|
-{
|
|
|
- ForEachItemIn(i, filters)
|
|
|
- {
|
|
|
- const char* logContentFilter = filters.item(i);
|
|
|
- if(!logContentFilter || !*logContentFilter)
|
|
|
- continue;
|
|
|
-
|
|
|
- StringArray branchNamesInFilter, branchNamesInLogContent;
|
|
|
- branchNamesInFilter.appendListUniq(logContentFilter, "/");
|
|
|
- filterAndAddLogContentBranch(branchNamesInFilter, 0, branchNamesInLogContent, originalContentTree, newLogContentTree, logContentEmpty);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void CESPServerLoggingAgent::filterLogContent(IEspUpdateLogRequestWrap* req)
|
|
|
{
|
|
|
- const char* logContent = req->getUpdateLogRequest();
|
|
|
- Owned<IPropertyTree> updateLogRequestTree = createPTree("UpdateLogRequest");
|
|
|
-
|
|
|
- StringBuffer source;
|
|
|
- if (groupFilters.length() < 1)
|
|
|
- {//No filter
|
|
|
- if (logContent && *logContent)
|
|
|
- {
|
|
|
- Owned<IPropertyTree> pTree = createPTreeFromXMLString(logContent);
|
|
|
- source = pTree->queryProp("Source");
|
|
|
- updateLogRequestTree->addPropTree(pTree->queryName(), LINK(pTree));
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Owned<IPropertyTree> espContext = req->getESPContext();
|
|
|
- Owned<IPropertyTree> userContext = req->getUserContext();
|
|
|
- Owned<IPropertyTree> userRequest = req->getUserRequest();
|
|
|
- const char* userResp = req->getUserResponse();
|
|
|
- const char* logDatasets = req->getLogDatasets();
|
|
|
- const char* backEndResp = req->getBackEndResponse();
|
|
|
- if (!espContext && !userContext && !userRequest && (!userResp || !*userResp) && (!backEndResp || !*backEndResp))
|
|
|
- throw MakeStringException(EspLoggingErrors::UpdateLogFailed, "Failed to read log content");
|
|
|
- source = userContext->queryProp("Source");
|
|
|
-
|
|
|
- StringBuffer espContextXML, userContextXML, userRequestXML;
|
|
|
- IPropertyTree* logContentTree = ensurePTree(updateLogRequestTree, "LogContent");
|
|
|
- if (espContext)
|
|
|
- {
|
|
|
- logContentTree->addPropTree(espContext->queryName(), LINK(espContext));
|
|
|
- }
|
|
|
- if (userContext)
|
|
|
- {
|
|
|
- IPropertyTree* pTree = ensurePTree(logContentTree, espLogContentGroupNames[ESPLCGUserContext]);
|
|
|
- pTree->addPropTree(userContext->queryName(), LINK(userContext));
|
|
|
- }
|
|
|
- if (userRequest)
|
|
|
- {
|
|
|
- IPropertyTree* pTree = ensurePTree(logContentTree, espLogContentGroupNames[ESPLCGUserReq]);
|
|
|
- pTree->addPropTree(userRequest->queryName(), LINK(userRequest));
|
|
|
- }
|
|
|
- if (userResp && *userResp)
|
|
|
- {
|
|
|
- IPropertyTree* pTree = ensurePTree(logContentTree, espLogContentGroupNames[ESPLCGUserResp]);
|
|
|
- Owned<IPropertyTree> userRespTree = createPTreeFromXMLString(userResp);
|
|
|
- pTree->addPropTree(userRespTree->queryName(), LINK(userRespTree));
|
|
|
- }
|
|
|
- if (logDatasets && *logDatasets)
|
|
|
- {
|
|
|
- IPropertyTree* pTree = ensurePTree(logContentTree, espLogContentGroupNames[ESPLCGLogDatasets]);
|
|
|
- Owned<IPropertyTree> logDatasetTree = createPTreeFromXMLString(logDatasets);
|
|
|
- pTree->addPropTree(logDatasetTree->queryName(), LINK(logDatasetTree));
|
|
|
- }
|
|
|
- if (backEndResp && *backEndResp)
|
|
|
- logContentTree->addProp(espLogContentGroupNames[ESPLCGBackEndResp], backEndResp);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- bool logContentEmpty = true;
|
|
|
- IPropertyTree* logContentTree = ensurePTree(updateLogRequestTree, "LogContent");
|
|
|
- if (logContent && *logContent)
|
|
|
- {
|
|
|
- Owned<IPropertyTree> originalContentTree = createPTreeFromXMLString(logContent);
|
|
|
- source = originalContentTree->queryProp("Source");
|
|
|
- filterLogContentTree(groupFilters.item(0).getFilters(), originalContentTree, logContentTree, logContentEmpty);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- for (unsigned group = 0; group < ESPLCGBackEndResp; group++)
|
|
|
- {
|
|
|
- Owned<IPropertyTree> originalContentTree;
|
|
|
- if (group == ESPLCGESPContext)
|
|
|
- originalContentTree.setown(req->getESPContext());
|
|
|
- else if (group == ESPLCGUserContext)
|
|
|
- {
|
|
|
- originalContentTree.setown(req->getUserContext());
|
|
|
- source = originalContentTree->queryProp("Source");
|
|
|
- }
|
|
|
- else if (group == ESPLCGUserReq)
|
|
|
- originalContentTree.setown(req->getUserRequest());
|
|
|
- else if (group == ESPLCGLogDatasets)
|
|
|
- {
|
|
|
- const char* logDatasets = req->getLogDatasets();
|
|
|
- if (logDatasets && *logDatasets)
|
|
|
- originalContentTree.setown(createPTreeFromXMLString(logDatasets));
|
|
|
- }
|
|
|
- else //group = ESPLCGUserResp
|
|
|
- {
|
|
|
- const char* resp = req->getUserResponse();
|
|
|
- if (!resp || !*resp)
|
|
|
- continue;
|
|
|
- originalContentTree.setown(createPTreeFromXMLString(resp));
|
|
|
- }
|
|
|
- if (!originalContentTree)
|
|
|
- continue;
|
|
|
-
|
|
|
- IPropertyTree* newContentTree = ensurePTree(logContentTree, espLogContentGroupNames[group]);
|
|
|
- bool hasFilters = false;
|
|
|
- ForEachItemIn(i, groupFilters)
|
|
|
- {
|
|
|
- CESPLogContentGroupFilters& filtersGroup = groupFilters.item(i);
|
|
|
- if (filtersGroup.getGroup() == group)
|
|
|
- {
|
|
|
- if (group != ESPLCGESPContext)//For non ESPLCGESPContext, we want to keep the root of original tree.
|
|
|
- newContentTree = ensurePTree(newContentTree, originalContentTree->queryName());
|
|
|
- filterLogContentTree(filtersGroup.getFilters(), originalContentTree, newContentTree, logContentEmpty);
|
|
|
- hasFilters = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!hasFilters)
|
|
|
- {
|
|
|
- newContentTree->addPropTree(originalContentTree->queryName(), LINK(originalContentTree));
|
|
|
- logContentEmpty = false;
|
|
|
- }
|
|
|
- }
|
|
|
- if (logBackEndResp)
|
|
|
- {
|
|
|
- const char* resp = req->getBackEndResponse();
|
|
|
- if (resp && *resp)
|
|
|
- {
|
|
|
- logContentTree->addProp(espLogContentGroupNames[ESPLCGBackEndResp], resp);
|
|
|
- logContentEmpty = false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (logContentEmpty)
|
|
|
- throw MakeStringException(EspLoggingErrors::UpdateLogFailed, "Failed to read log content");
|
|
|
- }
|
|
|
- if (!source.isEmpty())
|
|
|
- updateLogRequestTree->addProp("LogContent/Source", source.str());
|
|
|
-
|
|
|
- const char* option = req->getOption();
|
|
|
- if (option && *option)
|
|
|
- updateLogRequestTree->addProp("Option", option);
|
|
|
-
|
|
|
- StringBuffer updateLogRequestXML;
|
|
|
- toXML(updateLogRequestTree, updateLogRequestXML);
|
|
|
- ESPLOG(LogMax, "filtered content and option: <%s>", updateLogRequestXML.str());
|
|
|
- req->clearOriginalContent();
|
|
|
- req->setUpdateLogRequest(updateLogRequestXML.str());
|
|
|
+ logContentFilter.filterLogContent(req);
|
|
|
}
|
|
|
|
|
|
bool CESPServerLoggingAgent::sendHTTPRequest(StringBuffer& req, StringBuffer &resp, StringBuffer &status)
|