Skip to content

SO 5.8 ByExample Custom Exception Logger

Yauheni Akhotnikau edited this page Jul 7, 2023 · 1 revision

Note. It is better to read SO-5.8 Basics, SO-5.8 ByExample Exception Reaction, and SO-5.8 ByExample Custom Error Logger before this text.

Introduction

This examples demonstrates usage of custom exception logger with SObjectizer Environment.

Some Words About Event Exception Logger

SObjectizer distunguishes errors and exceptions thrown from by event handlers. Errors are negative results of some actions performed by SObjectizer or inside SObjectizer RunTime (such as a problem with delivering a message or inability to start another worker thread). Information about errors is logged by using the error logger. See SO-5.8 ByExample Custom Error Logger as an example.

But an exception thrown from an event handler is a different story. The instance of that exception will be lost anyway (SObjectizer will either terminate the application or discard the exception). If a user wants to log the fact that an exception was thrown, he/she can set a custom event exception logger. SObjectizer will use this exception logger only when SObjectizer catches an exception from an event handler.

What Example Does

The sample implements so_5::event_exception_logger_t interface. It installs an instance of that implementation as an event exception logger for SObjectizer Environment.

To provoke SObjectizer to use the exception logger agent of type a_hello_t throws an exception from its so_evt_start. This exception is intercepted by SObjectizer RunTime and is logged by using the user provided event exception logger. The agent a_hello_t uses so_5::deregister_coop_on_exception exception reaction and it tells the SObjectizer to deregister the coop with the agent that has thrown the exception.

Sample Code

/*
 * A sample of the exception logger.
 */

#include <iostream>
#include <stdexcept>

// Main SObjectizer header file.
#include <so_5/all.hpp>

// A class of the exception logger.
class sample_event_exception_logger_t final
	: public so_5::event_exception_logger_t
{
	public:
		// A reaction to an exception.
		void log_exception(
			const std::exception & event_exception,
			const so_5::coop_handle_t & coop ) noexcept override
		{
			std::cerr
				<< "Event_exception, coop:"
				<< coop << "; "
				" error: "
				<< event_exception.what()
				<< std::endl;
		}
};

// A class of an agent which will throw an exception.
class a_hello_t final : public so_5::agent_t
{
	public:
		a_hello_t( context_t ctx ) : so_5::agent_t( ctx )
		{}

		// A reaction to start work in SObjectizer.
		void so_evt_start() override
		{
			so_environment().install_exception_logger(
				std::make_unique<sample_event_exception_logger_t>() );

			throw std::runtime_error( "sample exception" );
		}

		// An instruction to SObjectizer for unhandled exception.
		so_5::exception_reaction_t so_exception_reaction() const noexcept override
		{
			return so_5::deregister_coop_on_exception;
		}
};

int main()
{
	try
	{
		so_5::launch(
			// SObjectizer initialization code.
			[]( so_5::environment_t & env )
			{
				// Creating and registering cooperation with a single agent.
				env.register_agent_as_coop( env.make_agent< a_hello_t >() );
			} );
	}
	catch( const std::exception & ex )
	{
		std::cerr << "Error: " << ex.what() << std::endl;
		return 1;
	}

	return 0;
}

Sample in Details

Custom Event Exception Logger

Custom event exception logger is implemented as class custom_logger_t in the sample code:

// A class of the exception logger.
class sample_event_exception_logger_t final
	: public so_5::event_exception_logger_t
{
	public:
		// A reaction to an exception.
		void log_exception(
			const std::exception & event_exception,
			const so_5::coop_handle_t & coop ) noexcept override
		{
			std::cerr
				<< "Event_exception, coop:"
				<< coop << "; "
				" error: "
				<< event_exception.what()
				<< std::endl;
		}
};

It is a very simple implementation. The base interface, so_5::event_exception_logger_t has just one pure virtual method -- log_exception(). This method must be reimplemented in descendant classes and sample_event_exception_logger_t does just that.

The log_exception() method has two parameters:

  • event_exception. This is the instance that has been caught by SObjectizer RunTime;
  • coop. This is the handle of the coop to that the problematic agent belongs.

Installing Event Exception Logger into SObjectizer Environment

The custom error logger is installed into SObjectizer Environment by a_hello_t agent:

so_environment().install_exception_logger(
    so_environment().install_exception_logger(
        std::make_unique<sample_event_exception_logger_t>() );

An event exception logger object must be created as dynamically allocated object and must be passed to SObjectizer Environment as std::unique_ptr.

NOTE. A custom event exception logger can also be installed via so_5::environment_params_t:

so_5::launch([](so_5::environment_t & env) {...},
    [](so_5::environment_params_t & params) {
        params.event_exception_logger(
            std::make_unique<sample_event_exception_logger_t>());
    });
Clone this wiki locally