Преглед на файлове

HPCC-17699 EclAgent to ensure scope format is w?:graph?:sg?:a?:c?:sg?:a?

Signed-off-by: Shamser Ahmed <shamser.ahmed@lexisnexis.co.uk>
Shamser Ahmed преди 8 години
родител
ревизия
72e0fbd03c

+ 47 - 17
common/workunit/workunit.cpp

@@ -169,13 +169,22 @@ void doDescheduleWorkkunit(char const * wuid)
  * Graph progress support
  */
 
-CWuGraphStats::CWuGraphStats(IPropertyTree *_progress, StatisticCreatorType _creatorType, const char * _creator, const char * _rootScope, unsigned _id)
+CWuGraphStats::CWuGraphStats(IPropertyTree *_progress, StatisticCreatorType _creatorType, const char * _creator, unsigned wfid, const char * _rootScope, unsigned _id)
     : progress(_progress), creatorType(_creatorType), creator(_creator), id(_id)
 {
-    StatisticScopeType scopeType = SSTgraph;
-    StatsScopeId rootScopeId;
-    verifyex(rootScopeId.setScopeText(_rootScope));
-    collector.setown(createStatisticsGatherer(_creatorType, _creator, rootScopeId));
+    StatsScopeId graphScopeId;
+    verifyex(graphScopeId.setScopeText(_rootScope));
+
+    if (wfid)
+    {
+        StatsScopeId rootScopeId(SSTworkflow,wfid);
+        collector.setown(createStatisticsGatherer(_creatorType, _creator, rootScopeId));
+        collector->beginScope(graphScopeId);
+    }
+    else
+    {
+        collector.setown(createStatisticsGatherer(_creatorType, _creator, graphScopeId));
+    }
 }
 
 void CWuGraphStats::beforeDispose()
@@ -284,6 +293,11 @@ protected:
                 tag = "node";
                 id += strlen(SubGraphScopePrefix);
                 break;
+            case SSTchildgraph:
+            case SSTworkflow:
+            case SSTgraph:
+                // SSTworkflow and SSTgraph may be safely ignored.  They are not required to produce the statistics.
+                continue;
             case SSTfunction:
                 //MORE:Should function scopes be included in the graph scope somehow, and if so how?
                 continue;
@@ -2853,8 +2867,8 @@ extern IConstWorkUnitInfo *createConstWorkUnitInfo(IPropertyTree &p)
 class CDaliWuGraphStats : public CWuGraphStats
 {
 public:
-    CDaliWuGraphStats(IRemoteConnection *_conn, StatisticCreatorType _creatorType, const char * _creator, const char * _rootScope, unsigned _id)
-        : CWuGraphStats(LINK(_conn->queryRoot()), _creatorType, _creator, _rootScope, _id), conn(_conn)
+    CDaliWuGraphStats(IRemoteConnection *_conn, StatisticCreatorType _creatorType, const char * _creator, unsigned _wfid, const char * _rootScope, unsigned _id)
+        : CWuGraphStats(LINK(_conn->queryRoot()), _creatorType, _creator, _wfid, _rootScope, _id), conn(_conn)
     {
     }
 protected:
@@ -3146,9 +3160,9 @@ public:
             }
         }
     }
-    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned subgraph) const
+    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned _wfid, unsigned subgraph) const override
     {
-        return new CDaliWuGraphStats(getWritableProgressConnection(graphName), creatorType, creator, graphName, subgraph);
+        return new CDaliWuGraphStats(getWritableProgressConnection(graphName), creatorType, creator, _wfid, graphName, subgraph);
     }
 
 protected:
@@ -3410,8 +3424,8 @@ public:
             { c->setGraphState(graphName, state); }
     virtual void setNodeState(const char *graphName, WUGraphIDType nodeId, WUGraphState state) const
             { c->setNodeState(graphName, nodeId, state); }
-    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned subgraph) const
-            { return c->updateStats(graphName, creatorType, creator, subgraph); }
+    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned _wfid, unsigned subgraph) const override
+            { return c->updateStats(graphName, creatorType, creator, _wfid, subgraph); }
     virtual void clearGraphProgress() const
             { c->clearGraphProgress(); }
     virtual IStringVal & getAbortBy(IStringVal & str) const
