Skip to content

Commit f014a8a

Browse files
authored
Unify logging (QC-224) (#222)
- Get rid of all cout/cerr in QC framework in favour of QCInfoLogger - Introduce some of the changes I proposed in Qcinfologger to decrease verbosity, in particular ILOG(level) << xxx << ENDM
1 parent d7df411 commit f014a8a

28 files changed

Lines changed: 205 additions & 122 deletions

Framework/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ add_library(QualityControl
4343
src/CheckInterface.cxx
4444
src/DatabaseFactory.cxx
4545
src/CcdbDatabase.cxx
46+
src/QcInfoLogger.cxx
4647
src/TaskFactory.cxx
4748
src/TaskRunner.cxx
4849
src/TaskRunnerFactory.cxx

Framework/include/QualityControl/QcInfoLogger.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
#define QC_CORE_QCINFOLOGGER_H
1818

1919
#include <InfoLogger/InfoLogger.hxx>
20-
#include "QualityControl/TaskInterface.h"
2120

22-
typedef AliceO2::InfoLogger::InfoLogger infologger; // not to have to type the full stuff each time -> log::endm
21+
typedef AliceO2::InfoLogger::InfoLogger infologger; // not to have to type the full stuff each time
22+
typedef AliceO2::InfoLogger::InfoLoggerContext infoContext;
2323

2424
namespace o2::quality_control::core
2525
{
@@ -30,6 +30,10 @@ namespace o2::quality_control::core
3030
/// and configure its own instance of InfoLogger.
3131
/// Independent InfoLogger instances can still be created when and if needed.
3232
/// Usage : QcInfoLogger::GetInstance() << "blabla" << infologger::endm;
33+
/// ILOG(Info) << "info message" << ENDM; // short version
34+
/// ILOGI << "info message" << ENDM; // shorter
35+
/// ILOG_INST << InfoLogger::InfoLoggerMessageOption{ InfoLogger::Fatal, 1, 1, "asdf", 3 }
36+
/// << "fatal message with extra fields" << ENDM; // complex version
3337
///
3438
/// \author Barthelemy von Haller
3539
class QcInfoLogger : public AliceO2::InfoLogger::InfoLogger
@@ -44,12 +48,7 @@ class QcInfoLogger : public AliceO2::InfoLogger::InfoLogger
4448
}
4549

4650
private:
47-
QcInfoLogger()
48-
{
49-
// TODO configure the QC infologger, e.g. proper facility
50-
*this << "QC infologger initialized" << infologger::endm;
51-
}
52-
51+
QcInfoLogger();
5352
~QcInfoLogger() override = default;
5453

5554
// Disallow copying
@@ -59,4 +58,14 @@ class QcInfoLogger : public AliceO2::InfoLogger::InfoLogger
5958

6059
} // namespace o2::quality_control::core
6160

61+
// Define the ILOG() macro.
62+
// Unfortunately it is not possible to have a zero argument MACRO here without generating warnings
63+
#define ILOG_INST o2::quality_control::core::QcInfoLogger::GetInstance()
64+
#define ILOG(severity) ILOG_INST << AliceO2::InfoLogger::InfoLogger::Severity::severity
65+
#define ILOGI ILOG_INST << AliceO2::InfoLogger::InfoLogger::Info
66+
#define ILOGW ILOG_INST << AliceO2::InfoLogger::InfoLogger::Warning
67+
#define ILOGE ILOG_INST << AliceO2::InfoLogger::InfoLogger::Error
68+
#define ILOGF ILOG_INST << AliceO2::InfoLogger::InfoLogger::Fatal
69+
#define ENDM AliceO2::InfoLogger::InfoLogger::endm;
70+
6271
#endif // QC_CORE_QCINFOLOGGER_H

Framework/include/QualityControl/TaskFactory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <memory>
2121
// QC
2222
#include "QualityControl/TaskConfig.h"
23+
#include "QualityControl/TaskInterface.h"
2324

2425
namespace o2::quality_control::core
2526
{

Framework/src/CcdbDatabase.cxx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "QualityControl/CcdbDatabase.h"
1717
#include "QualityControl/MonitorObject.h"
1818
#include "QualityControl/Version.h"
19+
#include "QualityControl/QcInfoLogger.h"
1920
#include "Common/Exceptions.h"
2021
// ROOT
2122
#include <TBufferJSON.h>
@@ -46,19 +47,19 @@ CcdbDatabase::~CcdbDatabase() { disconnect(); }
4647
void CcdbDatabase::loadDeprecatedStreamerInfos()
4748
{
4849
if (getenv("QUALITYCONTROL_ROOT") == nullptr) {
49-
LOG(WARNING) << "QUALITYCONTROL_ROOT is not set thus the the streamerinfo ROOT file can't be found.\n"
50-
<< "Consequently, old data might not be readable.";
50+
ILOG(Warning) << "QUALITYCONTROL_ROOT is not set thus the the streamerinfo ROOT file can't be found.\n"
51+
<< "Consequently, old data might not be readable." << ENDM;
5152
return;
5253
}
5354
string path = string(getenv("QUALITYCONTROL_ROOT")) + "/etc/";
5455
vector<string> filenames = { "streamerinfos.root", "streamerinfos_v017.root" };
5556
for (auto filename : filenames) {
5657
string localPath = path + filename;
57-
LOG(INFO) << "Loading streamerinfos from : " << localPath;
58+
ILOG(Info) << "Loading streamerinfos from : " << localPath << ENDM;
5859
TFile file(localPath.data(), "READ");
5960
if (file.IsZombie()) {
6061
string s = string("Cannot find ") + localPath;
61-
LOG(ERROR) << s;
62+
ILOG(Error) << s << ENDM;
6263
BOOST_THROW_EXCEPTION(DatabaseException() << errinfo_details(s));
6364
}
6465
TIter next(file.GetListOfKeys());
@@ -68,7 +69,7 @@ void CcdbDatabase::loadDeprecatedStreamerInfos()
6869
if (!cl->InheritsFrom("TStreamerInfo"))
6970
continue;
7071
auto* si = (TStreamerInfo*)key->ReadObj();
71-
LOG(DEBUG) << "importing streamer info version " << si->GetClassVersion() << " for '" << si->GetName();
72+
ILOG(Debug) << "importing streamer info version " << si->GetClassVersion() << " for '" << si->GetName() << ENDM;
7273
si->BuildCheck();
7374
}
7475
}
@@ -134,14 +135,14 @@ std::shared_ptr<core::MonitorObject> CcdbDatabase::retrieveMO(std::string taskNa
134135
if (object == nullptr) {
135136
// We could not open a TFile we should now try to open an object directly serialized
136137
object = ccdbApi.retrieve(path, metadata, when);
137-
LOG(DEBUG) << "We could retrieve the object " << path << " as a streamed object.";
138+
ILOG(Debug) << "We could retrieve the object " << path << " as a streamed object." << ENDM;
138139
if (object == nullptr) {
139140
return nullptr;
140141
}
141142
}
142143
std::shared_ptr<core::MonitorObject> mo(dynamic_cast<core::MonitorObject*>(object));
143144
if (mo == nullptr) {
144-
LOG(ERROR) << "Could not cast the object " << taskName << "/" << objectName << " to MonitorObject";
145+
ILOG(Error) << "Could not cast the object " << taskName << "/" << objectName << " to MonitorObject" << ENDM;
145146
}
146147
return mo;
147148
}
@@ -304,7 +305,7 @@ long CcdbDatabase::getCurrentTimestamp()
304305

305306
void CcdbDatabase::truncate(std::string taskName, std::string objectName)
306307
{
307-
LOG(INFO) << "truncating data for " << taskName << "/" << objectName;
308+
ILOG(Info) << "truncating data for " << taskName << "/" << objectName << ENDM;
308309

309310
ccdbApi.truncate(taskName + "/" + objectName);
310311
}

Framework/src/DataDumpGui.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
///
1616

1717
#include "QualityControl/DataDumpGui.h"
18-
18+
#include "QualityControl/QcInfoLogger.h"
1919
#include "imgui/BaseGui.h"
2020
#include "imgui/imgui.h"
2121
#include <Headers/DataHeader.h>
@@ -265,7 +265,7 @@ bool DataDumpGui::ConditionalRun()
265265
bool DataDumpGui::handleParts(FairMQParts& parts)
266266
{
267267
if (parts.Size() != 2) {
268-
cout << "number of parts must be 2" << endl;
268+
ILOG(Debug) << "number of parts must be 2" << ENDM;
269269
return false;
270270
}
271271

Framework/src/MySqlDatabase.cxx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void MySqlDatabase::connect(std::string host, std::string database, std::string
6161
}
6262
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details(s));
6363
} else {
64-
QcInfoLogger::GetInstance() << "Connected to the database" << infologger::endm;
64+
ILOG(Info) << "Connected to the database" << ENDM;
6565
}
6666
}
6767

