When you start writing code (i.e. plugin) called from a larger system (i.e. Nx Witness Server), one of the first tasks is to print something out. This section discusses options for logging.
Nx Witness Server has its own advanced logging subsystem which writes logs to files but is currently unavailable for the plugins. These logs can be used to investigate issues with Plugins as they are seen from the Server side. Refer to VMS logging to learn how to obtain the Server logs and set their logging levels.
On Windows, the Server main log opens from the menu of Nx Witness Server’s System Tray icon. On Linux, the default location of the Server main log (for the default Nx Witness installation) is at /opt/networkoptix/var/log/log_file*.log
, unless it's changed via Server settings (e.g. due to the specifics of the particular platform).
Nx Witness Server runs as a process in the OS. A Plugin is a dynamic library that works as a part of the Server process. The Plugin's code becomes a part of the Server code segment, and they interact simply by calling each other’s functions.
A process has its own standard output streams, a regular output stream (stdout), and an error output stream (stderr). Any code in the process, including the code in a Plugin’s dynamic library, has the inherent ability to output to these streams.
The following are options for logging from a Plugin:
- Print to stdout and/or stderr.
- One such helper is included with the SDK, as part of its nx_kit library (nx/kit/debug.h), and is described below. This approach is used in the plugin samples included with the SDK.
- This can be done via standard C++ ways like cout or printf(), or using some helper library which effectively does the same but offers additional conveniences like logging levels and forming a context-denoting prefix to each log message — which describes from which module, class, or function the message has been printed.
- Use its own logging subsystem.
- This approach requires a lot of effort if writing from scratch, and can be recommended only if you have your own library, or can find a suitable third-party one, that offers this feature; or if you use this in addition to the one in nx_kit.
Logging via nx_kit
The idea of logging via nx_kit is simple — there are a couple of macros in nx/kit/debug.h that mainly just print the message to stderr. These macros can be considered to form two log levels: a regular one, and a verbose one:
- NX_PRINT — prints the message to stderr, unconditionally. Consider it a regular log level.
- NX_OUTPUT — prints the message only if the configuration allows. Consider it a verbose log level.
- Here, the meaning of configuration can be defined via defining the macro NX_DEBUG_ENABLE_OUTPUT before including nx/kit/debug.h (the value of this macro must be a boolean);or relying on its default definition being the expression ini().enableOutput — this is the integration with the other nx_kit mechanism, IniConfig.
Both macros differ from std::cerr by offering additional usability:
- The message is automatically finished with a newline without the need to specify the final \n.
- A prefix is added to the message, constructed as follows: if a macro NX_PRINT_PREFIX is defined before including nx/kit/debug.h, its value is used as a prefix; if not, the prefix is calculated from the file name of the file that includes nx/kit/debug.h.
The stderr is chosen as the default stream because the messages directed to stderr are not buffered and, when written from different threads simultaneously, are less likely to collide and intersect. However, this stream can be changed to something else — see the Doxygen documentation for nx/kit/debug.h.
Example
// my_module.cpp
#define NX_DEBUG_ENABLE_OUTPUT true
#include <nx/kit/debug.h>
void func()
{
// Note no need for the final `\n`.
NX_PRINT << "Printed unconditionally.";
NX_OUTPUT << "Printed only if NX_DEBUG_ENABLE_OUTPUT is true.";
}
Output:
[my_module.cpp] Printed unconditionally.
[my_module.cpp] Printed only if NX_DEBUG_ENABLE_OUTPUT is true.
Switching log level via a .ini file
To easily switch the log level in runtime, we recommend using the IniConfig mechanism of nx_kit (for details, see Configuring via .ini files – IniConfig). All you need to do is to add a boolean flag, called enableOutput, to your .ini options:
// my_module_ini.h
#include <nx/kit/ini_config.h>
struct Ini: nx::kit::IniConfig
{
Ini(): IniConfig("my_module.ini") { reload(); }
NX_INI_FLAG(0, enableOutput, "Whether to produce verbose log on stderr.");
};
inline Ini& ini()
{
static Ini ini;
return ini;
}
// my_module.cpp
#include "my_module_ini.h"
#include <nx/kit/debug.h>
void func()
{
NX_OUTPUT << "Printed only if my_module.ini contains the line: enableOutput=1";
}
Redirecting stderr and stdout to files – OutputRedirector
Regardless of how the messages appear on stdout and/or stderr, it may be useful to capture all the output of a process into files. This is possible via nx_kit using its feature called OutputRedirector. It works fully automatically, any executable which uses the nx_kit library automatically inherits this capability.
This mechanism works in both Windows and Linux. It is especially useful in Windows when running Nx Witness Server as a service, as it seems there is no other way to see its output.
On Linux, there is a standard way to view the output of a service, though it may be less convenient than using OutputRedirector. If you are using a default Nx Witness installation, the command will look like:
journalctl -u networkoptix-mediaserver.service
Here networkoptix-mediaserver is the name of the VMS Server executable, which may be different if you are using a VMS installation other than Nx Witness.
On Linux, to see the Server's stderr and stdout in the console:
- Start Nx Witness Server from the console (as opposed to starting it as a service)
- Navigate to the directory containing the installed Server executables
- Run the Server executable with the option -e:
networkoptix-mediaserver/bin/mediaserver -e
The above method does not work in Windows, when starting Nx Witness Server manually from the console, its output is not shown. To see it, you may use the OutputRedirector mechanism, as shown below.
The redirection is performed as follows:
- Open the .ini files folder of the process (to determine the path to this folder, refer to Configuring via .ini files – IniConfig)
- Create one or two of the following files, leaving them empty:
<executable-name-without-extension>_stdout.log
<executable-name-without-extension>_stderr.log
When the process starts, OutputRedirector takes control before everything else, and checks whether such files exist; if any of them exist, it redirects the respective output stream to the file. On each process start, the file is rewritten (the contents from the previous start is deleted).
For details about using this mechanism in your own applications, refer to the Doxygen documentation for nx/kit/output_redirector.h.
Example
To capture all output of Nx Witness Server being run as a service in Ubuntu Linux, issue the following commands:
sudo touch /home/networkoptix/.config/nx_ini/mediaserver_stdout.log
sudo touch /home/networkoptix/.config/nx_ini/mediaserver_stderr.log
Then restart Nx Witness Server:
sudo service /opt/networkoptix restart
And watch its stderr output from the file:
tail -F /home/networkoptix/.config/nx_ini/mediaserver_stderr.log
In your case, the path to these .log files can be different — see Configuring via .ini files – IniConfig.
Note: currently, the OutputRedirector mechanism doesn’t work on Windows (stdout and stderr are lost) when a Plugin is built using the Debug build configuration.
Comments
0 comments
Article is closed for comments.