@@ -204,6 +204,25 @@ class EngineImpl: public ActionExecutorListener {
204204 std::condition_variable readyJobsCondition;
205205 bool shutdown{false };
206206
207+ // / Perf counters
208+ std::atomic<uint64_t > st_buildCount{0 };
209+ std::atomic<uint64_t > st_buildCompletedCount{0 };
210+
211+ std::atomic<uint64_t > st_artifactRequestCount{0 };
212+ std::atomic<uint64_t > st_ruleRequestCount{0 };
213+
214+ std::atomic<uint64_t > st_taskCount{0 };
215+ std::atomic<uint64_t > st_taskTransitions{0 };
216+ std::atomic<uint64_t > st_taskCacheHits{0 };
217+ std::atomic<uint64_t > st_taskCacheMisses{0 };
218+ std::atomic<uint64_t > st_taskCompletedCount{0 };
219+
220+ std::atomic<uint64_t > st_actionCount{0 };
221+ std::atomic<uint64_t > st_actionCompletedCount{0 };
222+ std::atomic<uint64_t > st_subtaskCount{0 };
223+ std::atomic<uint64_t > st_subtaskCompletedCount{0 };
224+
225+
207226public:
208227 EngineImpl (EngineConfig config, std::shared_ptr<CASDatabase> casDB,
209228 std::shared_ptr<ActionCache> cache,
@@ -301,6 +320,7 @@ class EngineImpl: public ActionExecutorListener {
301320 // / @{
302321
303322 Build build (const Label& artifact) {
323+ st_buildCount++;
304324 auto context = std::shared_ptr<BuildContext>(new BuildContext ());
305325
306326 uint64_t buildID = 0 ;
@@ -321,6 +341,7 @@ class EngineImpl: public ActionExecutorListener {
321341 }
322342
323343 if (res.has_error ()) {
344+ st_buildCompletedCount++;
324345 logger->event (logctx, {
325346 makeStat (" log.message" , " build_completed" ),
326347 makeStat (" build_id" , buildID),
@@ -333,6 +354,24 @@ class EngineImpl: public ActionExecutorListener {
333354 return Build (context);
334355 }
335356
357+ std::vector<Stat> stats () {
358+ return {
359+ makeStat (" builds" , st_buildCount),
360+ makeStat (" builds_completed" , st_buildCompletedCount),
361+ makeStat (" artifact_requests" , st_artifactRequestCount),
362+ makeStat (" rule_requests" , st_ruleRequestCount),
363+ makeStat (" tasks" , st_taskCount),
364+ makeStat (" task_transitions" , st_taskTransitions),
365+ makeStat (" task_cache_hits" , st_taskCacheHits),
366+ makeStat (" task_cache_misses" , st_taskCacheMisses),
367+ makeStat (" tasks_completed" , st_taskCompletedCount),
368+ makeStat (" actions" , st_actionCount),
369+ makeStat (" actions_completed" , st_actionCompletedCount),
370+ makeStat (" subtasks" , st_subtaskCount),
371+ makeStat (" subtasks_completed" , st_subtaskCompletedCount)
372+ };
373+ }
374+
336375 // / @}
337376
338377 // / @name Task Management Client APIs
@@ -344,6 +383,7 @@ class EngineImpl: public ActionExecutorListener {
344383
345384 result<uint64_t , Error> taskRequestArtifact (uint64_t taskID,
346385 const Label& label) {
386+ st_artifactRequestCount++;
347387 // FIXME: concretize label with context?
348388
349389 uint64_t buildID = 0 ;
@@ -444,6 +484,7 @@ class EngineImpl: public ActionExecutorListener {
444484 }
445485
446486 result<uint64_t , Error> taskRequestRule (uint64_t taskID, const Label& label) {
487+ st_ruleRequestCount++;
447488 // FIXME: concretize label with context?
448489
449490 uint64_t buildID = 0 ;
@@ -539,6 +580,8 @@ class EngineImpl: public ActionExecutorListener {
539580 }
540581
541582 result<uint64_t , Error> taskRequestAction (uint64_t taskID, const Action& action) {
583+ st_actionCount++;
584+
542585 uint64_t buildID = 0 ;
543586 uint64_t workID = 0 ;
544587
@@ -561,6 +604,7 @@ class EngineImpl: public ActionExecutorListener {
561604 if (res.has_error ()) {
562605 std::lock_guard<std::mutex> lock (taskInfosMutex);
563606 actionTaskMap.erase (workID);
607+ st_actionCompletedCount++;
564608 return fail (res.error ());
565609 }
566610
@@ -575,6 +619,8 @@ class EngineImpl: public ActionExecutorListener {
575619 }
576620
577621 result<uint64_t , Error> taskSpawnSubtask (uint64_t taskID, const Subtask& subtask) {
622+ st_subtaskCount++;
623+
578624 uint64_t buildID = 0 ;
579625 uint64_t workID = 0 ;
580626 uint64_t sid = 0 ;
@@ -599,6 +645,7 @@ class EngineImpl: public ActionExecutorListener {
599645 if (res.has_error ()) {
600646 std::lock_guard<std::mutex> lock (taskInfosMutex);
601647 subtaskTaskMap.erase (workID);
648+ st_subtaskCompletedCount++;
602649 return fail (res.error ());
603650 }
604651
@@ -635,6 +682,8 @@ class EngineImpl: public ActionExecutorListener {
635682 return ;
636683 }
637684
685+ st_actionCompletedCount++;
686+
638687 auto taskID = entry->second ;
639688 auto & rtask = taskInfos.at (taskID);
640689 rtask.pendingActions .at (cid.workID ).result = {std::move (result)};
@@ -658,6 +707,8 @@ class EngineImpl: public ActionExecutorListener {
658707 return ;
659708 }
660709
710+ st_subtaskCompletedCount++;
711+
661712 auto taskID = entry->second ;
662713 auto & rtask = taskInfos.at (taskID);
663714 rtask.pendingSubtasks .at (cid.workID ) = std::move (result);
@@ -797,6 +848,7 @@ class EngineImpl: public ActionExecutorListener {
797848 }
798849
799850 // Insert the task
851+ st_taskCount++;
800852 auto taskID = nextTaskID++;
801853 auto insertion = taskInfos.try_emplace (taskID, taskID, std::move (task));
802854 auto & taskInfo = (insertion.first )->second ;
@@ -860,12 +912,14 @@ class EngineImpl: public ActionExecutorListener {
860912 actionCache->get (cacheKey, [this , ctx, inputs, sres, &taskInfo](result<CacheValue, Error> res) {
861913 if (res.has_error ()) {
862914 logger->error (logctx, res.error ());
915+ st_taskCacheMisses++;
863916 enqueueReadyTask (taskInfo, ctx, inputs, sres);
864917 return ;
865918 }
866919
867920 if (!res->has_data ()) {
868921 // not found
922+ st_taskCacheMisses++;
869923 enqueueReadyTask (taskInfo, ctx, inputs, sres);
870924 return ;
871925 }
@@ -874,6 +928,7 @@ class EngineImpl: public ActionExecutorListener {
874928 casDB->get (res->data (), [this , ctx, inputs, sres, &taskInfo](result<CASObject, Error> res) {
875929 if (res.has_error ()) {
876930 logger->error (logctx, res.error ());
931+ st_taskCacheMisses++;
877932 enqueueReadyTask (taskInfo, ctx, inputs, sres);
878933 return ;
879934 }
@@ -884,6 +939,7 @@ class EngineImpl: public ActionExecutorListener {
884939 makeEngineError (EngineError::InternalProtobufSerialization,
885940 " failed to parse cached task transition" )
886941 );
942+ st_taskCacheMisses++;
887943 enqueueReadyTask (taskInfo, ctx, inputs, sres);
888944 return ;
889945 }
@@ -920,11 +976,13 @@ class EngineImpl: public ActionExecutorListener {
920976
921977 if (res.has_error ()) {
922978 logger->error (logctx, res.error ());
979+ st_taskCacheMisses++;
923980 enqueueReadyTask (taskInfo, ctx, inputs, sres);
924981 return ;
925982 }
926983 }
927984
985+ st_taskCacheHits++;
928986 processTaskNextState (taskInfo, value.state ());
929987 });
930988 });
@@ -1012,6 +1070,7 @@ class EngineImpl: public ActionExecutorListener {
10121070 }
10131071
10141072 void processTaskNextState (TaskInfo& taskInfo, const TaskNextState& next) {
1073+ st_taskTransitions++;
10151074 std::lock_guard<std::mutex> lock (taskInfosMutex);
10161075
10171076 switch (next.StateValue_case ()) {
@@ -1091,6 +1150,8 @@ class EngineImpl: public ActionExecutorListener {
10911150 }
10921151
10931152 void processFinishedTask (TaskInfo& taskInfo) {
1153+ st_taskCompletedCount++;
1154+
10941155 // update all tasks waiting on this task
10951156 auto work = [this , &taskInfo](const JobContext&) {
10961157 std::lock_guard<std::mutex> lock (taskInfosMutex);
@@ -1428,6 +1489,7 @@ class EngineImpl: public ActionExecutorListener {
14281489
14291490
14301491 void sendResult (const result<Artifact, Error>& buildResult) {
1492+ engine.st_buildCompletedCount ++;
14311493 engine.logger ->event (engine.logctx , {
14321494 makeStat (" log.message" , " build_completed" ),
14331495 makeStat (" build_id" , buildID),
@@ -1567,3 +1629,7 @@ std::shared_ptr<CASDatabase> Engine::cas() {
15671629Build Engine::build (const Label& artifact) {
15681630 return static_cast <EngineImpl*>(impl)->build (artifact);
15691631}
1632+
1633+ std::vector<Stat> Engine::stats () {
1634+ return static_cast <EngineImpl*>(impl)->stats ();
1635+ }
0 commit comments