@@ -88,7 +88,7 @@ void MySqlDatabase::prepareTable(std::string table_name)
8888
if (!execute(query)) {
8989
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details("Failed to create data table"));
9090
} else {
91-
QcInfoLogger::GetInstance() << "Create data table " << table_name << infologger::endm;
91+
ILOG(Info) << "Create data table " << table_name << ENDM;
9292
}
9393
}
9494

@@ -116,8 +116,8 @@ void MySqlDatabase::storeMO(std::shared_ptr<o2::quality_control::core::MonitorOb
116116

117117
void MySqlDatabase::storeQueue()
118118
{
119-
QcInfoLogger::GetInstance() << "Database queue will now be processed (" << queueSize << " objects)"
120-
<< infologger::endm;
119+
ILOG(Info) << "Database queue will now be processed (" << queueSize << " objects)"
120+
<< ENDM;
121121

122122
for (auto& kv : mMonitorObjectsQueue) {
123123
storeForMonitorObject(kv.first);
@@ -191,8 +191,8 @@ void MySqlDatabase::storeForMonitorObject(std::string name)
191191
return;
192192
}
193193

194-
cout << "** Store for task " << name << endl;
195-
cout << " # objects : " << objects.size() << endl;
194+
ILOG(Info) << "** Store for task " << name << ENDM;
195+
ILOG(Info) << " # objects : " << objects.size() << ENDM;
196196

197197
// build statement string
198198
string table_name = "data_" + name;
@@ -346,7 +346,7 @@ std::shared_ptr<o2::quality_control::core::MonitorObject> MySqlDatabase::retriev
346346
try {
347347
mo = std::shared_ptr<MonitorObject>((MonitorObject*)(mess.ReadObjectAny(mess.GetClass())));
348348
} catch (...) {
349-
QcInfoLogger::GetInstance() << "Node: unable to parse TObject from MySQL" << infologger::endm;
349+
ILOG(Info) << "Node: unable to parse TObject from MySQL" << ENDM;
350350
throw;
351351
}
352352
}
@@ -406,7 +406,7 @@ void MySqlDatabase::addIndex(string table, string column)
406406
if (res) {
407407
delete (res);
408408
} else {
409-
cerr << "Couldn't create the index on table " << table << " on column " << column << endl;
409+
ILOG(Error) << "Couldn't create the index on table " << table << " on column " << column << ENDM;
410410
}
411411
}
412412