@@ -9122,9 +9136,9 @@ void CLocalWorkUnit::setNodeState(const char *graphName, WUGraphIDType nodeId, W
 {
     throwUnexpected();   // Should only be used for persisted workunits
 }
-IWUGraphStats *CLocalWorkUnit::updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned subgraph) const
+IWUGraphStats *CLocalWorkUnit::updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned _wfid, unsigned subgraph) const
 {
-    return new CWuGraphStats(LINK(p), creatorType, creator, graphName, subgraph);
+    return new CWuGraphStats(LINK(p), creatorType, creator, _wfid, graphName, subgraph);
 }
 
 void CLocalWUGraph::setName(const char *str)
@@ -12635,9 +12649,14 @@ extern WORKUNIT_API void descheduleWorkunit(char const * wuid)
         doDescheduleWorkkunit(wuid);
 }
 
-extern WORKUNIT_API void updateWorkunitTimeStat(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * description, unsigned __int64 value)
+extern WORKUNIT_API void updateWorkunitTimeStat(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * description, unsigned __int64 value, unsigned wfid)
 {
-    wu->setStatistic(queryStatisticsComponentType(), queryStatisticsComponentName(), scopeType, scope, kind, description, value, 1, 0, StatsMergeReplace);
+    StringBuffer scopestr;
+    if (wfid && scope && *scope)
+        scopestr.append(WorkflowScopePrefix).append(wfid).append(":").append(scope);
+    else
+        scopestr.set(scope);
+    wu->setStatistic(queryStatisticsComponentType(), queryStatisticsComponentName(), scopeType, scopestr, kind, description, value, 1, 0, StatsMergeReplace);
 }
 
 class WuTimingUpdater : implements ITimeReportInfo
@@ -12672,9 +12691,15 @@ extern WORKUNIT_API void updateWorkunitTimings(IWorkUnit * wu, StatisticScopeTyp
 }
 
 
-extern WORKUNIT_API void addTimeStamp(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind)
+extern WORKUNIT_API void addTimeStamp(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, unsigned wfid)
 {
-    wu->setStatistic(queryStatisticsComponentType(), queryStatisticsComponentName(), scopeType, scope, kind, NULL, getTimeStampNowValue(), 1, 0, StatsMergeAppend);
+    StringBuffer scopestr;
+    if (wfid && scope && *scope)
+        scopestr.append(WorkflowScopePrefix).append(wfid).append(":").append(scope);
+    else
+        scopestr.set(scope);
+
+    wu->setStatistic(queryStatisticsComponentType(), queryStatisticsComponentName(), scopeType, scopestr, kind, NULL, getTimeStampNowValue(), 1, 0, StatsMergeAppend);
 }
 
 
@@ -12715,6 +12740,11 @@ public:
         StatsScopeId scopeId(SSTedge, id, oid);
         beginScope(scopeId);
     }
+    virtual void beginChildGraphScope(unsigned id)
+    {
+        StatsScopeId scopeId(SSTchildgraph, id);
+        beginScope(scopeId);
+    }
     virtual void endScope()
     {
         scope.setLength(prevLenStack.popGet());

+ 3 - 3
common/workunit/workunit.hpp

@@ -1269,7 +1269,7 @@ interface IConstWorkUnit : extends IConstWorkUnitInfo
     virtual WUGraphState queryNodeState(const char *graphName, WUGraphIDType nodeId) const = 0;
     virtual void setGraphState(const char *graphName, WUGraphState state) const = 0;
     virtual void setNodeState(const char *graphName, WUGraphIDType nodeId, WUGraphState state) const = 0;
-    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned subgraph) const = 0;
+    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned _wfid, unsigned subgraph) const = 0;
     virtual void clearGraphProgress() const = 0;
     virtual IStringVal & getAbortBy(IStringVal & str) const = 0;
     virtual unsigned __int64 getAbortTimeStamp() const = 0;
