Logging¶
MARTe offers a logging mechanism that is both thread and interrupt safe.
Note
The number of logging messages is expected to be maximised in any MARTe component.
ErrorType¶
The framework offers the following ErrorTypes (i.e. severities, see ErrorType).
Type |
Meaning |
---|---|
FatalError |
An error which is not recoverable. |
RecoverableError |
The component can recover from this error. |
InitialisationError |
Error which occurred during the initialisation of the component. |
OSError |
Operating system error (typically used when developing interfaces to hardware). |
ParametersError |
Initialisation error due to misconfiguration of parameters. |
IllegalOperation |
Operation not possible in a given state. |
ErrorSharing |
Given resource cannot be shared. |
ErrorAccessDenied |
Access denied to a given resource. |
Exception |
Runtime exception triggered. |
Timeout |
Timeout waiting for a given resource. |
CommunicationError |
Communication error (sockets, files, …). |
SyntaxError |
Invalid syntax. |
UnsupportedFeature |
Request for a feature that is not available (possibly available on other states). |
InternalSetupError |
Error due |
Debug |
Debug messages. |
Information |
Information messages. |
Warning |
Warning messages. |
Completed |
ErrorType to be used when a given operation has completed. |
NotCompleted |
ErrorType to be used when a given operation has not yet completed. Usually a retry is expected. |
Log macros¶
The AdvancedErrorManagement defines two main error logging macros.
The REPORT_ERROR_STATIC
is to be called by classes that do not inherit from Object while the REPORT_ERROR
should be called by classes that inherit from Object, since this will automatically add the object name, class name and object pointer to the log message.
Both macros expect a compulsory ErrorType, followed by a compulsory error/information string and a list of optional parameters that will be Printf
in the String using the rules described in the Streams section.
...
REPORT_ERROR(ErrorManagement::Information, "Array set to %f", readVector);
...
Callback¶
The messages are processed by a user registered callback function.
This is set by calling the global function SetErrorProcessFunction
with a pointer to user error handling function.
typedef void (*ErrorProcessFunctionType)(const ErrorInformation &errorInfo, const char8 * const errorDescription);
The errorDescription
already contains the printfed message while the ErrorInformation provides a list of properties related to the conditions at the time of the logging (e.g. time, line number, …).
void ErrorProcessExampleFunction(const MARTe::ErrorManagement::ErrorInformation &errorInfo, const char * const errorDescription) {
...
printf("[%s - %s:%d]: %s\n", errorCodeStr.Buffer(), errorInfo.fileName, errorInfo.header.lineNumber, errorDescription);
printf(RST);
...
LoggerService¶
The framework also offers a data-driven LoggerService which decouples the log production from the log consumption using a decoupling queue.
The LoggerService allows to register one or more LoggerConsumerI components, which will consume the logging message accordingly. Note that the LoggerService
will override any callback function previously set by the user.
The framework currently offers the following consumers: ConsoleLogger, UDPLogger and SysLogger (from the MARTe2-components).
PlainLoggerService¶
In scenarios where the advantages of LoggerService cannot be used (e.g. BareMetal, single core/thread applications), the PlainLoggerService is offered. Conversely to its multi-thread based counterpart, the PlainLoggerService directly intercepts the callback function, handling all the logging function in the same thread execution unit. This approach gives a consistent logging facility also for scenarios where no threading is possible or available, like the BareMetal porting of MARTe2.
LogView utility¶
When using UDPLogger consumer, a viewer counterpart may be needed. A companion tool: MARTe2-LogView offers a convenient way to render the message flow onto a webpage or curses terminal.
MARTe2-LogView is a standalone Python3 toolset which can be found at <https://vcis-gitlab.f4e.europa.eu/common/marte2-logview> with a comprehensive quick-start guide and an in-depth manual.
Tip
A configuration file example is provided (RTApp-11-Logger.cfg) to allow a quick bootstrap with all-default parameters.
Examples¶
The following is an example of a LoggerService instance which prints the logging messages in the console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | /**
* @file LoggerServiceExample1.cpp
* @brief Source file for class LoggerServiceExample1
* @date 04/04/2018
* @author Andre' Neto
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
* @details This source file contains the definition of all the methods for
* the class LoggerServiceExample1 (public, protected, and private). Be aware that some
* methods, such as those inline could be defined on the header file, instead.
*/
#define DLL_API
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ConfigurationDatabase.h"
#include "ErrorLoggerExample.h"
#include "JsonParser.h"
#include "Matrix.h"
#include "Object.h"
#include "ObjectRegistryDatabase.h"
#include "Reference.h"
#include "ReferenceT.h"
#include "StandardParser.h"
#include "StreamString.h"
#include "Vector.h"
/*---------------------------------------------------------------------------*/
/* Static definitions */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Method definitions */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
* @brief A MARTe::Object that will print some logging information.
*/
class LoggerEx1: public MARTe::Object {
public:
CLASS_REGISTER_DECLARATION()
LoggerEx1 () {
using namespace MARTe;
REPORT_ERROR_STATIC(ErrorManagement::Debug, "Constructing an instance of LoggerEx1");
}
virtual ~LoggerEx1 () {
if (GetName() != NULL) {
REPORT_ERROR_STATIC(MARTe::ErrorManagement::Debug, "Destroying an instance of LoggerEx1");
}
}
virtual bool Initialise(MARTe::StructuredDataI &data) {
using namespace MARTe;
bool ok = Object::Initialise(data);
REPORT_ERROR(MARTe::ErrorManagement::Information, "Initialised called");
float32 a;
if (ok) {
ok = data.Read("a", a);
}
if (ok) {
REPORT_ERROR(MARTe::ErrorManagement::Information, "a = %f", a);
}
else {
REPORT_ERROR(MARTe::ErrorManagement::ParametersError, "Could not read the value of a");
}
return ok;
}
};
CLASS_REGISTER(LoggerEx1, "")
}
int main(int argc, char **argv) {
using namespace MARTe;
using namespace MARTe2Tutorial;
//This will be later overridden by the LoggerService
SetErrorProcessFunction(&ErrorProcessExampleFunction);
StreamString configurationCfg = ""
"+LoggerService = {\n"
" Class = LoggerService\n"
" CPUs = 0x1\n"
" StackSize = 32768\n"
" NumberOfLogPages = 128\n"
" +ConsoleLogger1 = {\n"
" Class = ConsoleLogger\n"
" Format = \"EtOoFmC\"\n"
" PrintKeys = 1\n"
" }\n"
"}"
"+LEx1 = {\n"
" Class = LoggerEx1\n"
" a=5.3\n"
"}\n"
"+LEx2 = {\n"
" Class = LoggerEx1\n"
" a = 2"
"}\n";
REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s",
configurationCfg.Buffer());
ConfigurationDatabase cdb;
StreamString err;
//Force the string to be seeked to the beginning.
configurationCfg.Seek(0LLU);
StandardParser parser(configurationCfg, cdb, &err);
bool ok = parser.Parse();
if (ok) {
//After parsing the tree is pointing at the last leaf
cdb.MoveToRoot();
ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
}
else {
StreamString errPrint;
errPrint.Printf("Failed to parse %s", err.Buffer());
REPORT_ERROR_STATIC(ErrorManagement::ParametersError,
errPrint.Buffer());
}
if (ok) {
REPORT_ERROR_STATIC(ErrorManagement::Information,
"Successfully loaded the configuration file");
}
//Purge all the Objects!
MARTe::ObjectRegistryDatabase::Instance()->Purge();
return 0;
}
|
Instructions on how to compile and execute the example can be found here.