|
@@ -52,7 +52,6 @@
|
|
|
|
|
|
static int workUnitTraceLevel = 1;
|
|
|
|
|
|
-
|
|
|
static StringBuffer &getXPath(StringBuffer &wuRoot, const char *wuid)
|
|
|
{
|
|
|
// MORE - can fold in the date
|
|
@@ -440,6 +439,25 @@ public:
|
|
|
};
|
|
|
|
|
|
|
|
|
+class CLocalWUStatistic : public CInterface, implements IConstWUStatistic
|
|
|
+{
|
|
|
+ Owned<IPropertyTree> p;
|
|
|
+public:
|
|
|
+ IMPLEMENT_IINTERFACE;
|
|
|
+ CLocalWUStatistic(IPropertyTree *p);
|
|
|
+
|
|
|
+ virtual IStringVal & getFullName(IStringVal & str) const;
|
|
|
+ virtual IStringVal & getCreator(IStringVal & str) const;
|
|
|
+ virtual IStringVal & getDescription(IStringVal & str) const;
|
|
|
+ virtual IStringVal & getName(IStringVal & str) const;
|
|
|
+ virtual IStringVal & getScope(IStringVal & str) const;
|
|
|
+ virtual StatisticMeasure getKind() const;
|
|
|
+ virtual unsigned __int64 getValue() const;
|
|
|
+ virtual unsigned __int64 getCount() const;
|
|
|
+ virtual unsigned __int64 getMax() const;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
template <typename T, typename IT> struct CachedTags
|
|
|
{
|
|
|
CachedTags(): cached(false) {}
|
|
@@ -459,6 +477,11 @@ template <typename T, typename IT> struct CachedTags
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ void append(IPropertyTree * p)
|
|
|
+ {
|
|
|
+ tags.append(*new T(p));
|
|
|
+ }
|
|
|
+
|
|
|
operator IArrayOf<IT>&() { return tags; }
|
|
|
|
|
|
void kill()
|
|
@@ -545,6 +568,7 @@ class CLocalWorkUnit : public CInterface, implements IConstWorkUnit , implements
|
|
|
mutable IArrayOf<IWUResult> variables;
|
|
|
mutable CachedTags<CLocalWUTimeStamp,IConstWUTimeStamp> timestamps;
|
|
|
mutable CachedTags<CLocalWUAppValue,IConstWUAppValue> appvalues;
|
|
|
+ mutable CachedTags<CLocalWUStatistic,IConstWUStatistic> statistics;
|
|
|
mutable Owned<IUserDescriptor> userDesc;
|
|
|
Mutex locked;
|
|
|
Owned<ISecManager> secMgr;
|
|
@@ -629,10 +653,13 @@ public:
|
|
|
virtual IStringVal & getStateDesc(IStringVal & str) const;
|
|
|
virtual IConstWUResult * getTemporaryByName(const char * name) const;
|
|
|
virtual IConstWUResultIterator & getTemporaries() const;
|
|
|
- virtual unsigned getTimerCount(const char * timerName, const char * instance) const;
|
|
|
- virtual unsigned getTimerDuration(const char * timerName, const char * instance) const;
|
|
|
+ virtual unsigned getTimerCount(const char * timerName) const;
|
|
|
+ virtual unsigned getTimerDuration(const char * timerName) const;
|
|
|
+ virtual IStringVal & getTimerDescription(const char * timerName, IStringVal & str) const;
|
|
|
virtual IStringIterator & getTimers() const;
|
|
|
virtual IConstWUTimeStampIterator & getTimeStamps() const;
|
|
|
+ virtual IConstWUStatisticIterator & getStatistics() const;
|
|
|
+ virtual IConstWUStatistic * getStatistic(const char * name) const;
|
|
|
virtual IConstWUWebServicesInfo * getWebServicesInfo() const;
|
|
|
virtual IConstWURoxieQueryInfo * getRoxieQueryInfo() const;
|
|
|
virtual IStringVal & getXmlParams(IStringVal & params) const;
|
|
@@ -707,7 +734,8 @@ public:
|
|
|
void setStateEx(const char * text);
|
|
|
void setAgentSession(__int64 sessionId);
|
|
|
void setSecurityToken(const char *value);
|
|
|
- void setTimerInfo(const char * name, const char * instance, unsigned ms, unsigned count, unsigned __int64 max);
|
|
|
+ void setStatistic(const char * creator, const char * wuScope, const char * stat, const char * description, StatisticMeasure kind, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, bool merge);
|
|
|
+ void setTimerInfo(const char * name, unsigned ms, unsigned count, unsigned __int64 max);
|
|
|
void setTracingValue(const char * propname, const char * value);
|
|
|
void setTracingValueInt(const char * propname, int value);
|
|
|
void setUser(const char * value);
|
|
@@ -768,6 +796,9 @@ public:
|
|
|
bool getAllowAutoQueueSwitch() const;
|
|
|
void setLibraryInformation(const char * name, unsigned interfaceHash, unsigned definitionHash);
|
|
|
|
|
|
+protected:
|
|
|
+ IConstWUStatistic * getStatisticByDescription(const char * name) const;
|
|
|
+
|
|
|
private:
|
|
|
void init();
|
|
|
IWUGraph *createGraph();
|
|
@@ -1031,16 +1062,22 @@ public:
|
|
|
{ return c->getStateDesc(str); }
|
|
|
virtual bool getRunningGraph(IStringVal & graphName, WUGraphIDType & subId) const
|
|
|
{ return c->getRunningGraph(graphName, subId); }
|
|
|
- virtual unsigned getTimerCount(const char * timerName, const char * instance) const
|
|
|
- { return c->getTimerCount(timerName, instance); }
|
|
|
- virtual unsigned getTimerDuration(const char * timerName, const char * instance) const
|
|
|
- { return c->getTimerDuration(timerName, instance); }
|
|
|
+ virtual unsigned getTimerCount(const char * timerName) const
|
|
|
+ { return c->getTimerCount(timerName); }
|
|
|
+ virtual unsigned getTimerDuration(const char * timerName) const
|
|
|
+ { return c->getTimerDuration(timerName); }
|
|
|
+ virtual IStringVal & getTimerDescription(const char * timerName, IStringVal & str) const
|
|
|
+ { return c->getTimerDescription(timerName, str); }
|
|
|
virtual IStringVal & getTimeStamp(const char * name, const char * instance, IStringVal & str) const
|
|
|
{ return c->getTimeStamp(name, instance, str); }
|
|
|
virtual IStringIterator & getTimers() const
|
|
|
{ return c->getTimers(); }
|
|
|
virtual IConstWUTimeStampIterator & getTimeStamps() const
|
|
|
{ return c->getTimeStamps(); }
|
|
|
+ virtual IConstWUStatisticIterator & getStatistics() const
|
|
|
+ { return c->getStatistics(); }
|
|
|
+ virtual IConstWUStatistic * getStatistic(const char * name) const
|
|
|
+ { return c->getStatistic(name); }
|
|
|
|
|
|
virtual bool getWuDate(unsigned & year, unsigned & month, unsigned& day)
|
|
|
{ return c->getWuDate(year,month,day);}
|
|
@@ -1168,8 +1205,11 @@ public:
|
|
|
{ c->setStateEx(text); }
|
|
|
virtual void setAgentSession(__int64 sessionId)
|
|
|
{ c->setAgentSession(sessionId); }
|
|
|
- virtual void setTimerInfo(const char * name, const char * instance, unsigned ms, unsigned count, unsigned __int64 max)
|
|
|
- { c->setTimerInfo(name, instance, ms, count, max); }
|
|
|
+ virtual void setTimerInfo(const char * name, unsigned ms, unsigned count, unsigned __int64 max)
|
|
|
+ { c->setTimerInfo(name, ms, count, max); }
|
|
|
+ virtual void setStatistic(const char * creator, const char * wuScope, const char * stat, const char * description, StatisticMeasure kind, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, bool merge)
|
|
|
+ { c->setStatistic(creator, wuScope, stat, description, kind, value, count, maxValue, merge); }
|
|
|
+
|
|
|
virtual void setTracingValue(const char * propname, const char * value)
|
|
|
{ c->setTracingValue(propname, value); }
|
|
|
virtual void setTracingValueInt(const char * propname, int value)
|
|
@@ -2965,6 +3005,7 @@ CLocalWorkUnit::~CLocalWorkUnit()
|
|
|
variables.kill();
|
|
|
timestamps.kill();
|
|
|
appvalues.kill();
|
|
|
+ statistics.kill();
|
|
|
|
|
|
userDesc.clear();
|
|
|
secMgr.clear();
|
|
@@ -4175,7 +4216,6 @@ IConstWUAppValueIterator& CLocalWorkUnit::getApplicationValues() const
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
void CLocalWorkUnit::setApplicationValue(const char *app, const char *propname, const char *value, bool overwrite)
|
|
|
{
|
|
|
CriticalBlock block(crit);
|
|
@@ -5056,6 +5096,13 @@ void CLocalWorkUnit::copyWorkUnit(IConstWorkUnit *cached, bool all)
|
|
|
mergePTree(tgtTimings, pt);
|
|
|
pt->Release();
|
|
|
}
|
|
|
+ pt = fromP->getBranch("Statistics");
|
|
|
+ if (pt)
|
|
|
+ {
|
|
|
+ IPropertyTree *tgtStatistics = ensurePTree(p, "Statistics");
|
|
|
+ mergePTree(tgtStatistics, pt);
|
|
|
+ pt->Release();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
updateProp(p, fromP, "@clusterName");
|
|
@@ -5382,17 +5429,54 @@ IConstWULibrary * CLocalWorkUnit::getLibraryByName(const char * search) const
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-unsigned CLocalWorkUnit::getTimerDuration(const char *name, const char *_unused) const
|
|
|
+unsigned CLocalWorkUnit::getTimerDuration(const char *name) const
|
|
|
{
|
|
|
+ Owned<IConstWUStatistic> stat = getStatisticByDescription(name);
|
|
|
+ if (stat)
|
|
|
+ {
|
|
|
+ unsigned __int64 time = stat->getValue();
|
|
|
+ return (unsigned)(time / 1000000);
|
|
|
+ }
|
|
|
+
|
|
|
+ //Backward compatibility - but only use it if no statistics
|
|
|
CriticalBlock block(crit);
|
|
|
+ if (p->hasProp("Statistics"))
|
|
|
+ return 0;
|
|
|
+
|
|
|
StringBuffer pname;
|
|
|
pname.appendf("Timings/Timing[@name=\"%s\"]/@duration", name);
|
|
|
return p->getPropInt(pname.str(), 0);
|
|
|
}
|
|
|
|
|
|
-unsigned CLocalWorkUnit::getTimerCount(const char *name, const char *_unused) const
|
|
|
+IStringVal & CLocalWorkUnit::getTimerDescription(const char * name, IStringVal & str) const
|
|
|
+{
|
|
|
+ Owned<IConstWUStatistic> stat = getStatisticByDescription(name);
|
|
|
+ if (stat)
|
|
|
+ return stat->getDescription(str);
|
|
|
+
|
|
|
+ //Backward compatibility - but only use it if no statistics
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ if (p->hasProp("Statistics"))
|
|
|
+ {
|
|
|
+ str.clear();
|
|
|
+ return str;
|
|
|
+ }
|
|
|
+
|
|
|
+ str.set(name);
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned CLocalWorkUnit::getTimerCount(const char *name) const
|
|
|
{
|
|
|
+ Owned<IConstWUStatistic> stat = getStatisticByDescription(name);
|
|
|
+ if (stat)
|
|
|
+ return (unsigned)stat->getCount();
|
|
|
+
|
|
|
+ //Backward compatibility - but only use it if no statistics
|
|
|
CriticalBlock block(crit);
|
|
|
+ if (p->hasProp("Statistics"))
|
|
|
+ return 0;
|
|
|
+
|
|
|
StringBuffer pname;
|
|
|
pname.appendf("Timings/Timing[@name=\"%s\"]/@count", name);
|
|
|
return p->getPropInt(pname.str(), 0);
|
|
@@ -5401,6 +5485,11 @@ unsigned CLocalWorkUnit::getTimerCount(const char *name, const char *_unused) co
|
|
|
IStringIterator& CLocalWorkUnit::getTimers() const
|
|
|
{
|
|
|
CriticalBlock block(crit);
|
|
|
+
|
|
|
+ if (p->hasProp("Statistics"))
|
|
|
+ return *new CStringPTreeAttrIterator(p->getElements("Statistics/Statistic[@unit=\"ns\"]"), "@desc");
|
|
|
+
|
|
|
+ //Backward compatibility - but only use it if no statistics
|
|
|
return *new CStringPTreeAttrIterator(p->getElements("Timings/Timing"), "@name");
|
|
|
}
|
|
|
|
|
@@ -5412,21 +5501,30 @@ StringBuffer &formatGraphTimerLabel(StringBuffer &str, const char *graphName, un
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
-bool parseGraphTimerLabel(const char *label, StringBuffer &graphName, unsigned &subGraphNum, unsigned __int64 &subId)
|
|
|
+StringBuffer &formatGraphTimerScope(StringBuffer &str, const char *graphName, unsigned subGraphNum, unsigned __int64 subId)
|
|
|
+{
|
|
|
+ str.append(graphName);
|
|
|
+ if (subId) str.append(":").append(subId);
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+bool parseGraphTimerLabel(const char *label, StringAttr &graphName, unsigned & graphNum, unsigned &subGraphNum, unsigned &subId)
|
|
|
{
|
|
|
// expects format: "Graph <graphname>[ - <subgraphnum> (<subgraphid>)]"
|
|
|
unsigned len = (size32_t)strlen(label);
|
|
|
if (len < 6 || (0 != memcmp(label, "Graph ", 6)))
|
|
|
return false;
|
|
|
+ graphNum = 0;
|
|
|
subGraphNum = 0;
|
|
|
subId = 0;
|
|
|
const char *finger = label+6;
|
|
|
const char *finger2 = strchr(finger, '-');
|
|
|
+
|
|
|
if (NULL == finger2) // just graphName
|
|
|
- graphName.append(finger);
|
|
|
+ graphName.set(finger);
|
|
|
else
|
|
|
{
|
|
|
- graphName.append((size32_t)((finger2-1)-finger), finger);
|
|
|
+ graphName.set(finger, (size32_t)((finger2-1)-finger));
|
|
|
finger = finger2+2; // skip '-' and space
|
|
|
finger2 = strchr(finger, ' ');
|
|
|
if (finger2)
|
|
@@ -5435,40 +5533,40 @@ bool parseGraphTimerLabel(const char *label, StringBuffer &graphName, unsigned &
|
|
|
finger = finger2+2; // skip space and '('
|
|
|
finger2 = strchr(finger, ')');
|
|
|
if (finger2)
|
|
|
- subId = atoi64_l(finger, (size32_t)(finger2-finger));
|
|
|
+ subId = atoi_l(finger, (size32_t)(finger2-finger));
|
|
|
}
|
|
|
else if (((len-(finger-label))>3) && 0 == memcmp(finger, "id(", 3)) // subgraph id only, new format.
|
|
|
{
|
|
|
finger += 3;
|
|
|
finger2 = strchr(finger, ')');
|
|
|
if (finger2)
|
|
|
- subId = atoi64_l(finger, (size32_t)(finger2-finger));
|
|
|
+ subId = atoi_l(finger, (size32_t)(finger2-finger));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (graphName && memicmp(graphName, "graph", 5))
|
|
|
+ graphNum = atoi(graphName + 5);
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-void CLocalWorkUnit::setTimerInfo(const char *name, const char *subname, unsigned ms, unsigned count, unsigned __int64 max)
|
|
|
+void CLocalWorkUnit::setTimerInfo(const char *name, unsigned ms, unsigned count, unsigned __int64 max)
|
|
|
{
|
|
|
CriticalBlock block(crit);
|
|
|
IPropertyTree *timings = p->queryPropTree("Timings");
|
|
|
if (!timings)
|
|
|
timings = p->addPropTree("Timings", createPTree("Timings"));
|
|
|
- StringBuffer fullname;
|
|
|
- if (subname)
|
|
|
- fullname.append('.').append(subname);
|
|
|
- fullname.append(name);
|
|
|
StringBuffer xpath;
|
|
|
- xpath.append("Timing[@name=\"").append(fullname).append("\"]");
|
|
|
+ xpath.append("Timing[@name=\"").append(name).append("\"]");
|
|
|
IPropertyTree *timing = timings->queryPropTree(xpath.str());
|
|
|
if (!timing)
|
|
|
{
|
|
|
timing = timings->addPropTree("Timing", createPTree("Timing"));
|
|
|
- timing->setProp("@name", fullname.str());
|
|
|
+ timing->setProp("@name", name);
|
|
|
}
|
|
|
timing->setPropInt("@count", count);
|
|
|
timing->setPropInt("@duration", ms);
|
|
|
- if (!max && 1==count) max = (unsigned __int64)ms * 1000000; // max is in nanoseconds
|
|
|
+ if (!max && 1==count) max = milliToNano(ms); // max is in nanoseconds
|
|
|
if (max)
|
|
|
timing->setPropInt64("@max", max);
|
|
|
}
|
|
@@ -5515,6 +5613,91 @@ void CLocalWorkUnit::setTimeStamp(const char *application, const char *instance,
|
|
|
ts->addPropTree("TimeStamp", t);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+mapEnums queryStatMeasure[] =
|
|
|
+{
|
|
|
+ { SMEASURE_TIME_NS, "ns" },
|
|
|
+ { SMEASURE_COUNT, "cnt" },
|
|
|
+ { SMEASURE_MEM_KB, "kb" },
|
|
|
+ { SMEASURE_MAX, NULL},
|
|
|
+};
|
|
|
+
|
|
|
+void CLocalWorkUnit::setStatistic(const char * creator, const char * wuScope, const char * stat, const char * description, StatisticMeasure kind, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, bool merge)
|
|
|
+{
|
|
|
+ if (!wuScope) wuScope = "workunit";
|
|
|
+
|
|
|
+ //creator. scope and name must all be present, and must not contain semi colons.
|
|
|
+ assertex(creator && wuScope && stat);
|
|
|
+ dbgassertex(!strchr(creator, ';') && !strchr(wuScope, ';') && !strchr(stat, ';'));
|
|
|
+ if (count == 1 && maxValue < value)
|
|
|
+ maxValue = value;
|
|
|
+
|
|
|
+ StringBuffer fullname;
|
|
|
+ fullname.append(creator).append(";").append(wuScope).append(";").append(stat);
|
|
|
+
|
|
|
+ StringBuffer xpath;
|
|
|
+ xpath.append("Statistic[@name=\"").append(fullname).append("\"]");
|
|
|
+
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ IPropertyTree * stats = p->queryPropTree("Statistics");
|
|
|
+ if (!stats)
|
|
|
+ stats = p->addPropTree("Statistics", createPTree("Statistics"));
|
|
|
+ IPropertyTree * statTree = stats->queryPropTree(xpath.str());
|
|
|
+ if (!statTree)
|
|
|
+ {
|
|
|
+ //MORE: When getTimings is removed the default description could be dynamically calculated
|
|
|
+ StringBuffer descriptionText;
|
|
|
+ if (!description || !*description)
|
|
|
+ {
|
|
|
+ bool isDefaultName = streq(stat, "time");
|
|
|
+ bool isDefaultScope = streq(wuScope, "workunit");
|
|
|
+
|
|
|
+ descriptionText.append(creator);
|
|
|
+ if (isDefaultName || !isDefaultScope)
|
|
|
+ descriptionText.append(": ").append(wuScope);
|
|
|
+ if (!isDefaultName)
|
|
|
+ descriptionText.append(": ").append(stat);
|
|
|
+ description = descriptionText;
|
|
|
+ }
|
|
|
+
|
|
|
+ statTree = stats->addPropTree("Statistic", createPTree("Statistic"));
|
|
|
+ statTree->setProp("@name", fullname.str());
|
|
|
+
|
|
|
+ if (description)
|
|
|
+ statTree->setProp("@desc", description);
|
|
|
+ setEnum(statTree, "@unit", kind, queryStatMeasure);
|
|
|
+
|
|
|
+ statTree->setPropInt64("@value", value);
|
|
|
+ statTree->setPropInt64("@count", count);
|
|
|
+ if (maxValue)
|
|
|
+ statTree->setPropInt64("@max", maxValue);
|
|
|
+
|
|
|
+ if (statistics.cached)
|
|
|
+ statistics.append(LINK(statTree));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (merge)
|
|
|
+ {
|
|
|
+ unsigned __int64 oldValue = statTree->getPropInt64("@value", 0);
|
|
|
+ unsigned __int64 oldCount = statTree->getPropInt64("@count", 0);
|
|
|
+ unsigned __int64 oldMax = statTree->getPropInt64("@max", 0);
|
|
|
+
|
|
|
+ statTree->setPropInt64("@value", value + oldValue);
|
|
|
+ statTree->setPropInt64("@count", count + oldCount);
|
|
|
+ if (maxValue > oldMax)
|
|
|
+ statTree->setPropInt64("@max", maxValue);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ statTree->setPropInt64("@value", value);
|
|
|
+ statTree->setPropInt64("@count", count);
|
|
|
+ if (maxValue)
|
|
|
+ statTree->setPropInt64("@max", maxValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void CLocalWorkUnit::setTimeStamp(const char *application, const char *instance, const char *event)
|
|
|
{
|
|
|
setTimeStamp(application,instance,event,false);
|
|
@@ -5550,6 +5733,35 @@ IConstWUTimeStampIterator& CLocalWorkUnit::getTimeStamps() const
|
|
|
return *new CArrayIteratorOf<IConstWUTimeStamp,IConstWUTimeStampIterator> (timestamps, 0, (IConstWorkUnit *) this);
|
|
|
}
|
|
|
|
|
|
+IConstWUStatisticIterator& CLocalWorkUnit::getStatistics() const
|
|
|
+{
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ statistics.load(p,"Statistics/*");
|
|
|
+ return *new CArrayIteratorOf<IConstWUStatistic,IConstWUStatisticIterator> (statistics, 0, (IConstWorkUnit *) this);
|
|
|
+}
|
|
|
+
|
|
|
+IConstWUStatistic * CLocalWorkUnit::getStatisticByDescription(const char * desc) const
|
|
|
+{
|
|
|
+ StringBuffer xpath;
|
|
|
+ xpath.appendf("Statistics/Statistic[@desc=\"%s\"]", desc);
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ IPropertyTree * match = p->queryPropTree(xpath);
|
|
|
+ if (!match)
|
|
|
+ return NULL;
|
|
|
+ return new CLocalWUStatistic(LINK(match));
|
|
|
+}
|
|
|
+
|
|
|
+IConstWUStatistic * CLocalWorkUnit::getStatistic(const char * name) const
|
|
|
+{
|
|
|
+ StringBuffer xpath;
|
|
|
+ xpath.appendf("Statistics/Statistic[@name=\"%s\"]", name);
|
|
|
+ CriticalBlock block(crit);
|
|
|
+ IPropertyTree * match = p->queryPropTree(xpath);
|
|
|
+ if (!match)
|
|
|
+ return NULL;
|
|
|
+ return new CLocalWUStatistic(LINK(match));
|
|
|
+}
|
|
|
+
|
|
|
bool CLocalWorkUnit::getWuDate(unsigned & year, unsigned & month, unsigned& day)
|
|
|
{
|
|
|
CriticalBlock block(crit);
|
|
@@ -6466,12 +6678,23 @@ unsigned CLocalWorkUnit::getVariableCount() const
|
|
|
unsigned CLocalWorkUnit::getTimerCount() const
|
|
|
{
|
|
|
CriticalBlock block(crit);
|
|
|
- if (p->hasProp("Timings"))
|
|
|
+
|
|
|
+ if (p->hasProp("Statistics"))
|
|
|
{
|
|
|
- return p->queryPropTree("Timings")->numChildren();
|
|
|
+ Owned<IPropertyTreeIterator> iter = p->getElements("Statistics/Statistic[@unit=\"ns\"]");
|
|
|
+ unsigned cnt =0;
|
|
|
+ if (iter)
|
|
|
+ {
|
|
|
+ ForEach(*iter)
|
|
|
+ cnt++;
|
|
|
+ }
|
|
|
+ return cnt;
|
|
|
}
|
|
|
+
|
|
|
+ if (p->hasProp("Timings"))
|
|
|
+ return p->queryPropTree("Timings")->numChildren();
|
|
|
+
|
|
|
return 0;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
unsigned CLocalWorkUnit::getApplicationValueCount() const
|
|
@@ -8276,6 +8499,8 @@ void CLocalWUException::setExceptionColumn(unsigned c)
|
|
|
p->setPropInt("@col", c);
|
|
|
}
|
|
|
|
|
|
+//==========================================================================================
|
|
|
+
|
|
|
CLocalWUTimeStamp::CLocalWUTimeStamp(IPropertyTree *props) : p(props)
|
|
|
{
|
|
|
}
|
|
@@ -8300,6 +8525,8 @@ IStringVal & CLocalWUTimeStamp::getDate(IStringVal & str) const
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
+//==========================================================================================
|
|
|
+
|
|
|
CLocalWUAppValue::CLocalWUAppValue(IPropertyTree *props,unsigned child): p(props)
|
|
|
{
|
|
|
prop.append("*[").append(child).append("]");
|
|
@@ -8325,6 +8552,79 @@ IStringVal & CLocalWUAppValue::getValue(IStringVal & str) const
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
+//==========================================================================================
|
|
|
+
|
|
|
+CLocalWUStatistic::CLocalWUStatistic(IPropertyTree *props) : p(props)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+IStringVal & CLocalWUStatistic::getFullName(IStringVal & str) const
|
|
|
+{
|
|
|
+ str.set(p->queryProp("@name"));
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+IStringVal & CLocalWUStatistic::getCreator(IStringVal & str) const
|
|
|
+{
|
|
|
+ const char * name = p->queryProp("@name");
|
|
|
+ const char * sep1 = strchr(name, ';');
|
|
|
+ assertex(sep1);
|
|
|
+ str.setLen(name, sep1-name);
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+IStringVal & CLocalWUStatistic::getDescription(IStringVal & str) const
|
|
|
+{
|
|
|
+ str.set(p->queryProp("@desc"));
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+IStringVal & CLocalWUStatistic::getName(IStringVal & str) const
|
|
|
+{
|
|
|
+ const char * name = p->queryProp("@name");
|
|
|
+ const char * sep1 = strchr(name, ';');
|
|
|
+ assertex(sep1);
|
|
|
+ const char * scope = sep1+1;
|
|
|
+ const char * sep2 = strchr(scope, ';');
|
|
|
+ assertex(sep2);
|
|
|
+ str.set(sep2+1);
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+IStringVal & CLocalWUStatistic::getScope(IStringVal & str) const
|
|
|
+{
|
|
|
+ const char * name = p->queryProp("@name");
|
|
|
+ const char * sep1 = strchr(name, ';');
|
|
|
+ assertex(sep1);
|
|
|
+ const char * scope = sep1+1;
|
|
|
+ const char * sep2 = strchr(scope, ';');
|
|
|
+ assertex(sep2);
|
|
|
+ str.setLen(scope, sep2-scope);
|
|
|
+ return str;
|
|
|
+}
|
|
|
+
|
|
|
+StatisticMeasure CLocalWUStatistic::getKind() const
|
|
|
+{
|
|
|
+ return (StatisticMeasure)getEnum(p, "@unit", queryStatMeasure);
|
|
|
+}
|
|
|
+
|
|
|
+unsigned __int64 CLocalWUStatistic::getValue() const
|
|
|
+{
|
|
|
+ return p->getPropInt64("@value", 0);
|
|
|
+}
|
|
|
+
|
|
|
+unsigned __int64 CLocalWUStatistic::getCount() const
|
|
|
+{
|
|
|
+ return p->getPropInt64("@count", 0);
|
|
|
+}
|
|
|
+
|
|
|
+unsigned __int64 CLocalWUStatistic::getMax() const
|
|
|
+{
|
|
|
+ return p->getPropInt64("@max", 0);
|
|
|
+}
|
|
|
+
|
|
|
+//==========================================================================================
|
|
|
+
|
|
|
extern WORKUNIT_API ILocalWorkUnit * createLocalWorkUnit()
|
|
|
{
|
|
|
Owned<CLocalWorkUnit> cw = new CLocalWorkUnit("W_LOCAL", NULL, (ISecManager*)NULL, NULL);
|
|
@@ -9938,3 +10238,58 @@ extern WORKUNIT_API void descheduleWorkunit(char const * wuid)
|
|
|
else
|
|
|
doDescheduleWorkkunit(wuid);
|
|
|
}
|
|
|
+
|
|
|
+extern WORKUNIT_API void updateWorkunitTimeStat(IWorkUnit * wu, const char * component, const char * wuScope, const char * stat, const char * description, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue)
|
|
|
+{
|
|
|
+ if (!wuScope)
|
|
|
+ wuScope = "workunit";
|
|
|
+ if (!stat)
|
|
|
+ stat = "time";
|
|
|
+
|
|
|
+ //The following line duplicates the statistics as timing information - preserved temporarily to show refactoring.
|
|
|
+ //wu->setTimerInfo(description, (unsigned)(value/1000000), (unsigned)count, (unsigned)maxValue);
|
|
|
+ wu->setStatistic(component, wuScope, stat, description, SMEASURE_TIME_NS, value, count, maxValue, false);
|
|
|
+}
|
|
|
+
|
|
|
+extern WORKUNIT_API void updateWorkunitTiming(IWorkUnit * wu, const char * component, const char * mangledScope, const char * description, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue)
|
|
|
+{
|
|
|
+ StringAttr scopeText;
|
|
|
+ StringAttr componentText;
|
|
|
+ const char * wuScope = mangledScope;
|
|
|
+ const char * stat = "time";
|
|
|
+
|
|
|
+ //If the scope contains a semicolon then it is taken to mean (wuScope;stat or comonent;wuScope;stat)
|
|
|
+ const char * sep1 = strchr(mangledScope, ';');
|
|
|
+ if (sep1)
|
|
|
+ {
|
|
|
+ const char * sep2 = strchr(sep1+1, ';');
|
|
|
+ if (sep2)
|
|
|
+ {
|
|
|
+ componentText.set(mangledScope, sep1 - mangledScope);
|
|
|
+ scopeText.set(sep1+1, sep2-(sep1+1));
|
|
|
+ component = componentText;
|
|
|
+ wuScope = scopeText;
|
|
|
+ stat = sep2+1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ scopeText.set(mangledScope, sep1-mangledScope);
|
|
|
+ wuScope = scopeText.get();
|
|
|
+ stat = sep1+1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ updateWorkunitTimeStat(wu, component, wuScope, stat, description, value, count, maxValue);
|
|
|
+}
|
|
|
+
|
|
|
+extern WORKUNIT_API void updateWorkunitTimings(IWorkUnit * wu, ITimeReporter *timer, const char * component)
|
|
|
+{
|
|
|
+ StringBuffer description;
|
|
|
+ StringBuffer scope;
|
|
|
+ for (unsigned i = 0; i < timer->numSections(); i++)
|
|
|
+ {
|
|
|
+ timer->getDescription(i, description.clear());
|
|
|
+ timer->getScope(i, scope.clear());
|
|
|
+ updateWorkunitTiming(wu, component, scope, description, timer->getTime(i), timer->getCount(i), timer->getMaxTime(i));
|
|
|
+ }
|
|
|
+}
|