Errors
Introduction
COREmanager libraries actively use the exception mechanism. The system architecture implies highly nested calls, and exceptions are an easy way to deliver error information. When writing your own components, follow the rules below:
- Never suppress exceptions raised by internal calls to isp_api::InternalCall. This may lead to system instability due to some of query processing operations that were not executed completely. If you have detected an error, but still want to try completing the call, use the mechanism of re-executing the call isp_api::RestartRequest.
- Never trap exceptions without the catch (...) type or throughout the exception throw /** without parameters */;
- Always pass the language or session when making internal or external requests. This will allow you to receive an error message in a localized form.
Types of exceptions
Exceptions in COREmanager libraries can be classified based on their processing algorithm:
Exceptions mgr_err::Error
Practically all of the exceptions in COREmanager libraries belong to the mgr_err::Error type. This exception type is inherited from std::exception. If you to trap all exceptions,it is better to trap mgr_err::Error or std::exception. In COREmanager, we do not use exception typing. Firstly, exceptions may occur in case of remote requests, and their serialization and deserialization sometimes is impossible (local version of COREmanager that received an exception from a remote service may simply not contain a required class of exceptions). Secondly as practice shows, there is no need in typification of exceptions (99% of all catches is catch(const mgr_err::Error &) or catch(const std::exception &)).
This class contains a stack status at the time the exception occurred and an XML document describing the type of exception. An the XML example:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<error type="xml" object="xpath" report="yes" lang="ru">
<param name="object" type="msg" msg="Error in XPath '__value__'">xpath</param>
<param name="value">bad XPath</param>
<stack>
<action level="30" user="root">xmlerror</action>
</stack>
<group>An error when working with the XML-document. __object__</group>
<msg>An error occurred when working with the XML-document. Error in XPath 'bad XPath'</msg>
</error>
</doc>
Attributes and child nodes of the error node:
external attribute: "yes" indicates an exception from a remote service. Such exceptions require no special processing.
report attribute: "yes" indicates that a report should be sent to software developers. Such exceptions should not be sent to users. If a user does get it, he will be asked to inform developers.
help attribute: if specified, an error message will contain a link to documentation. The article name will be taken from the attribute value.
type attribute: exclusion type - string in any format. Used for locales.
lang attribute: localization language.
object attribute: value of the object parameter.
value attribute: value of the value parameter.
param node: exception parameter. It has the following parameters: @name - parameter name, @type - parameter type (must have the "msg" value for localization parameters), @msg - localized value. Parameter's value is taken from the node.
stack node: call stack isp_api::InternalCall at the time the exception occurs. Each child node action contains the @level and @user attributes, which are user role and username who performed the operation. A function name is specified in the action node.
detail, group and default nodes: localized description of an exception.
msg node: composed localized description of an exception.
Localization
Classes of exceptions
Though we do not use typification of exceptions, not all exceptions are processed in the same way. In COREmanager libraries, they are classified only on the error node attributes. Groups classified according to processing type are listed below:
Function errors (local errors). Such errors are caused by incorrect system settings or invalid parameters. They should provide all the required information to users.
Special errors. Similar to the errors described above, however they are processed differently. Example: notconfigured. In the case of the API request (out=xml), this error will return to users in the same way as errors described above. If an error occurs when accessing the panel through web interface, a user will be asked to provide missing data. This group also include authorization errors. If they occur in the web interface, a user will be redirected to the registration form.
Library errors. Can be caused by insufficient resources or it can can be algorithmic errors, if a developer uses some library function incorrectly. If such errors occur, a report to developers will be generated (the report attribute).
Errors from remote services. Errors from remote services running on COREmanager. Their xml can be similar to that of any other error. No special processing is required (the external attribute)
Service exceptions
Except for mgr_err::Error, COREmanager uses a number of exceptions that are inherited neither form mgr_err::Error, nor form std::exception. Such errors should never be cought by users.
Assert critical error. This error class should never occur. If it does occur, any further operation may be useless or dangerous. This type of exceptions is created by the ASSERT macros. As opposed to standard Assert, it will terminate not an application, but the current string. COREmanager will try to roll back all changes made while the process was running.
Restart exception requires to process the request once again. This type of exceptions is used by the isp_api::RestartRequest function.
Skip informs that there is no need in further processing of the request. A user will receive the response as it was at the time this exception occurred.
Error localization
Errors may be localized differently depending on the access level of a user who will see it. The first step is to search for a message with the __XX suffix, where XX is a number, the minimum access level a user must have to see it. If no suitable message is found, the message without the suffix is used.
For example, a user with access level 16 receives an error, a message named *msg_error_some_error* can be used to localize it. Messages with names from *msg_error_some_error16* to *msg_error_some_error1* will first be checked sequentially. If none of them are found, the message named *msg_error_some_error* will be used.
In case a user works under another user's account (su function), the access level for generating the error message will be taken from the first user in the chain (the one he/she logged into the panel under). Thus, an administrator working with user permissions and a user logged into the control panel can see different messages for the same errors.
When localizing an error, COREmanager is trying to find corresponding messages searching message sections as follows:
- mgrerror_
- All the message sections starting with the last one (the function causing that error). There can be several sections, if the the error occurred while performing an internal call isp_api::InternalCall
- mgrerror
In those section COREmanager will search for corresponding values of the msg parameters and the following messages:
- msg_error__
- msg_error_
- msg_error_unknown
To form a message that a user will see, the most appropriate one will be used - (msg_error_<type>_<object> has the highest priority). Then, in the resulting string, all substrings __<name>__ corresponding to parameters with type msg will be replaced by their localized value. And then, all substrings __<name>__ corresponding to other parameters as well.
For example, when using database built-in mechanisms, if you were unable to add a record into the database because it already exists, the "exists" error will be dispayed containing names of duplicated fields (separated with a comma). To localize that error, add the following message: msg_error_exists_<table_name>
А message text may look like: __cols__ with the __value__ value already exists.