@@ -457,7 +457,7 @@ void MySqlDatabase::truncate(std::string taskName, std::string objectName)
457457
string s = string("Failed to delete object ") + objectName + " from task " + taskName;
458458
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details(s));
459459
} else {
460-
QcInfoLogger::GetInstance() << "Delete object " << objectName << " from task " << taskName << infologger::endm;
460+
ILOG(Info) << "Delete object " << objectName << " from task " << taskName << ENDM;
461461
}
462462
}
463463

Framework/src/PostProcessingRunner.cxx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,33 @@ PostProcessingRunner::~PostProcessingRunner()
3939

4040
bool PostProcessingRunner::init()
4141
{
42-
LOG(INFO) << "Initializing PostProcessingRunner";
42+
ILOG(Info) << "Initializing PostProcessingRunner" << ENDM;
4343

4444
try {
4545
// configuration of the database
4646
mDatabase = DatabaseFactory::create(mConfigFile->get<std::string>("qc.config.database.implementation"));
4747
mDatabase->connect(mConfigFile->getRecursiveMap("qc.config.database"));
48-
LOG(INFO) << "Database that is going to be used : ";
49-
LOG(INFO) << ">> Implementation : " << mConfigFile->get<std::string>("qc.config.database.implementation");
50-
LOG(INFO) << ">> Host : " << mConfigFile->get<std::string>("qc.config.database.host");
48+
ILOG(Info) << "Database that is going to be used : " << ENDM;
49+
ILOG(Info) << ">> Implementation : " << mConfigFile->get<std::string>("qc.config.database.implementation") << ENDM;
50+
ILOG(Info) << ">> Host : " << mConfigFile->get<std::string>("qc.config.database.host") << ENDM;
5151
mServices.registerService<DatabaseInterface>(mDatabase.get());
5252
} catch (
5353
std::string const& e) { // we have to catch here to print the exception because the device will make it disappear todo: is it still the case?
54-
LOG(ERROR) << "exception : " << e;
54+
ILOG(Error) << "exception : " << e << ENDM;
5555
throw;
5656
} catch (...) {
5757
std::string diagnostic = boost::current_exception_diagnostic_information();
58-
LOG(ERROR) << "Unexpected exception, diagnostic information follows:\n"
59-
<< diagnostic;
58+
ILOG(Error) << "Unexpected exception, diagnostic information follows:\n"
59+
<< diagnostic << ENDM;
6060
throw;
6161
}
6262

6363
// setup user's task
64-
LOG(INFO) << "Creating a user task '" << mConfig.taskName << "'";
64+
ILOG(Info) << "Creating a user task '" << mConfig.taskName << "'" << ENDM;
6565
PostProcessingFactory f;
6666
mTask.reset(f.create(mConfig));
6767
if (mTask) {
68-
LOG(INFO) << "The user task '" << mConfig.taskName << "' successfully created";
68+
ILOG(Info) << "The user task '" << mConfig.taskName << "' successfully created" << ENDM;
6969

7070
mState = TaskState::Created;
7171
mTask->setName(mConfig.taskName);
@@ -74,19 +74,19 @@ bool PostProcessingRunner::init()
7474
mInitTriggers = trigger_helpers::createTriggers(mConfig.initTriggers);
7575
return true;
7676
} else {
77-
LOG(INFO) << "Failed to create the task '" << mConfig.taskName << "'";
77+
ILOG(Info) << "Failed to create the task '" << mConfig.taskName << "'" << ENDM;
7878
// todo :maybe exceptions instead of return values
7979
return false;
8080
}
8181
}
8282

