Skip to content

Commit ff2ce9a

Browse files
authored
Common: allow retrieving latest QOs in QualityTask (#2416)
* [COMMON] allow retrieving latest QOs in QualityTask Instead of retrieving the QOs based on the time stamp of the update trigger, the latest version of the QOs is retrieved, even if their validities are ending before the update time stamp. A `maxObjectAgeSeconds` configuration parameter allows to consider only QOs that were created not more than a given number of seconds before the time at which the `update()` function was called. * [COMMON] updated QualityTask documentation
1 parent 28acd77 commit ff2ce9a

3 files changed

Lines changed: 33 additions & 11 deletions

File tree

Modules/Common/include/Common/QualityTask.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,14 @@ class QualityTask : public quality_control::postprocessing::PostProcessingInterf
8383
void finalize(quality_control::postprocessing::Trigger, framework::ServiceRegistryRef) override;
8484

8585
private:
86-
std::pair<std::shared_ptr<quality_control::core::QualityObject>, bool> getQO(
87-
quality_control::repository::DatabaseInterface& qcdb, const quality_control::postprocessing::Trigger& t, const std::string& fullPath, const std::string& group);
86+
std::pair<std::shared_ptr<quality_control::core::QualityObject>, bool> getLatestQO(
87+
quality_control::repository::DatabaseInterface& qcdb, const o2::quality_control::core::Activity& activity, const std::string& fullPath, const std::string& group);
8888

8989
private:
9090
/// \brief configuration parameters
9191
QualityTaskConfig mConfig;
92+
/// \brief QOs are discarded if their creation time stamp is more than mMaxObjectAgeMs milliseconds in the past (set to zero to accept all objects)
93+
int64_t mMaxObjectAgeMs{ 600000 };
9294
/// \brief latest creation timestamp of each tracked QO
9395
std::unordered_map<std::string /* full path */, uint64_t> mLatestTimestamps;
9496
/// \brief colors associated to each quality state (Good/Medium/Bad/Null)

Modules/Common/src/QualityTask.cxx

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,20 @@ void QualityTask::initialize(quality_control::postprocessing::Trigger t, framewo
153153
mColors[Quality::Bad.getName()] = kRed;
154154
mColors[Quality::Medium.getName()] = kOrange - 3;
155155
mColors[Quality::Good.getName()] = kGreen + 2;
156+
mColors["Missing"] = kBlue + 2;
156157

157158
mQualityIDs[Quality::Null.getName()] = 0;
158159
mQualityIDs[Quality::Bad.getName()] = 1;
159160
mQualityIDs[Quality::Medium.getName()] = 2;
160161
mQualityIDs[Quality::Good.getName()] = 3;
161162

163+
std::string key("maxObjectAgeSeconds");
164+
auto value = mCustomParameters.atOptional(key, t.activity);
165+
if (!value) {
166+
value = mCustomParameters.atOptional(key).value_or("600");
167+
}
168+
mMaxObjectAgeMs = std::stoi(*value) * 1000;
169+
162170
// instantiate the histograms and trends, one for each of the quality objects in the data sources list
163171
for (const auto& qualityGroupConfig : mConfig.qualityGroups) {
164172
for (const auto& qualityConfig : qualityGroupConfig.inputObjects) {
@@ -189,19 +197,26 @@ void QualityTask::initialize(quality_control::postprocessing::Trigger t, framewo
189197
// A non-null QO is returned in the first element of the pair if the QO is found in the QCDB
190198
// The second element of the pair is set to true if the QO has a time stamp more recent than the last retrieved one
191199

192-
std::pair<std::shared_ptr<QualityObject>, bool> QualityTask::getQO(
193-
repository::DatabaseInterface& qcdb, const Trigger& t, const std::string& fullPath, const std::string& group)
200+
std::pair<std::shared_ptr<QualityObject>, bool> QualityTask::getLatestQO(
201+
repository::DatabaseInterface& qcdb, const Activity& activity, const std::string& fullPath, const std::string& group)
194202
{
195203
// retrieve QO from CCDB
196-
auto qo = qcdb.retrieveQO(fullPath, t.timestamp, t.activity);
204+
auto qo = qcdb.retrieveQO(fullPath, repository::DatabaseInterface::Timestamp::Latest, activity);
197205
if (!qo) {
198206
return { nullptr, false };
199207
}
200208
// get the MO creation time stamp
201-
long thisTimestamp{ 0 };
202-
auto createdIter = qo->getMetadataMap().find(repository::metadata_keys::created);
203-
if (createdIter != qo->getMetadataMap().end()) {
204-
thisTimestamp = std::stol(createdIter->second);
209+
long thisTimestamp = (qo->getMetadataMap().count(repository::metadata_keys::created) > 0) ? std::stol(qo->getMetadataMap().at(repository::metadata_keys::created)) : 0;
210+
211+
// check if the object is not older than a given number of milliseconds
212+
if (mMaxObjectAgeMs > 0) {
213+
uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
214+
auto elapsed = now - thisTimestamp;
215+
ILOG(Info, Devel) << "Quality Object '" << fullPath << "' for activity " << activity << " was created " << elapsed << " ms in the past" << ENDM;
216+
if (elapsed > mMaxObjectAgeMs) {
217+
ILOG(Warning, Support) << "Quality Object '" << fullPath << "' for activity " << activity << " is too old: " << elapsed << " > " << mMaxObjectAgeMs << " ms" << ENDM;
218+
return { nullptr, false };
219+
}
205220
}
206221

207222
// check if the object is newer than the last visited one
@@ -245,9 +260,9 @@ void QualityTask::update(quality_control::postprocessing::Trigger t, framework::
245260
// retrieve QO from CCDB, in the form of a std::pair<std::shared_ptr<QualityObject>, bool>
246261
// a valid object is returned in the first element of the pair if the QO is found in the QCDB
247262
// the second element of the pair is set to true if the QO has a time stamp more recent than the last retrieved one
248-
auto [qo, wasUpdated] = getQO(qcdb, t, fullPath, qualityGroupConfig.name);
263+
auto [qo, wasUpdated] = getLatestQO(qcdb, t.activity, fullPath, qualityGroupConfig.name);
249264
if (!qo) {
250-
lines.emplace_back(Message{ fmt::format("#color[{}]{{{} : quality missing!}}", mColors[Quality::Null.getName()], qualityTitle) });
265+
lines.emplace_back(Message{ fmt::format("#color[{}]{{{} : quality missing!}}", mColors["Missing"], qualityTitle) });
251266
lines.emplace_back(TextAlign{ 12 });
252267
continue;
253268
}

doc/PostProcessing.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,8 @@ A **title** can be added, which is used in the summary canvas to denote given Qu
730730
If it is absent, **name** is used instead.
731731
Optionally, one can add **messageBad**, **messageMedium**, **messageGood**, **messageNull** to add a message when a particular Quality is seen.
732732

733+
At each update, the task retrieves the latest version of each input QualityObject, even if their validity range ends in the past. A task configuration parameter, called `maxObjectAgeSeconds`, allows to define the maximum allowed age (in seconds) of the retrieved objects. The age is defined as the difference between the the time stamp of the task update and the creation time stamp of the retrieved object.
734+
733735
Here is a complete example of `QualityTask` configuration:
734736
```json
735737
{
@@ -743,6 +745,9 @@ Here is a complete example of `QualityTask` configuration:
743745
"className": "o2::quality_control_modules::common::QualityTask",
744746
"moduleName": "QualityControl",
745747
"detectorName": "TST",
748+
"taskParameters": {
749+
"maxObjectAgeSeconds": "300"
750+
},
746751
"qualityGroups": [
747752
{
748753
"name" : "global",

0 commit comments

Comments
 (0)