Tools
Logging
FairMQ logs with the library FairLogger. This page shows the log macro, the severities that FairMQ uses, and the options that control the console log and the log file.
Write a log line
Section titled “Write a log line”FairMQ needs FairLogger 1.6.0 or newer (cmake/FairMQDependencies.cmake). Write a log line with the macro
LOG(severity) and the operator <<:
bool ConditionalRun() override{ // create a copy of the data with new(), that will be deleted after the transfer is complete std::string* text = new std::string(fText);
// create message object with a pointer to the data buffer, its size, // custom deletion function (called when transfer is done), // and pointer to the object managing the data buffer fair::mq::MessagePtr msg(NewMessage( const_cast<char*>(text->c_str()), text->length(), [](void* /*data*/, void* object) { delete static_cast<std::string*>(object); }, text));
LOG(info) << "Sending \"" << fText << "\"";
// in case of error or transfer interruption, return false to go to the Ready state // successfull transfer will return number of bytes transfered (can be 0 if sending an empty message). if (Send(msg, "data") < 0) { return false; } else if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations) { LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state."; return false; }
return true;}<fairmq/Device.h>includes<fairlogger/Logger.h>. Thus the code of a device can useLOG()without an include.- In other files, include
<fairlogger/Logger.h>. - The old header
<fairmq/FairMQLogger.h>gives the compiler warningDeprecated header: Use <fairlogger/Logger.h> instead. Replace it with<fairlogger/Logger.h>.
Severities
Section titled “Severities”The option --severity names these severities, from the most lines to the fewest:
| Severity | FairMQ uses it for | Example from the code |
|---|---|---|
trace |
Internal steps of the device and of the plugins. | device notified on new state: BINDING |
debug |
Details of the setup: plugins, transports, channels and the configuration. | Attached channel data[0] to tcp://*:5555 (bind) (push) |
info |
Normal messages of FairMQ and of your device. | fair::mq::Device running... |
state |
State changes of the state machine. | IDLE ---> INITIALIZING DEVICE |
warn |
Problems that do not stop the device. | No channels created after finishing initialization |
error |
Errors, for example an exception that ends the device. | Uncaught exception reached the top of main: … |
fatal |
FairMQ does not use it. |
A severity shows its own lines and the lines of all severities after it in the table. For example, --severity debug
shows all lines of the table except trace. The value nolog turns the console log off. FairLogger still prints the
fatal lines.
FairLogger knows more severities, for example debug1 to debug4, detail, important, alarm and critical.
FairMQ does not use them. For a name that FairLogger does not know, it logs
Unknown severity setting: '…', setting to default 'info'. and uses info.
The severity state
Section titled “The severity state”The state machine logs each change of state with the severity state
(StateMachine.cxx). The key c of the interactive control mode also
logs the current state with this severity. Thus --severity state shows the states, the warnings and the errors,
without the info lines. The state lines are in Device states.
Set the log with options
Section titled “Set the log with options”DeviceRunner reads these options after it parses the command line. Thus they work for all devices that start with
runDevice.h.
| Option | Default | Description |
|---|---|---|
--severitystring | "" | Console log severity: trace, debug, info, state, warn, error, fatal or nolog. Empty: keep the default of FairLogger. The environment variable FAIRMQ_SEVERITY overrides this option.ProgOptions |
--file-severitystring | debug | Log severity for the log file of --log-to-file.ProgOptions |
--verbositystring | medium | Log verbosity: veryhigh, high, medium or low. It sets the fields in each log line.ProgOptions |
--colorbool | true | Use colors in the console log.ProgOptions |
--log-to-filestring | "" | Write the log to this file. The console log is then off.ProgOptions |
| No option matches. Clear the filter or choose All. | ||
- With
--severity ""(default), the device does not set the console severity. The default of FairLogger then applies. - The environment variable
FAIRMQ_SEVERITYreplaces the value of--severity. --verbositysets the fields of each log line. The help text namesveryhigh,high,medium(default) andlow. See The verbosity.--color falseremoves the colors from the console log.--helpand--print-optionsprint to the standard output, without the logger. The log options have no effect on them.
This command starts the sink with the debug lines on the console:
FAIRMQ_SEVERITY=debug fairmq-sink --id sink1 \ --channel-config name=data,type=pull,method=bind,address=tcp://*:5555The verbosity
Section titled “The verbosity”The verbosity sets the prefix of each log line. A space separates the prefix from the message.
--verbosity |
Prefix |
|---|---|
low |
[SEVERITY] |
medium (default) |
[HH:MM:SS][SEVERITY] |
high |
[process][HH:MM:SS][SEVERITY] |
veryhigh |
[process][HH:MM:SS.uuuuuu][SEVERITY][file:line:function] |
process is the name of the program, for example fairmq-sink. uuuuuu are the microseconds. The severity is in
upper case, for example INFO or STATE. With medium, a state line looks so:
[14:03:21][STATE] IDLE ---> INITIALIZING DEVICEFairLogger also knows verylow (no prefix) and user1 to user4. For a name that FairLogger does not know, it logs
Unknown verbosity setting: '…', setting to default 'low'. and uses low. The log file gets the same prefix as the
console, without colors.
Write the log to a file
Section titled “Write the log to a file”--log-to-file <name> starts a file log with the severity of --file-severity (default debug). The device gives
<name> to fair::Logger::InitFileSink(), and FairLogger creates the file.
With --log-to-file, the console log is off: the device sets the console severity to nolog. Thus --severity,
FAIRMQ_SEVERITY and --color have no effect.
fairmq-sink --id sink1 \ --channel-config name=data,type=pull,method=bind,address=tcp://*:5555 \ --log-to-file sink1 --file-severity traceChange the log at run time
Section titled “Change the log at run time”DeviceRunner subscribes to the log properties (DeviceRunner.cxx).
When a plugin or the device changes one of them, the new value applies at once:
| Property | Type | Effect of a change |
|---|---|---|
severity |
std::string |
Sets the console severity. |
file-severity |
std::string |
Sets the severity of the log file. |
verbosity |
std::string |
Sets the verbosity. |
color |
bool |
Turns the console colors on or off. |
log-to-file |
std::string |
Starts a file log with the value of file-severity. The console log stays on. |
Give the type to SetProperty(). The subscription gets only values of the type in the table:
// In a plugin: show the debug lines from now on.SetProperty<std::string>("severity", "debug");SetProperty("severity", "debug") stores a const char*, and the severity does not change. See
Read and change properties at run time.
Keys and plugin functions
Section titled “Keys and plugin functions”- In the interactive mode of the control plugin, the key
kmoves the console severity one step up, towardfatal. The keylmoves it one step down, towardtrace. The steps include the severities that FairMQ does not use. At the end of the list, the next step goes to the other end. The keysnandmmove the verbosity one step up or down in the same way. FairLogger prints the list of values and marks the new value with<and>. See Keys of the interactive mode. - A plugin can call
CycleLogConsoleSeverityUp(),CycleLogConsoleSeverityDown(),CycleLogVerbosityUp()andCycleLogVerbosityDown(). The keys call these functions. - The keys and the
CycleLogfunctions change FairLogger directly. The propertiesseverityandverbositykeep their old values.
Set the log in your code
Section titled “Set the log in your code”Your code can call the functions of FairLogger directly. The custom-controller example sets the console severity before the runner starts:
DeviceRunner runner(argc, argv);
runner.AddHook<hooks::LoadPlugins>([](DeviceRunner& r) { r.fPluginManager.LoadPlugin("s:mycontroller"); // 's:' stands for static because the plugin is compiled into the executable // 'mycontroller' is the plugin name passed as second arg to REGISTER_FAIRMQ_PLUGIN});
fair::Logger::SetConsoleSeverity(fair::Severity::debug);With the default --severity "", DeviceRunner keeps this value. A program without DeviceRunner reads no log
options and subscribes to no log properties. It must call these functions itself. FairMQ calls these functions of
fair::Logger:
| Function | FairMQ uses it for |
|---|---|
SetConsoleSeverity() |
--severity, FAIRMQ_SEVERITY and nolog for a log file. |
SetFileSeverity() |
A change of file-severity at run time. |
InitFileSink(severity, name) |
--log-to-file. |
SetVerbosity() |
--verbosity. |
SetConsoleColor() |
--color. |
CycleConsoleSeverityUp(), CycleConsoleSeverityDown(), CycleVerbosityUp(), CycleVerbosityDown() |
The CycleLog functions of the plugin API. |
Add a sink
Section titled “Add a sink”A custom sink is a function of your code that gets each log line, for example to send the lines to a log server.
FairLogger adds and removes sinks with static functions of fair::Logger. FairMQ does not call them. FairLogger is
not part of this repository: these declarations are from logger/Logger.h of FairLogger. They are the same in
FairLogger 1.6.0, the minimum version of FairMQ, and in the current source of
FairLogger:
static void AddCustomSink(const std::string& key, Severity severity, std::function<void(const std::string& content, const LogMetaData& metadata)> sink);static void AddCustomSink(const std::string& key, const std::string& severityStr, std::function<void(const std::string& content, const LogMetaData& metadata)> sink);static void RemoveCustomSink(const std::string& key);keyis the name of the sink.RemoveCustomSink()takes the same name.- The sink gets the lines of
severityand of all more severe levels. It always gets thefatallines. For a severity name that FairLogger does not know, it logsUnknown severity setting: '…', setting to default 'info'.and usesinfo. contentis the text of the line, without the prefix of the verbosity.metadatais afair::LogMetaDatawith the fieldstimestamp(std::time_t),us(the microseconds of the second,std::chrono::microseconds),process_name,file,line,func,severity_nameandseverity(fair::Severity). The text fields arestd::stringin FairLogger 1.6.0 andstd::string_viewin the current source. Copy them into astd::stringif your sink keeps them.- The sink is independent of the console and of the log file.
--severity nologand--log-to-filedo not change it. - For a key that exists,
AddCustomSink()of the current FairLogger throwsstd::runtime_error. For a key that does not exist,RemoveCustomSink()also throwsstd::runtime_error. FairLogger 1.6.0 prints a message to the standard output instead and changes nothing.
This program adds a sink for the warnings and errors before the runner starts, and removes it after the runner is
destroyed. MyDevice is your device class:
#include <fairlogger/Logger.h>#include <fairmq/DeviceRunner.h>
#include <iostream>#include <memory>#include <string>
int main(int argc, char* argv[]){ fair::Logger::AddCustomSink("my-sink", "warn", [](const std::string& content, const fair::LogMetaData& metadata) { std::cerr << "sink: " << metadata.severity_name << " " << content << '\n'; });
int result = 0; { fair::mq::DeviceRunner runner(argc, argv); runner.AddHook<fair::mq::hooks::InstantiateDevice>([](fair::mq::DeviceRunner& r) { r.fDevice = std::make_unique<MyDevice>(); }); result = runner.RunWithExceptionHandlers(); } // destroys the plugins and the device
fair::Logger::RemoveCustomSink("my-sink"); return result;}Rules for a sink:
- FairLogger calls the sink at the end of each
LOG()statement, in the thread of the statement. It holds a global mutex of the logger during the call. Thus only one sink call runs at a time. A slow sink also delays the other threads that write to a sink or to the log file. Keep the sink short. - Do not write log lines in the sink. A
LOG()statement in the sink that goes to a sink or to the log file locks the mutex again, and the thread waits forever. AddCustomSink()locks the mutex, butRemoveCustomSink()does not, and theLOG()statements read the list of sinks without the mutex. Add and remove sinks only while no other thread logs. WithrunDevice.h, add the sink ingetDevice()or inaddCustomOptions(). Both run in the main thread before the plugins and the state machine start.- A sink that stays until the end of the process must not use objects that are destroyed before, for example your device.
- A sink with a low severity, for example
trace, makes FairLogger prepare the lines of this severity for eachLOG()statement, also when the console does not show them.
Other programs
Section titled “Other programs”fairmq-shmmonitorhas its own option--severity(defaultinfo), and no colors. See fairmq-shmmonitor.- FairMQ prints the output of
--print-channelsand--versionwithLOGV(info, verylow).LOGV(severity, verbosity)is a log macro of FairLogger that also takes a verbosity.
Related pages
Section titled “Related pages”- Command-line options: all options of a device.
- Device states: the state machine and its log lines.
- Plugins and control: the control plugin and its keys.
- Control a device from code: change properties at run time.