@@ -1668,7 +1668,7 @@ extern WORKUNIT_API void gatherLibraryNames(StringArray &names, StringArray &unr
 extern WORKUNIT_API void associateLocalFile(IWUQuery * query, WUFileType type, const char * name, const char * description, unsigned crc, unsigned minActivity=0, unsigned maxActivity=0);
 
 interface ITimeReporter;
-extern WORKUNIT_API void updateWorkunitTimeStat(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * description, unsigned __int64 value);
+extern WORKUNIT_API void updateWorkunitTimeStat(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * description, unsigned __int64 value, unsigned wfid=0);
 extern WORKUNIT_API void updateWorkunitTimings(IWorkUnit * wu, ITimeReporter *timer);
 extern WORKUNIT_API void updateWorkunitTimings(IWorkUnit * wu, StatisticScopeType scopeType, StatisticKind kind, ITimeReporter *timer);
 extern WORKUNIT_API void aggregateStatistic(StatsAggregation & result, IConstWorkUnit * wu, const WuScopeFilter & filter, StatisticKind search);
@@ -1683,7 +1683,7 @@ extern WORKUNIT_API const char * getWorkunitStateStr(WUState state);
 extern WORKUNIT_API const char * getWorkunitActionStr(WUAction action);
 extern WORKUNIT_API WUAction getWorkunitAction(const char * actionStr);
 
-extern WORKUNIT_API void addTimeStamp(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind);
+extern WORKUNIT_API void addTimeStamp(IWorkUnit * wu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, unsigned wfid=0);
 extern WORKUNIT_API IPropertyTree * getWUGraphProgress(const char * wuid, bool readonly);
 
 class WORKUNIT_API WorkUnitErrorReceiver : implements IErrorReceiver, public CInterface

+ 2 - 2
common/workunit/workunit.ipp

@@ -275,7 +275,7 @@ public:
     virtual void setGraphState(const char *graphName, WUGraphState state) const;
     virtual void setNodeState(const char *graphName, WUGraphIDType nodeId, WUGraphState state) const;
     virtual WUGraphState queryNodeState(const char *graphName, WUGraphIDType nodeId) const;
-    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned subgraph) const;
+    virtual IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned _wfid, unsigned subgraph) const override;
     void clearGraphProgress() const;
 
     virtual const char *queryJobName() const;
@@ -692,7 +692,7 @@ public:
 class WORKUNIT_API CWuGraphStats : public CInterfaceOf<IWUGraphStats>
 {
 public:
-    CWuGraphStats(IPropertyTree *_progress, StatisticCreatorType _creatorType, const char * _creator, const char * _rootScope, unsigned _id);
+    CWuGraphStats(IPropertyTree *_progress, StatisticCreatorType _creatorType, const char * _creator, unsigned wfid, const char * _rootScope, unsigned _id);
     virtual void beforeDispose();
     virtual IStatisticGatherer & queryStatsBuilder();
 protected:

+ 3 - 1
ecl/eclagent/eclagent.ipp

@@ -1069,6 +1069,7 @@ public:
     IProbeManager * probeManager;
     CriticalSection evaluateCrit;
     bool isChildGraph;
+    bool isLoopBody;
 };
 
 typedef EclSubGraph * EclSubGraphPtr;
@@ -1115,7 +1116,8 @@ public:
     void createFromXGMML(ILoadedDllEntry * dll, IPropertyTree * xgmml, bool enableProbe);
     void execute(const byte * parentExtract);
     void executeLibrary(const byte * parentExtract, IHThorGraphResults * results);
-    IWUGraphStats *updateStats(StatisticCreatorType creatorType, const char * creator, unsigned subgraph);
+    IWUGraphStats *updateStats(StatisticCreatorType creatorType, const char * creator, unsigned wfid, unsigned subgraph);
+    void updateWUStatistic(IWorkUnit* lockedwu, StatisticScopeType scopeType, const char* scope, StatisticKind kind, const char* descr, long long unsigned int value);
 
     EclSubGraph * idToGraph(unsigned id);
     EclGraphElement * idToActivity(unsigned id);

+ 32 - 10
ecl/eclagent/eclgraph.cpp

@@ -722,9 +722,7 @@ void EclGraphElement::updateProgress(IStatisticGatherer &progress)
         return;
     }
     if(isSink && activity)
-    {
         activity->updateProgress(progress);
-    }
 }
 
 IHThorException * EclGraphElement::makeWrappedException(IException * e)
@@ -735,7 +733,7 @@ IHThorException * EclGraphElement::makeWrappedException(IException * e)
 //---------------------------------------------------------------------------
 
 EclSubGraph::EclSubGraph(IAgentContext & _agent, EclGraph & _parent, EclSubGraph * _owner, unsigned _seqNo, bool enableProbe, CHThorDebugContext * _debugContext, IProbeManager * _probeManager)
