Skip to content

Commit a97faf7

Browse files
committed
[QC-421] Allow to check PP tasks results in CheckRunners
1 parent 1157807 commit a97faf7

10 files changed

Lines changed: 90 additions & 10 deletions

File tree

Framework/postprocessing.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@
2222
"url": "ccdb-test.cern.ch:8080"
2323
}
2424
},
25+
"checks": {
26+
"ExamplePPCheck": {
27+
"active": "true",
28+
"className": "o2::quality_control_modules::skeleton::SkeletonCheck",
29+
"moduleName": "QcSkeleton",
30+
"policy": "OnAny",
31+
"detectorName": "TST",
32+
"dataSource": [{
33+
"type": "PostProcessing",
34+
"name": "ExampleTrend",
35+
"MOs": ["mean_of_histogram"]
36+
}]
37+
}
38+
},
2539
"postprocessing": {
2640
"ExamplePostprocessing": {
2741
"active": "true",

Framework/src/Check.cxx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "QualityControl/TaskRunner.h"
2626
#include "QualityControl/InputUtils.h"
2727
#include "QualityControl/RootClassFactory.h"
28+
#include "QualityControl/PostProcessingDevice.h"
2829
// Fairlogger
2930
#include <fairlogger/Logger.h>
3031

@@ -34,6 +35,7 @@ using namespace o2::configuration;
3435

3536
using namespace o2::quality_control::checker;
3637
using namespace o2::quality_control::core;
38+
using namespace o2::quality_control::postprocessing;
3739
using namespace std;
3840

3941
/// Static functions
@@ -88,12 +90,15 @@ void Check::initConfig(std::string checkName)
8890
mNumberOfTaskSources = 0;
8991
for (const auto& [_key, dataSource] : checkConfig.get_child("dataSource")) {
9092
(void)_key;
91-
if (dataSource.get<std::string>("type") == "Task" || dataSource.get<std::string>("type") == "ExternalTask") {
93+
if (auto sourceType = dataSource.get<std::string>("type");
94+
sourceType == "Task" || sourceType == "ExternalTask" || sourceType == "PostProcessing") {
9295
auto taskName = dataSource.get<std::string>("name");
9396
mNumberOfTaskSources++;
9497

9598
if (dataSource.get<std::string>("type") == "Task") {
9699
mInputs.push_back({ taskName, TaskRunner::createTaskDataOrigin(), TaskRunner::createTaskDataDescription(taskName) });
100+
} else if (dataSource.get<std::string>("type") == "PostProcessing") {
101+
mInputs.push_back({ taskName, PostProcessingDevice::createPostProcessingDataOrigin(), PostProcessingDevice::createPostProcessingDataDescription(taskName) });
97102
} else if (dataSource.get<std::string>("type") == "ExternalTask") {
98103
auto query = config->getString("qc.externalTasks." + taskName + ".query").get();
99104
framework::Inputs input = o2::framework::DataDescriptorQueryBuilder::parse(query.c_str());

Framework/src/CheckRunner.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ void CheckRunner::prepareCacheData(framework::InputRecord& inputRecord)
274274
void CheckRunner::sendPeriodicMonitoring()
275275
{
276276
if (mTimer.isTimeout()) {
277-
mTimer.reset(1000000); // 10 s.
277+
mTimer.reset(10000000); // 10 s.
278278
mCollector->send({ mTotalNumberObjectsReceived, "qc_objects_received" }, DerivedMetricMode::RATE);
279279
mCollector->send({ mTotalNumberCheckExecuted, "qc_checks_executed" }, DerivedMetricMode::RATE);
280280
mCollector->send({ mTotalNumberQOStored, "qc_qo_stored" }, DerivedMetricMode::RATE);
@@ -397,7 +397,7 @@ void CheckRunner::initMonitoring()
397397
mCollector->enableProcessMonitoring();
398398
mCollector->addGlobalTag(tags::Key::Subsystem, tags::Value::QC);
399399
mCollector->addGlobalTag("CheckRunnerName", mDeviceName);
400-
mTimer.reset(1000000); // 10 s.
400+
mTimer.reset(10000000); // 10 s.
401401
}
402402

403403
void CheckRunner::initServiceDiscovery()

Framework/src/InfrastructureGenerator.cxx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,15 @@ void InfrastructureGenerator::generateCheckRunners(framework::WorkflowSpec& work
367367
}
368368
}
369369

370+
if (config->getRecursive("qc").count("postprocessing")) {
371+
for (const auto& [ppTaskName, ppTaskConfig] : config->getRecursive("qc.postprocessing")) {
372+
if (ppTaskConfig.get<bool>("active", true)) {
373+
InputSpec taskOutput{ ppTaskName, PostProcessingDevice::createPostProcessingDataOrigin(), PostProcessingDevice::createPostProcessingDataDescription(ppTaskName) };
374+
tasksOutputMap.insert({ DataSpecUtils::label(taskOutput), taskOutput });
375+
}
376+
}
377+
}
378+
370379
// For each external task prepare the InputSpec to be stored in tasksoutputMap
371380
if (config->getRecursive("qc").count("externalTasks")) {
372381
for (const auto& [taskName, taskConfig] : config->getRecursive("qc.externalTasks")) {
@@ -467,7 +476,7 @@ void InfrastructureGenerator::generatePostProcessing(WorkflowSpec& workflow, std
467476
ppTask.getOptions()
468477
};
469478

470-
ppTaskSpec.algorithm = std::move(adaptFromTask<PostProcessingDevice>(std::move(ppTask)));
479+
ppTaskSpec.algorithm = adaptFromTask<PostProcessingDevice>(std::move(ppTask));
471480

472481
workflow.emplace_back(std::move(ppTaskSpec));
473482
}

Framework/src/PostProcessingDevice.cxx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,9 @@ void PostProcessingDevice::init(framework::InitContext& ctx)
5252

5353
void PostProcessingDevice::run(framework::ProcessingContext& ctx)
5454
{
55-
// todo: enable once check runners can store the results.
56-
// Now we still choose the default option - storing data directly to the repo.
5755
// we set the publication callback each time, because we cannot be sure that
5856
// the reference to DataAllocator does not change
59-
// mRunner.setPublicationCallback(publishToDPL(ctx.outputs(), outputBinding));
57+
mRunner->setPublicationCallback(publishToDPL(ctx.outputs(), outputBinding));
6058

6159
// When run returns false, it has done its processing.
6260
if (!mRunner->run()) {

Framework/test/testCheck.cxx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,22 @@ BOOST_AUTO_TEST_CASE(test_check_dont_invoke_beautify)
116116
// Beautify should not run - more than one MO declared
117117
BOOST_CHECK(!testCheck.mBeautify);
118118
}
119+
120+
BOOST_AUTO_TEST_CASE(test_check_postprocessing)
121+
{
122+
std::string configFilePath = std::string("json://") + getTestDataDirectory() + "testSharedConfig.json";
123+
124+
Check check("checkAnyPP", configFilePath);
125+
check.init();
126+
127+
TestCheck testCheck;
128+
check.setCheckInterface(dynamic_cast<CheckInterface*>(&testCheck));
129+
130+
std::map<std::string, std::shared_ptr<MonitorObject>> moMap = { { "SkeletonPostProcessing/example", std::shared_ptr<MonitorObject>(new MonitorObject()) } };
131+
132+
check.check(moMap);
133+
// Check should run
134+
BOOST_CHECK(testCheck.mCheck);
135+
// Beautify should run - single MO declared
136+
BOOST_CHECK(testCheck.mBeautify);
137+
}

Framework/test/testSharedConfig.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@
147147
"test2"
148148
]
149149
}]
150+
},
151+
"checkAnyPP": {
152+
"active": "true",
153+
"className": "o2::quality_control_modules::skeleton::SkeletonCheck",
154+
"moduleName": "QcSkeleton",
155+
"policy": "OnAny",
156+
"dataSource": [{
157+
"type": "PostProcessing",
158+
"name": "SkeletonPostProcessing",
159+
"MOs": [
160+
"example"
161+
]
162+
}]
150163
}
151164
},
152165
"postprocessing": {

Modules/Skeleton/src/SkeletonCheck.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ void SkeletonCheck::beautify(std::shared_ptr<MonitorObject> mo, Quality checkRes
6262
if (checkResult == Quality::Good) {
6363
h->SetFillColor(kGreen);
6464
} else if (checkResult == Quality::Bad) {
65-
ILOG(Info, Support) << "Quality::Bad, setting to red";
65+
ILOG(Info, Support) << "Quality::Bad, setting to red" << ENDM;
6666
h->SetFillColor(kRed);
6767
} else if (checkResult == Quality::Medium) {
68-
ILOG(Info, Support) << "Quality::medium, setting to orange";
68+
ILOG(Info, Support) << "Quality::medium, setting to orange" << ENDM;
6969
h->SetFillColor(kOrange);
7070
}
7171
h->SetLineColor(kBlack);

doc/Advanced.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ Below the full QC Checks configuration structure is described. Note that more th
600600
"policy": "OnAny", "": ["Policy which determines when MOs should be checked. See the documentation",
601601
"of Checks for the list of available policies and their behaviour."],
602602
"dataSource": [{ "": "List of data source of the Check.",
603-
"type": "Task", "": "Type of the data source, only \"Task\" up to this date",
603+
"type": "Task", "": "Type of the data source, \"Task\", \"ExternalTask\" or \"PostProcessing\"",
604604
"name": "myTask_1", "": "Name of the Task",
605605
"MOs": [ "example" ], "": ["List of MOs to be checked. Use \"all\" (not as a list) to check each MO ",
606606
"which is produced by the Task"]

doc/PostProcessing.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,28 @@ This is a snippet of a JSON structure which configures a post-processing task:
8888
```
8989
Each task is identified by its name (`MyPostProcessingTask`). One can activate it by setting the `"active"` field to `"true"`. The task is loaded given its full `"className"` and a `"moduleName"` where it is located. The `"detectorName"` might be used by tasks to store generated data in correct paths in QCDB. The `"initTrigger"`, `"updateTrigger"` and `"stopTrigger"` lists contain triggers which should invoke corresponding interface methods.
9090

91+
Checks can be applied to the results of Post-processing Tasks just as for normal QC Tasks. However, one should use
92+
data source type of `"PostProcessing"` instead of `"Task"`:
93+
94+
```
95+
...
96+
"checks": {
97+
"ExamplePPCheck": {
98+
"active": "true",
99+
"className": "o2::quality_control_modules::skeleton::SkeletonCheck",
100+
"moduleName": "QcSkeleton",
101+
"policy": "OnAny",
102+
"detectorName": "TST",
103+
"dataSource": [{
104+
"type": "PostProcessing",
105+
"name": "ExampleTrend",
106+
"MOs": ["mean_of_histogram"]
107+
}]
108+
}
109+
},
110+
...
111+
```
112+
91113
### Triggers configuration
92114

93115
Each of the three methods can be invoked by one or more triggers. Below are listed the possible options (case insensitive).

0 commit comments

Comments
 (0)