Web Service Development Guide : PART IV Extending your Applications : Chapter 12 Web Service Logging : Logging in Client Code
Logging in Client Code
For client-side and standalone server logging (“Logging in a Standalone Service” ), use the Web service logger. This logger is implemented as a message handler and invoked statically via the rwsf::HandlerManager class. The simplest way to log a message in the client is to invoke the logger with a string and an optional log level describing the severity of the message:
 
#include <rwsf/webservice/HandlerManager.h> // required include
 
rwsf::HandlerManager::invokeLogger("This is an info message");
 
rwsf::HandlerManager::invokeLogger("This is a warning message",
rwsf::CallInfo::Warning);
In client code, the invokeLogger() method uses the logger defined in the client-handlers.xml file. If no logger configuration is found, then logging defaults to the default log file, webservice.log, located in your <installdir>\logs directory. This logger logs only messages at the Fatal or Error level, however.
To implement logging in the client
Configure a logger in the client-handlers.xml file. The design of using a configuration file allows you to change the logging level and the output file name at runtime, without having to recompile your code.
Load and define the logger from within your client code.
This process is described in detail in “Configuring and Using a Client Logger” .
By default, the code generator automatically creates a logger handler and places its configuration in the generated conf/client-handlers.xml file. The client code then loads the configuration using the loadConfiguration() method:
 
rwsf::HandlerManager::loadConfiguration("../conf/client-handlers.xml");
If you undefine the logger by commenting out the above line in the generated client implementation or removing the logger element in the client-handlers.xml, then only Error and Fatal messages are logged to the webservice.log file.
Configuring and Using a Client Logger
HydraExpress sample clients all feature loggers that are configured in the way described in this section.
The client logger is configured in the file client-handlers.xml located by default in the project’s generated conf directory:
 
<configuration>
<logger name="RWSFClientLogger">
<property name="filename" value="client.log"/> <!-- if not defined, writes to stdout -->
<property name="level" value="Info"/>
</logger>
<!-- service definitions, if any -->
</configuration>
The output from this logger is written to the file client.log in the directory where the client is invoked. If the filename property is omitted, log messages are written to stdout.
Note that the level is set at Info, which means all messages are reported.
At startup, the line of code below loads the configuration file and rwsf::HandlerManager is initialized with the logger.
 
rwsf::HandlerManager::loadConfiguration("../conf/client-handlers.xml");
NOTE >> Note that if the logger is invoked in your code before the handlers configuration file is loaded, no logging occurs.
Finally, for loadConfiguration() to be successful, a static message handler with the logger name from the configuration file must be defined. You accomplish this by placing the macro shown below in the client implementation file at file scope. Note the use of the provided DefaultLogger class to carry out the actual logging.
 
using rwsf::DefaultLogger;
RWSF_DEFINE_STATIC_MESSAGE_HANDLER("RWSFClientLogger", DefaultLogger)
Now let’s put it all together. Here is an excerpt from client code that invokes a logger:
 
#include <rwsf/webservice/HandlerManager.h> //1
...
using rwsf::DefaultLogger; //2
RWSF_DEFINE_STATIC_MESSAGE_HANDLER("RWSFClientLogger", DefaultLogger)
...
rwsf::HandlerManager::loadConfiguration("../../conf/client-handlers.xml"); //3
rwsf::HandlerManager::invokeLogger("This is a warning message", //4
rwsf::CallInfo::Warning);
//1 Required include
//2 Define the static message handler for logging
//3 Load the logger configuration file
//4 Invoke the logger, in this case setting it to the non-default Warning level. Note that the generated code does not include this line, although it includes the previous three.
Logging in a Standalone Service
You also use the Web service logger for logging from within a standalone server. A standalone service is deployed independent from the Agent and is created by generating service code using the -standalone option. This option results in the generation of a sample server, MyServiceServer.cpp in the app\server directory. Implement logging in this file. For more information on standalone servers in general, please see “Standalone Server Implementations.”
Logging from a standalone server is similar to logging from within client code, with the additional step of defining a logging element in the <servicecontextname>_handlers.xml file which can then be loaded and defined in the standalone server just as in the client. Note that logging is not generated by default in a standalone server implementation.
For example, if you were to generate a standalone server for the example DayofWeek, the app\server directory would contain a DayOfWeekPortServer.cpp file.
To implement logging for the DayofWeek standalone server:
1. Define the logger in the generated dayofweek_handlers.xml, similar to that defined in the client-handlers.xml file.
2. Load it and invoke it from the DayofWeekPortServer.cpp file.
These steps are exactly the same as those for the client, described in detail in “Configuring and Using a Client Logger” .