-    : parent(_parent), owner(_owner), seqNo(_seqNo), probeEnabled(enableProbe), debugContext(_debugContext), probeManager(_probeManager)
+    : parent(_parent), owner(_owner), seqNo(_seqNo), probeEnabled(enableProbe), debugContext(_debugContext), probeManager(_probeManager), isLoopBody(false)
 {
     executed = false;
     created = false;
@@ -760,10 +758,10 @@ void EclSubGraph::createFromXGMML(EclGraph * graph, ILoadedDllEntry * dll, IProp
     bool multiInstance = node->getPropBool("@multiInstance");
     if (multiInstance)
         agent = &subgraphAgentContext;
-
     isSink = xgmml->getPropBool("att[@name=\"rootGraph\"]/@value", false);
     parentActivityId = node->getPropInt("att[@name=\"_parentActivity\"]/@value", 0);
     numResults = xgmml->getPropInt("att[@name=\"_numResults\"]/@value", 0);
+    isLoopBody = xgmml->getPropBool("@loopBody",false);
     if (multiInstance || numResults)
     {
         localResults.setown(new GraphResults(numResults));
@@ -853,15 +851,34 @@ void EclSubGraph::updateProgress()
 {
     if (!isChildGraph && agent->queryRemoteWorkunit())
     {
-        Owned<IWUGraphStats> progress = parent.updateStats(queryStatisticsComponentType(), queryStatisticsComponentName(), id);
+        Owned<IWUGraphStats> progress = parent.updateStats(queryStatisticsComponentType(), queryStatisticsComponentName(), agent->getWorkflowId(), id);
         IStatisticGatherer & stats = progress->queryStatsBuilder();
         updateProgress(stats);
+
+        if (startGraphTime || elapsedGraphCycles)
+        {
+            WorkunitUpdate lockedwu(agent->updateWorkUnit());
+            StringBuffer subgraphid;
+            subgraphid.append(parent.queryGraphName()).append(":").append(SubGraphScopePrefix).append(id);
+            if (startGraphTime)
+                parent.updateWUStatistic(lockedwu, SSTsubgraph, subgraphid, StWhenStarted, nullptr, startGraphTime);
+            if (elapsedGraphCycles)
+                parent.updateWUStatistic(lockedwu, SSTsubgraph, subgraphid, StTimeElapsed, nullptr, cycle_to_nanosec(elapsedGraphCycles));
+        }
     }
 }
 
 void EclSubGraph::updateProgress(IStatisticGatherer &progress)
 {
-    StatsSubgraphScope subgraph(progress, id);
+    OwnedPtr<StatsScopeBlock> subGraph;
+    OwnedPtr<StatsScopeBlock> activityScope;
+    if ((isChildGraph || isLoopBody) && parentActivityId != owner->parentActivityId)
+    {
+        activityScope.setown(new StatsActivityScope(progress, parentActivityId));
+        subGraph.setown(new StatsChildGraphScope(progress, id));
+    }
+    else
+        subGraph.setown(new StatsSubgraphScope(progress, id));
     if (startGraphTime)
         progress.addStatistic(StWhenStarted, startGraphTime);
     if (elapsedGraphCycles)
@@ -1172,7 +1189,7 @@ void EclGraph::execute(const byte * parentExtract)
 
     {
         Owned<IWorkUnit> wu(agent->updateWorkUnit());
-        addTimeStamp(wu, SSTgraph, queryGraphName(), StWhenStarted);
+        addTimeStamp(wu, SSTgraph, queryGraphName(), StWhenStarted, agent->getWorkflowId());
     }
 
     try
@@ -1263,7 +1280,7 @@ void EclGraph::updateLibraryProgress()
     ForEachItemIn(idx, graphs)
     {
         EclSubGraph & cur = graphs.item(idx);
-        Owned<IWUGraphStats> progress = wu->updateStats(queryGraphName(), queryStatisticsComponentType(), queryStatisticsComponentName(), cur.id);
+        Owned<IWUGraphStats> progress = wu->updateStats(queryGraphName(), queryStatisticsComponentType(), queryStatisticsComponentName(), agent->getWorkflowId(), cur.id);
         cur.updateProgress(progress->queryStatsBuilder());
     }
 }
@@ -1404,9 +1421,14 @@ void GraphResults::setResult(unsigned id, IHThorGraphResult * result)
 
 //---------------------------------------------------------------------------
 
-IWUGraphStats *EclGraph::updateStats(StatisticCreatorType creatorType, const char * creator, unsigned subgraph)
+IWUGraphStats *EclGraph::updateStats(StatisticCreatorType creatorType, const char * creator, unsigned wfid, unsigned subgraph)
+{
+    return wu->updateStats (queryGraphName(), creatorType, creator, wfid, subgraph);
+}
+
+void EclGraph::updateWUStatistic(IWorkUnit *lockedwu, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * descr, unsigned __int64 value)
 {
-    return wu->updateStats (queryGraphName(), creatorType, creator, subgraph);
+    updateWorkunitTimeStat(lockedwu, scopeType, scope, kind, descr, value, agent->getWorkflowId());
 }
 
 IThorChildGraph * EclGraph::resolveChildQuery(unsigned subgraphId)

+ 4 - 5
plugins/cassandra/cassandrawu.cpp

@@ -2668,8 +2668,8 @@ public:
     class CCassandraWuGraphStats : public CWuGraphStats
     {
     public:
-        CCassandraWuGraphStats(const CCassandraWorkUnit *_parent, StatisticCreatorType _creatorType, const char * _creator, const char * _rootScope, unsigned _id)
-        : CWuGraphStats(createPTree(_rootScope), _creatorType, _creator, _rootScope, _id),
+        CCassandraWuGraphStats(const CCassandraWorkUnit *_parent, StatisticCreatorType _creatorType, const char * _creator, unsigned _wfid, const char * _rootScope, unsigned _id)
+        : CWuGraphStats(createPTree(_rootScope), _creatorType, _creator, _wfid, _rootScope, _id),
           parent(_parent)
         {
         }
@@ -2684,10 +2684,9 @@ public:
         StringAttr wuid;
     };
 
-
-    IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned subgraph) const
+    IWUGraphStats *updateStats(const char *graphName, StatisticCreatorType creatorType, const char * creator, unsigned wfid, unsigned subgraph) const override
     {
-        return new CCassandraWuGraphStats(this, creatorType, creator, graphName, subgraph);
+        return new CCassandraWuGraphStats(this, creatorType, creator, wfid, graphName, subgraph);
     }
 
 

+ 1 - 1
roxie/ccd/ccdcontext.cpp

@@ -1435,7 +1435,7 @@ public:
         if (debugContext)
             debugContext->checkBreakpoint(DebugStateGraphStart, NULL, graphName);
         if (workUnit)
-            graphStats.setown(workUnit->updateStats(graph->queryName(), SCTroxie, queryStatisticsComponentName(), 0));
+            graphStats.setown(workUnit->updateStats(graph->queryName(), SCTroxie, queryStatisticsComponentName(), 0, 0));
     }
 
     virtual void endGraph(unsigned __int64 startTimeStamp, cycle_t startCycles, bool aborting)

+ 15 - 8
system/jlib/jstats.cpp

@@ -1872,45 +1872,51 @@ public:
     {
         scopes.append(*scope);
     }
-    virtual void beginScope(const StatsScopeId & id)
+    virtual void beginScope(const StatsScopeId & id) override
     {
         CStatisticCollection & tos = scopes.tos();
         scopes.append(*tos.ensureSubScope(id, true));
     }
-    virtual void beginActivityScope(unsigned id)
+    virtual void beginActivityScope(unsigned id) override
     {
         StatsScopeId scopeId(SSTactivity, id);
         CStatisticCollection & tos = scopes.tos();
         scopes.append(*tos.ensureSubScope(scopeId, false));
     }
-    virtual void beginSubGraphScope(unsigned id)
+    virtual void beginSubGraphScope(unsigned id) override
     {
         StatsScopeId scopeId(SSTsubgraph, id);
         CStatisticCollection & tos = scopes.tos();
         scopes.append(*tos.ensureSubScope(scopeId, true));
     }
-    virtual void beginEdgeScope(unsigned id, unsigned oid)
+    virtual void beginEdgeScope(unsigned id, unsigned oid) override
     {
         StatsScopeId scopeId(SSTedge, id, oid);
         CStatisticCollection & tos = scopes.tos();
         scopes.append(*tos.ensureSubScope(scopeId, false));
     }
-    virtual void endScope()
+    virtual void beginChildGraphScope(unsigned id) override
+    {
+        StatsScopeId scopeId(SSTchildgraph, id);
+        CStatisticCollection & tos = scopes.tos();
+        scopes.append(*tos.ensureSubScope(scopeId, true));
+    }
+    virtual void endScope() override
     {
         scopes.tos().Release();
         scopes.pop();
     }
-    virtual void addStatistic(StatisticKind kind, unsigned __int64 value)
+    virtual void addStatistic(StatisticKind kind, unsigned __int64 value) override
     {
         CStatisticCollection & tos = scopes.tos();
         tos.addStatistic(kind, value);
     }
-    virtual void updateStatistic(StatisticKind kind, unsigned __int64 value, StatsMergeAction mergeAction)
+    virtual void updateStatistic(StatisticKind kind, unsigned __int64 value, StatsMergeAction mergeAction) override
     {
         CStatisticCollection & tos = scopes.tos();
         tos.updateStatistic(kind, value, mergeAction);
     }
-    virtual IStatisticCollection * getResult()
+    virtual IStatisticCollection * getResult() override
     {
         return LINK(rootScope);
     }
@@ -1961,6 +1967,7 @@ public:
         beginScope(temp.str());
     }
     virtual void beginSubGraphScope(unsigned id) { throwUnexpected(); }
