Programming Reference:Debug Output
When writing your own BCI2000 module, you will sometimes want to report values of variables, execution of a certain function, or other information that is
- irrelevant to the user, but
- helps you check whether your code does what it is supposed to.
Often, programmers use individual log files for debugging output, and review those files while their program runs, or afterwards.
This page describes how the BCI2000 C++ framework allows you to easily display debugging information in the operator module's log window, without bothering about creating your own log file. Nevertheless, you are free to use your own log file if you feel that this better fits your needs.
Debugging Stream bcidbg
Similar to the bcierr and bciout streams used for error handling and user warnings, BCI2000 provides a std::ostream derived object that accepts strings and numbers for formatted output. Like the output of bcierr and bciout, data from bcidbg is directed into the operator module's log window. Similar to error and warning messages, debugging messages will be time stamped and provided with a function context.
However, there are important differences:
- Unlike for bcierr, the framework does not interpret the fact that something was written to the stream.
- bcidbg can conditionally ignore the data inserted into it, according to a user-defined global setting. That way, you need not remove your debugging code, nor devise your own conditional output scheme.
- Messages are formatted unobtrusively, and will not automatically pop up the operator module's log window.
The bcidbg stream is available globally, and used as any other std::ostream descendant:
#include "BCIError.h" ... mSomeDataMember = SomeFunction(); bcidbg << "Set mSomeDataMember to " << mSomeDataMember << endl;
Note that, just as for bcierr and bciout, writing to bcidbg will not take effect unless it is flushed by inserting flush or endl. (The latter will insert a newline character before flushing the stream.)
The Debug Level
A Debug Level concept is used to control the output of debug messages. Basically, a user-specified debug level is compared to the debug levels of individual messages, and messages with a debug level above the user-specified debug level will be suppressed from the output. As the debug level defaults to 0, no debug messages will be visible to an end user unless configured accordingly.
Individual messages are associated with a numerical value, their Debug Level, depending on their significance. Important and sparse messages are given a low debug level value, less important and probably more frequent messages are given a higher debug level.
Message Debug Level
The default message debug level is 1.
bcidbg << "This is an important message on any level of debugging" << endl;
To give a message a higher debug level, put the level in brackets after the bcidbg name:
bcidbg( 10 ) << "This is a fairly uninteresting message" << endl;
Although there is practically no upper limit to debug level values, a usual range for debug levels is from 1 to 10.
Global Debug Level
The amount of actual debugging output is governed by a global debug level. In BCI2000, this value is corresponds to the DebugLevel parameter. This parameter is not normally available, and must be specified from the command line when starting a module:
FeedbackDemo 127.0.0.1 --DebugLevel=10
will start the FeedbackDemo module with a debug level of 10.
Note that the debug level parameter will propagate to the other modules only after "Set Config" has been pressed from the operator module. Thus, other modules must be started with the DebugLevel argument, as well, if you need to view debugging messages from operation phases prior to the Initialization Phase.
Logging into Files
Debug messages may be logged into files residing in data directories, along with data files. This behavior is governed by the DebugLog parameter. As in the case of the DebugLevel parameter, this parameter must be specified from the command line when starting a module:
FeedbackDemo 127.0.0.1 --DebugLevel=10 --DebugLog=1
will enable debug messages, and log them to files.
Debug log files carry the name of the corresponding run file, and a .dbg extension.
Note: Data files are written by the source module; debug log files are maintained by the operator module. When source and operator module do not reside in the same directory, and the DataDirectory parameter contains a relative path, this path will be resolved differently by the two modules, and data and log files will not be located in a common directory.