Browse Source

HPCC-21168 Setup ESP logging agent to only run specified services

The changes are for all ESP logging agents (MySQLLoggingAgent,
CassandraLoggingAgent, ESPServerLoggingAgent, and
WSLogServiceLoggingAgent).

1. Modify setting scripts to allow users to set which logging services are
provided by a logging agent;
2. Create CLogAgentBase for basic functions shared by all log agents;
3. Move agent name and agent services into CLogAgentBase;
4. Set agent name and agent services in all log agent;
5. Call transaction seed/ID functions only the transaction seed/ID services
is set for the log agent;
6. Call UpdateLog functions only the UpdateLog service is set for the log
agent.

Signed-off-by: wangkx <kevin.wang@lexisnexis.com>
wangkx 6 years ago
parent
commit
249eefbe56

+ 20 - 9
esp/logging/loggingagent/cassandraloggingagent/cassandralogagent.cpp

@@ -43,24 +43,35 @@ bool CCassandraLogAgent::init(const char* name, const char* type, IPropertyTree*
     if (!cfg)
     if (!cfg)
         throw MakeStringException(-1, "Unable to find configuration for log agent %s:%s", name, type);
         throw MakeStringException(-1, "Unable to find configuration for log agent %s:%s", name, type);
 
 
+    agentName.set(name);
+    const char* servicesConfig = cfg->queryProp("@services");
+    if (isEmptyString(servicesConfig))
+        throw MakeStringException(-1,"No Logging Service defined for %s", agentName.get());
+    setServices(servicesConfig);
+
     IPropertyTree* cassandra = cfg->queryBranch("Cassandra");
     IPropertyTree* cassandra = cfg->queryBranch("Cassandra");
     if(!cassandra)
     if(!cassandra)
         throw MakeStringException(-1, "Unable to find Cassandra settings for log agent %s:%s", name, type);
         throw MakeStringException(-1, "Unable to find Cassandra settings for log agent %s:%s", name, type);
 
 
     readDBCfg(cassandra, dbServer, dbUserID, dbPassword);
     readDBCfg(cassandra, dbServer, dbUserID, dbPassword);
 
 
-    //Read information about data mapping for every log groups
-    readLogGroupCfg(cfg, defaultLogGroup, logGroups);
-    if (defaultLogGroup.isEmpty())
-        throw MakeStringException(-1,"LogGroup not defined");
+    if (hasService(LGSTUpdateLOG))
+    {
+        //Read information about data mapping for every log groups
+        readLogGroupCfg(cfg, defaultLogGroup, logGroups);
+        if (defaultLogGroup.isEmpty())
+            throw MakeStringException(-1,"LogGroup not defined");
 
 
-    //Read mapping between log sources and log groups
-    readLogSourceCfg(cfg, logSourceCount, logSourcePath, logSources);
+        //Read mapping between log sources and log groups
+        readLogSourceCfg(cfg, logSourceCount, logSourcePath, logSources);
+    }
 
 
     //Read transactions settings
     //Read transactions settings
-    readTransactionCfg(cfg);
-
-    maxTriesGTS = cfg->getPropInt("MaxTriesGTS", defaultMaxTriesGTS);
+    if (hasService(LGSTGetTransactionSeed))
+    {
+        readTransactionCfg(cfg);
+        maxTriesGTS = cfg->getPropInt("MaxTriesGTS", defaultMaxTriesGTS);
+    }
 
 
     //Setup Cassandra
     //Setup Cassandra
     initKeySpace();
     initKeySpace();

+ 68 - 43
esp/logging/loggingagent/espserverloggingagent/loggingagent.cpp

@@ -43,6 +43,12 @@ bool CESPServerLoggingAgent::init(const char * name, const char * type, IPropert
     if (!cfg)
     if (!cfg)
         return false;
         return false;
 
 
+    agentName.set(name);
+    const char* servicesConfig = cfg->queryProp("@services");
+    if (isEmptyString(servicesConfig))
+        throw MakeStringException(-1,"No Logging Service defined for %s", agentName.get());
+    setServices(servicesConfig);
+
     IPropertyTree* espServer = cfg->queryBranch(PropESPServer);
     IPropertyTree* espServer = cfg->queryBranch(PropESPServer);
     if(!espServer)
     if(!espServer)
         throw MakeStringException(-1,"Unable to find ESPServer settings for log agent %s:%s", name, type);
         throw MakeStringException(-1,"Unable to find ESPServer settings for log agent %s:%s", name, type);
@@ -59,63 +65,73 @@ bool CESPServerLoggingAgent::init(const char * name, const char * type, IPropert
         decrypt(serverPassword, password);
         decrypt(serverPassword, password);
     }
     }
     maxServerWaitingSeconds = cfg->getPropInt(PropServerWaitingSeconds);
     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");
-    ForEach(*iter)
+    if (hasService(LGSTUpdateLOG))
     {
     {
-        ensureInputString(iter->query().queryProp("@name"), false, sourceName, -1, "LogSource @name required");
-        ensureInputString(iter->query().queryProp("@maptologgroup"), true, groupName, -1, "LogSource @maptologgroup required");
-        ensureInputString(iter->query().queryProp("@maptodb"), true, dbName, -1, "LogSource @maptodb required");
-        Owned<CLogSource> logSource = new CLogSource(sourceName.str(), groupName.str(), dbName.str());
-        logSources.setValue(sourceName.str(), logSource);
-
-        bool* found = uniqueGroupNames.getValue(groupName.str());
-        if (!found || !*found)
+        BoolHash uniqueGroupNames;
+        StringBuffer sourceName, groupName, dbName;
+        Owned<IPropertyTreeIterator> iter = cfg->getElements("LogSourceMap/LogSource");
+        ForEach(*iter)
         {
         {
-            uniqueGroupNames.setValue(groupName.str(), true);
-
-            unsigned maxSeq = 0;
-            unsigned maxLength = 0;
-            unsigned seedExpiredSeconds = 0;
-            VStringBuffer xpath("LogGroup/[@name='%s']", groupName.str());
-            IPropertyTree* logGroup = cfg->queryBranch(xpath.str());
-            if (logGroup)
-            {
-                maxLength = logGroup->getPropInt(PropMaxTransIDLength, 0);
-                maxSeq = logGroup->getPropInt(PropMaxTransIDSequenceNumber, 0),
-                seedExpiredSeconds = 60 * logGroup->getPropInt(PropMaxTransSeedTimeoutMinutes, 0);
-            }
-
-            StringBuffer transactionSeed, statusMessage;
-            getTransactionSeed(groupName.str(), transactionSeed, statusMessage);
-            if (transactionSeed.length() > 0)
+            ensureInputString(iter->query().queryProp("@name"), false, sourceName, -1, "LogSource @name required");
+            ensureInputString(iter->query().queryProp("@maptologgroup"), true, groupName, -1, "LogSource @maptologgroup required");
+            ensureInputString(iter->query().queryProp("@maptodb"), true, dbName, -1, "LogSource @maptodb required");
+            Owned<CLogSource> logSource = new CLogSource(sourceName.str(), groupName.str(), dbName.str());
+            logSources.setValue(sourceName.str(), logSource);
+
+            bool* found = uniqueGroupNames.getValue(groupName.str());
+            if (!found || !*found)
             {
             {
-                Owned<CTransIDBuilder> entry = new CTransIDBuilder(transactionSeed.str(), false, transactionSeedType.get(),
-                    maxLength, maxSeq, seedExpiredSeconds);
-                transIDMap.setValue(groupName.str(), entry);
-                if (iter->query().getPropBool("@default", false))
-                    defaultGroup.set(groupName.str());
+                uniqueGroupNames.setValue(groupName.str(), true);
+
+                unsigned maxSeq = 0;
+                unsigned maxLength = 0;
+                unsigned seedExpiredSeconds = 0;
+                VStringBuffer xpath("LogGroup/[@name='%s']", groupName.str());
+                IPropertyTree* logGroup = cfg->queryBranch(xpath.str());
+                if (logGroup)
+                {
+                    maxLength = logGroup->getPropInt(PropMaxTransIDLength, 0);
+                    maxSeq = logGroup->getPropInt(PropMaxTransIDSequenceNumber, 0),
+                    seedExpiredSeconds = 60 * logGroup->getPropInt(PropMaxTransSeedTimeoutMinutes, 0);
+                }
+
+                if (!hasService(LGSTGetTransactionSeed) && !hasService(LGSTGetTransactionID))
+                    continue;
+
+                StringBuffer transactionSeed, statusMessage;
+                getTransactionSeed(groupName.str(), transactionSeed, statusMessage);
+                if (transactionSeed.length() > 0)
+                {
+                    Owned<CTransIDBuilder> entry = new CTransIDBuilder(transactionSeed.str(), false, transactionSeedType.get(),
+                        maxLength, maxSeq, seedExpiredSeconds);
+                    transIDMap.setValue(groupName.str(), entry);
+                    if (iter->query().getPropBool("@default", false))
+                        defaultGroup.set(groupName.str());
+                }
+                else
+                    PROGLOG("Failed to get TransactionSeed for <%s>", groupName.str());
             }
             }
-            else
-                PROGLOG("Failed to get TransactionSeed for <%s>", groupName.str());
         }
         }
+        logContentFilter.readAllLogFilters(cfg);
     }
     }
 
 
+    if (!hasService(LGSTGetTransactionSeed) && !hasService(LGSTGetTransactionID))
+        return true;
+
+    maxGTSRetries = cfg->getPropInt(MaxTriesGTS, DefaultMaxTriesGTS);
+    transactionSeedType.set(cfg->hasProp(PropTransactionSeedType) ? cfg->queryProp(PropTransactionSeedType) :
+        DefaultTransactionSeedType);
+    alternativeTransactionSeedType.set(cfg->hasProp(PropAlternativeTransactionSeedType) ?
+        cfg->queryProp(PropAlternativeTransactionSeedType) : DefaultAlternativeTransactionSeedType);
+
+    StringBuffer localTransactionSeed;
     createLocalTransactionSeed(localTransactionSeed);
     createLocalTransactionSeed(localTransactionSeed);
     Owned<CTransIDBuilder> localTransactionEntry = new CTransIDBuilder(localTransactionSeed.str(), true, alternativeTransactionSeedType.get(),
     Owned<CTransIDBuilder> localTransactionEntry = new CTransIDBuilder(localTransactionSeed.str(), true, alternativeTransactionSeedType.get(),
         cfg->getPropInt(PropMaxTransIDLength, 0), cfg->getPropInt(PropMaxTransIDSequenceNumber, 0),
         cfg->getPropInt(PropMaxTransIDLength, 0), cfg->getPropInt(PropMaxTransIDSequenceNumber, 0),
         60 * cfg->getPropInt(PropMaxTransSeedTimeoutMinutes, 0));
         60 * cfg->getPropInt(PropMaxTransSeedTimeoutMinutes, 0));
     transIDMap.setValue(appESPServerLoggingAgent, localTransactionEntry);
     transIDMap.setValue(appESPServerLoggingAgent, localTransactionEntry);
 
 
-    logContentFilter.readAllLogFilters(cfg);
     return true;
     return true;
 }
 }
 
 