+    virtual void beginChildGraphScope(unsigned id) { throwUnexpected(); }
     virtual void beginActivityScope(unsigned id) { throwUnexpected(); }
     virtual void beginEdgeScope(unsigned id, unsigned oid) { throwUnexpected(); }
     virtual void endScope()

+ 10 - 0
system/jlib/jstats.h

@@ -125,6 +125,7 @@ public:
     virtual void beginSubGraphScope(unsigned id) = 0;
     virtual void beginActivityScope(unsigned id) = 0;
     virtual void beginEdgeScope(unsigned id, unsigned oid) = 0;
+    virtual void beginChildGraphScope(unsigned id) = 0;
     virtual void endScope() = 0;
     virtual void addStatistic(StatisticKind kind, unsigned __int64 value) = 0;
     virtual void updateStatistic(StatisticKind kind, unsigned __int64 value, StatsMergeAction mergeAction) = 0;
@@ -177,6 +178,15 @@ public:
     }
 };
 
+class StatsChildGraphScope : public StatsScopeBlock
+{
+public:
+    inline StatsChildGraphScope(IStatisticGatherer & _gatherer, unsigned id) : StatsScopeBlock(_gatherer)
+    {
+        gatherer.beginChildGraphScope(id);
+    }
+};
+
 class StatsActivityScope : public StatsScopeBlock
 {
 public:

+ 2 - 2
thorlcr/master/thdemonserver.cpp

@@ -130,7 +130,7 @@ private:
                 ForEachItemIn (g, activeGraphs)
                 {
                     CGraphBase &graph = activeGraphs.item(g);
-                    Owned<IWUGraphStats> stats = currentWU.updateStats(graphName, SCTthor, queryStatisticsComponentName(), graph.queryGraphId());
+                    Owned<IWUGraphStats> stats = currentWU.updateStats(graphName, SCTthor, queryStatisticsComponentName(), 0, graph.queryGraphId());
                     reportGraph(stats->queryStatsBuilder(), &graph, finished);
                 }
                 Owned<IWorkUnit> wu = &currentWU.lock();
@@ -157,7 +157,7 @@ private:
             IConstWorkUnit &currentWU = graph->queryJob().queryWorkUnit();
             const char *graphName = ((CJobMaster &)activeGraphs.item(0).queryJob()).queryGraphName();
             {
-                Owned<IWUGraphStats> stats = currentWU.updateStats(graphName, SCTthor, queryStatisticsComponentName(), graph->queryGraphId());
+                Owned<IWUGraphStats> stats = currentWU.updateStats(graphName, SCTthor, queryStatisticsComponentName(), 0, graph->queryGraphId());
                 reportGraph(stats->queryStatsBuilder(), graph, finished);
             }
 

+ 1 - 1
tools/wutool/wutool.cpp

@@ -1227,7 +1227,7 @@ protected:
         ret = wu->getRunningGraph(s, subid);
         ASSERT(!ret);
 
-        Owned<IWUGraphStats> progress = wu->updateStats("graph1", SCThthor, queryStatisticsComponentName(), 1);
+        Owned<IWUGraphStats> progress = wu->updateStats("graph1", SCThthor, queryStatisticsComponentName(), 0, 1);
         IStatisticGatherer & stats = progress->queryStatsBuilder();
         {
             StatsSubgraphScope subgraph(stats, 1);