8383
bool PostProcessingRunner::run()
8484
{
85-
LOG(INFO) << "Running PostProcessingRunner";
85+
ILOG(Info) << "Running PostProcessingRunner" << ENDM;
8686

8787
if (mState == TaskState::Created) {
8888
if (Trigger trigger = trigger_helpers::tryTrigger(mInitTriggers)) {
89-
LOG(INFO) << "Initializing user task";
89+
ILOG(Info) << "Initializing user task" << ENDM;
9090

9191
mTask->initialize(trigger, mServices);
9292

@@ -98,22 +98,22 @@ bool PostProcessingRunner::run()
9898
if (mState == TaskState::Running) {
9999

100100
if (Trigger trigger = trigger_helpers::tryTrigger(mUpdateTriggers)) {
101-
LOG(INFO) << "Updating user task";
101+
ILOG(Info) << "Updating user task" << ENDM;
102102
mTask->update(trigger, mServices);
103103
}
104104
if (Trigger trigger = trigger_helpers::tryTrigger(mStopTriggers)) {
105-
LOG(INFO) << "Finalizing user task";
105+
ILOG(Info) << "Finalizing user task" << ENDM;
106106
mTask->finalize(trigger, mServices);
107107
mState = TaskState::Finished; // maybe the task should monitor its state by itself?
108108
}
109109
}
110110
if (mState == TaskState::Finished) {
111-
LOG(INFO) << "User task finished, returning...";
111+
ILOG(Info) << "User task finished, returning..." << ENDM;
112112
return false;
113113
}
114114
if (mState == TaskState::INVALID) {
115115
// todo maybe exception?
116-
LOG(INFO) << "User task state INVALID, returning...";
116+
ILOG(Info) << "User task state INVALID, returning..." << ENDM;
117117
return false;
118118
}
119119

Framework/src/QcInfoLogger.cxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright CERN and copyright holders of ALICE O2. This software is
2+
// distributed under the terms of the GNU General Public License v3 (GPL
3+
// Version 3), copied verbatim in the file "COPYING".
4+
//
5+
// See http://alice-o2.web.cern.ch/license for full licensing information.
6+
//
7+
// In applying this license CERN does not waive the privileges and immunities
8+
// granted to it by virtue of its status as an Intergovernmental Organization
9+
// or submit itself to any jurisdiction.
10+
11+
///
12+
/// \file QcInfoLogger.cxx
13+
/// \author Barthelemy von Haller
14+
///
15+
16+
#include "QualityControl/QcInfoLogger.h"
17+
#include <InfoLogger/InfoLoggerFMQ.hxx>
18+
19+
namespace o2::quality_control::core
20+
{
21+
22+
QcInfoLogger::QcInfoLogger()
23+
{
24+
infoContext context;
25+
context.setField(infoContext::FieldName::Facility, "QC");
26+
context.setField(infoContext::FieldName::System, "QC");
27+
this->setContext(context);
28+
// setFMQLogsToInfoLogger(this); // disabled, see https://github.com/AliceO2Group/QualityControl/pull/222
29+
*this << "QC infologger initialized" << infologger::endm;
30+
}
31+
32+
} // namespace o2::quality_control::core

Framework/src/RepositoryBenchmark.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ void RepositoryBenchmark::InitTask()
8585
mDatabase->prepareTaskDataContainer(mTaskName);
8686
} catch (boost::exception& exc) {
8787
string diagnostic = boost::current_exception_diagnostic_information();
88-
std::cerr << "Unexpected exception, diagnostic information follows:\n"
89-
<< diagnostic << endl;
88+
ILOG(Error) << "Unexpected exception, diagnostic information follows:\n"
89+
<< diagnostic << ENDM;
9090
if (diagnostic == "No diagnostic information available.") {
9191
throw;
9292
}

Framework/src/ServiceDiscovery.cxx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
///
1414

1515
#include "QualityControl/ServiceDiscovery.h"
16-
#include <iostream>
16+
#include "QualityControl/QcInfoLogger.h"
1717
#include <string>
1818
#include <boost/asio.hpp>
1919
#include <boost/property_tree/ptree.hpp>
@@ -124,7 +124,7 @@ void ServiceDiscovery::runHealthServer(unsigned int port)
124124
}
125125
} catch (std::exception& e) {
126126
mThreadRunning = false;
127-
std::cerr << e.what() << std::endl;
127+
ILOG(Error) << e.what() << ENDM;
128128
}
129129
}
130130

@@ -145,10 +145,10 @@ void ServiceDiscovery::send(const std::string& path, std::string&& post)
145145
response = curl_easy_perform(curl);
146146
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
147147
if (response != CURLE_OK) {
148-
std::cerr << "ServiceDiscovery: " << curl_easy_strerror(response) << ": " << uri << std::endl;
148+
ILOG(Error) << "ServiceDiscovery: " << curl_easy_strerror(response) << ": " << uri << ENDM;
149149
}
150150
if (responseCode < 200 || responseCode > 206) {
151-
std::cerr << "ServiceDiscovery: Response code: " << responseCode << std::endl;
151+
ILOG(Error) << "ServiceDiscovery: Response code: " << responseCode << ENDM;
152152
}
153153
}
154154
} // namespace o2::quality_control::core

0 commit comments

Comments
 (0)