@@ -132,6 +148,9 @@ void CESPServerLoggingAgent::createLocalTransactionSeed(StringBuffer& transactio
 
 
 bool CESPServerLoggingAgent::getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp)
 bool CESPServerLoggingAgent::getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp)
 {
 {
+    if (!hasService(LGSTGetTransactionSeed))
+        throw MakeStringException(EspLoggingErrors::GetTransactionSeedFailed, "%s: no getTransactionSeed service configured", agentName.get());
+
     StringBuffer statusMessage, transactionSeed;
     StringBuffer statusMessage, transactionSeed;
     int statusCode = getTransactionSeed(req.getApplication(), transactionSeed, statusMessage);
     int statusCode = getTransactionSeed(req.getApplication(), transactionSeed, statusMessage);
     resp.setStatusCode(statusCode);
     resp.setStatusCode(statusCode);
@@ -229,6 +248,9 @@ void CESPServerLoggingAgent::resetTransSeed(CTransIDBuilder *builder, const char
 
 
 void CESPServerLoggingAgent::getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID)
 void CESPServerLoggingAgent::getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID)
 {
 {
+    if (!hasService(LGSTGetTransactionID))
+        throw MakeStringException(EspLoggingErrors::GetTransactionSeedFailed, "%s: no getTransactionID service configured", agentName.get());
+
     const char* groupName = nullptr;
     const char* groupName = nullptr;
     CTransIDBuilder* transIDBuilder = nullptr;
     CTransIDBuilder* transIDBuilder = nullptr;
     StringAttr* source = nullptr;
     StringAttr* source = nullptr;
@@ -272,6 +294,9 @@ bool CESPServerLoggingAgent::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdate
 {
 {
     try
     try
     {
     {
+        if (!hasService(LGSTUpdateLOG))
+            throw MakeStringException(EspLoggingErrors::UpdateLogFailed, "%s: no updateLog service configured", agentName.get());
+
         StringBuffer soapreq(
         StringBuffer soapreq(
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""
             "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""

+ 1 - 1
esp/logging/loggingagent/espserverloggingagent/loggingagent.hpp

@@ -27,7 +27,7 @@
     #define ESPSERVERLOGGINGAGENT_API DECL_IMPORT
     #define ESPSERVERLOGGINGAGENT_API DECL_IMPORT
 #endif
 #endif
 
 
-class CESPServerLoggingAgent : public CInterface, implements IEspLogAgent
+class CESPServerLoggingAgent : public CLogAgentBase
 {
 {
     StringBuffer serviceName, loggingAgentName, defaultGroup;
     StringBuffer serviceName, loggingAgentName, defaultGroup;
     StringBuffer serverUrl, serverUserID, serverPassword;
     StringBuffer serverUrl, serverUserID, serverPassword;

+ 6 - 0
esp/logging/logginglib/loggingagentbase.cpp

@@ -321,6 +321,9 @@ void CDBLogAgentBase::readTransactionCfg(IPropertyTree* cfg)
 
 
 bool CDBLogAgentBase::getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp)
 bool CDBLogAgentBase::getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp)
 {
 {
+    if (!hasService(LGSTGetTransactionSeed))
+        throw MakeStringException(EspLoggingErrors::GetTransactionSeedFailed, "%s: no getTransactionSeed service configured", agentName.get());
+
     bool bRet = false;
     bool bRet = false;
     StringBuffer appName = req.getApplication();
     StringBuffer appName = req.getApplication();
     appName.trim();
     appName.trim();
@@ -366,6 +369,9 @@ bool CDBLogAgentBase::getTransactionSeed(IEspGetTransactionSeedRequest& req, IEs
 
 
 bool CDBLogAgentBase::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp)
 bool CDBLogAgentBase::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp)
 {
 {
+    if (!hasService(LGSTUpdateLOG))
+        throw MakeStringException(EspLoggingErrors::UpdateLogFailed, "%s: no updateLog service configured", agentName.get());
+
     unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
     unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
     bool ret = false;
     bool ret = false;
     try
     try

+ 45 - 1
esp/logging/logginglib/loggingagentbase.hpp

@@ -241,6 +241,7 @@ interface IEspLogAgent : extends IInterface
     virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp) = 0;
     virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp) = 0;
     virtual void getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID) = 0;
     virtual void getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID) = 0;
     virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp) = 0;
     virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp) = 0;
+    virtual bool hasService(LOGServiceType service) = 0;
     virtual IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req) = 0;
     virtual IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req) = 0;
 };
 };
 
 
@@ -284,7 +285,50 @@ public:
     IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req);
     IEspUpdateLogRequestWrap* filterLogContent(IEspUpdateLogRequestWrap* req);
 };
 };
 
 
-class LOGGINGCOMMON_API CDBLogAgentBase : public CInterface, implements IEspLogAgent
+class LOGGINGCOMMON_API CLogAgentBase : public CInterface, implements IEspLogAgent
+{
+protected:
+    StringAttr agentName;
+    LOGServiceType services[MAXLOGSERVICES];
+
+    bool hasService(LOGServiceType service)
+    {
+        unsigned int i = 0;
+        while (services[i] != LGSTterm)
+        {
+            if (services[i] == service)
+                return true;
+            i++;
+        }
+        return false;
+    }
+    void setServices(const char* servicesConfig)
+    {
+        StringArray serviceArray;
+        serviceArray.appendListUniq(servicesConfig, ",");
+
+        unsigned i=0;
+        ForEachItemIn(s, serviceArray)
+        {
+            const char* service = serviceArray.item(s);
+            if (service && strieq(service, "UpdateLOG"))
+                services[i++] = LGSTUpdateLOG;
+            else if (service && strieq(service, "GetTransactionSeed"))
+                services[i++] = LGSTGetTransactionSeed;
+            else if (service && strieq(service, "GetTransactionID"))
+                services[i++] = LGSTGetTransactionID;
+        }
+        services[i] = LGSTterm;
+    };
+public:
+    IMPLEMENT_IINTERFACE;
+
+    CLogAgentBase() { services[0] = LGSTterm; };
+    virtual ~CLogAgentBase() {};
+};
+
+
+class LOGGINGCOMMON_API CDBLogAgentBase : public CLogAgentBase
 {
 {
 protected:
 protected:
     StringBuffer defaultDB, transactionTable, loggingTransactionSeed;
     StringBuffer defaultDB, transactionTable, loggingTransactionSeed;

+ 0 - 20
esp/logging/logginglib/logthread.cpp

@@ -58,26 +58,6 @@ CLogThread::CLogThread(IPropertyTree* _cfg , const char* _service, const char* _
     if(!_logAgent)
     if(!_logAgent)
         throw MakeStringException(-1,"No Logging agent interface for %s", _agentName);
         throw MakeStringException(-1,"No Logging agent interface for %s", _agentName);
 
 
-    const char* servicesConfig = _cfg->queryProp("@services");
-    if (!servicesConfig || !*servicesConfig)
-        throw MakeStringException(-1,"No Logging Service defined for %s", _agentName);
-
-    StringArray serviceArray;
-    serviceArray.appendListUniq(servicesConfig, ",");
-
-    unsigned i=0;
-    ForEachItemIn(s, serviceArray)
-    {
-        const char* service = serviceArray.item(s);
-        if (service && strieq(service, "UpdateLOG"))
-            services[i++] = LGSTUpdateLOG;
-        else if (service && strieq(service, "GetTransactionSeed"))
-            services[i++] = LGSTGetTransactionSeed;
-        else if (service && strieq(service, "GetTransactionID"))
-            services[i++] = LGSTGetTransactionID;
-    }
-    services[i] = LGSTterm;
-
     logAgent.setown(_logAgent);
     logAgent.setown(_logAgent);
 
 
     maxLogQueueLength = _cfg->getPropInt(PropMaxLogQueueLength, MaxLogQueueLength);
     maxLogQueueLength = _cfg->getPropInt(PropMaxLogQueueLength, MaxLogQueueLength);

+ 1 - 15
esp/logging/logginglib/logthread.hpp

@@ -46,7 +46,6 @@ class CLogThread : public Thread , implements IUpdateLogThread
     unsigned maxLogRetries;   // Max. # of attempts to send log message
     unsigned maxLogRetries;   // Max. # of attempts to send log message
 
 
     Owned<IEspLogAgent> logAgent;
     Owned<IEspLogAgent> logAgent;
-    LOGServiceType services[MAXLOGSERVICES];
     QueueOf<IInterface, false> logQueue;
     QueueOf<IInterface, false> logQueue;
     CriticalSection logQueueCrit;
     CriticalSection logQueueCrit;
     Semaphore       m_sem;
     Semaphore       m_sem;
@@ -72,21 +71,8 @@ public:
 
 
     bool hasService(LOGServiceType service)
     bool hasService(LOGServiceType service)
     {
     {
-        unsigned int i = 0;
-        while (services[i] != LGSTterm)
-        {
-            if (services[i] == service)
-                return true;
-            i++;
-        }
-        return false;
+        return logAgent->hasService(service);
     }
     }
-    void addService(LOGServiceType service)
-    {
-        unsigned i=0;
-        while (services[i] != LGSTterm) i++;
-        services[i] = service;
-    };
 
 
     int run();
     int run();
     void start();
     void start();

+ 14 - 2
initfiles/componentfiles/configxml/@temp/logging_agent.xsl

@@ -118,7 +118,13 @@ xmlns:set="http://exslt.org/sets">
         <xsl:if test="string($agentNode/@serverIP) = ''">
         <xsl:if test="string($agentNode/@serverIP) = ''">
             <xsl:message terminate="yes">Cassandra server network address is undefined for <xsl:value-of select="$agentName"/>!</xsl:message>
             <xsl:message terminate="yes">Cassandra server network address is undefined for <xsl:value-of select="$agentName"/>!</xsl:message>
         </xsl:if>
         </xsl:if>
-        <LogAgent name="{$agentName}" type="LogAgent" services="GetTransactionSeed,UpdateLog,GetTransactionID" plugin="cassandralogagent">
+        <xsl:variable name="Services">
+            <xsl:choose>
+                <xsl:when test="string($agentNode/@Services) != ''"><xsl:value-of select="$agentNode/@Services"/></xsl:when>
+                <xsl:otherwise>GetTransactionSeed,UpdateLog,GetTransactionID</xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <LogAgent name="{$agentName}" type="LogAgent" services="{$Services}" plugin="cassandralogagent">
             <Cassandra server="{$agentNode/@serverIP}" dbUser="{$agentNode/@userName}" dbPassWord="{$agentNode/@userPassword}" dbName="{$agentNode/@ksName}"/>
             <Cassandra server="{$agentNode/@serverIP}" dbUser="{$agentNode/@userName}" dbPassWord="{$agentNode/@userPassword}" dbName="{$agentNode/@ksName}"/>
 
 
             <xsl:call-template name="LogBasic">
             <xsl:call-template name="LogBasic">
@@ -165,7 +171,13 @@ xmlns:set="http://exslt.org/sets">
         </xsl:if>
         </xsl:if>
 
 
         <xsl:variable name="wsloggingUrl"><xsl:text>http://</xsl:text><xsl:value-of select="$espNetAddress"/><xsl:text>:</xsl:text><xsl:value-of select="$espPort"/></xsl:variable>
         <xsl:variable name="wsloggingUrl"><xsl:text>http://</xsl:text><xsl:value-of select="$espNetAddress"/><xsl:text>:</xsl:text><xsl:value-of select="$espPort"/></xsl:variable>
-        <LogAgent name="{$agentName}" type="LogAgent" services="GetTransactionSeed,UpdateLog,GetTransactionID" plugin="espserverloggingagent">
+        <xsl:variable name="Services">
+            <xsl:choose>
+                <xsl:when test="string($agentNode/@Services) != ''"><xsl:value-of select="$agentNode/@Services"/></xsl:when>
+                <xsl:otherwise>GetTransactionSeed,UpdateLog,GetTransactionID</xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <LogAgent name="{$agentName}" type="LogAgent" services="{$Services}" plugin="espserverloggingagent">
             <ESPServer url="{$wsloggingUrl}" user="{$agentNode/@User}" password="{$agentNode/@Password}"/>
             <ESPServer url="{$wsloggingUrl}" user="{$agentNode/@User}" password="{$agentNode/@Password}"/>
             <xsl:if test="string($agentNode/@MaxServerWaitingSeconds) != ''">
             <xsl:if test="string($agentNode/@MaxServerWaitingSeconds) != ''">
                 <MaxServerWaitingSeconds><xsl:value-of select="$agentNode/@MaxServerWaitingSeconds"/></MaxServerWaitingSeconds>
                 <MaxServerWaitingSeconds><xsl:value-of select="$agentNode/@MaxServerWaitingSeconds"/></MaxServerWaitingSeconds>

+ 7 - 1
initfiles/componentfiles/configxml/@temp/wslogserviceespagent.xsl

@@ -40,7 +40,13 @@ xmlns:set="http://exslt.org/sets">
             <xsl:message terminate="yes">Log Data XPath is undefined for <xsl:value-of select="$agentName"/> </xsl:message>
             <xsl:message terminate="yes">Log Data XPath is undefined for <xsl:value-of select="$agentName"/> </xsl:message>
         </xsl:if>
         </xsl:if>
 
 
-        <LogAgent name="{$agentName}" type="LogAgent" services="GetTransactionSeed,UpdateLog,GetTransactionID" plugin="wslogserviceespagent">
+        <xsl:variable name="Services">
+            <xsl:choose>
+                <xsl:when test="string($agentNode/@Services) != ''"><xsl:value-of select="$agentNode/@Services"/></xsl:when>
+                <xsl:otherwise>GetTransactionSeed,UpdateLog,GetTransactionID</xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <LogAgent name="{$agentName}" type="LogAgent" services="{$Services}" plugin="wslogserviceespagent">
             <LoggingServer url="{$loggingServerUrl}" user="{$loggingServer/@User}" password="{$loggingServer/@Password}"/>
             <LoggingServer url="{$loggingServerUrl}" user="{$loggingServer/@User}" password="{$loggingServer/@Password}"/>
             <xsl:if test="string($agentNode/@FailSafe) != ''">
             <xsl:if test="string($agentNode/@FailSafe) != ''">
                 <FailSafe><xsl:value-of select="$agentNode/@FailSafe"/></FailSafe>
                 <FailSafe><xsl:value-of select="$agentNode/@FailSafe"/></FailSafe>

+ 8 - 0
initfiles/componentfiles/configxml/cassandraloggingagent.xsd

@@ -63,6 +63,13 @@
           </xs:appinfo>
           </xs:appinfo>
         </xs:annotation>
         </xs:annotation>
       </xs:attribute>
       </xs:attribute>
+      <xs:attribute name="Services" type="xs:string" use="optional" default="GetTransactionSeed,UpdateLog">
+        <xs:annotation>
+          <xs:appinfo>
+            <tooltip>the names of logging services to be supported in this logging agent.</tooltip>
+          </xs:appinfo>
+        </xs:annotation>
+      </xs:attribute>
       <xs:attribute name="MaxTriesGTS" type="xs:nonNegativeInteger" use="optional" default="3">
       <xs:attribute name="MaxTriesGTS" type="xs:nonNegativeInteger" use="optional" default="3">
         <xs:annotation>
         <xs:annotation>
           <xs:appinfo>
           <xs:appinfo>
@@ -238,6 +245,7 @@
         </xs:appinfo>
         </xs:appinfo>
       </xs:annotation>
       </xs:annotation>
     </xs:attribute>
     </xs:attribute>
+    
     <xs:attribute name="ksName" type="xs:string" use="optional" >
     <xs:attribute name="ksName" type="xs:string" use="optional" >
       <xs:annotation>
       <xs:annotation>
          <xs:appinfo>
          <xs:appinfo>

+ 7 - 0
initfiles/componentfiles/configxml/esploggingagent.xsd

@@ -44,6 +44,13 @@
           </xs:appinfo>
           </xs:appinfo>
         </xs:annotation>
         </xs:annotation>
       </xs:attribute>
       </xs:attribute>
+      <xs:attribute name="Services" type="xs:string" use="optional" default="GetTransactionSeed,UpdateLog,GetTransactionID">
+        <xs:annotation>
+          <xs:appinfo>
+            <tooltip>the names of logging services to be supported in this logging agent.</tooltip>
+          </xs:appinfo>
+        </xs:annotation>
+      </xs:attribute>
       <xs:attribute name="description" type="xs:string" use="optional" default="ESP Logging Agent">
       <xs:attribute name="description" type="xs:string" use="optional" default="ESP Logging Agent">
         <xs:annotation>
         <xs:annotation>
           <xs:appinfo>
           <xs:appinfo>