Functions

Short snippets on this page show only the LogThat calls; longer ones are written inside the routine they belong in. Application variables are left undeclared unless a rendered output comment depends on them. Snippets that write a log entry from a cyclic body are guarded on an edge flag, because a log entry is a one-shot event. The function blocks are different: logStateChange and logDelete are called every scan by design, and do their own edge or completion handling.

createLogInit

Creates a user logbook. This function may only be called from an _INIT routine. It calls the underlying ArEventLogCreate once and returns that call’s status rather than polling the function block to completion. ArEventLogCreate is documented asynchronous, but in _INIT it completes within that single call, so the logbook is usable by the time the next statement runs and the status is the final result.

Direction Name Type Description
In loggerName STRING[LOG_STRLEN_LOGGERNAME] Name of the logbook to create. Maximum 8 characters, must not be empty.
In size UDINT Size of the log data area in bytes, 4096 minimum. 0 uses LOG_DEFAULT_LOGGERSIZE (100000).
In persistence LOG_PERSISTENCE_enum Where the entries are stored
Return status DINT 0 on success, otherwise a status value
void _INIT ProgramInit(void)
{
	createLogInit("App", 100000, LOG_PERSISTENCE_PERSIST);
}

If a logbook with the same name already exists, the create reports arEVENTLOG_ERR_LOGBOOK_EXISTS and the existing logbook is untouched. If the name collides with a task, program, or other module, it reports arEVENTLOG_ERR_MODULE_EXISTS and no logbook is created. See Choosing a name in Usage.

logError

Writes an entry with error severity.

Direction Name Type Description
In loggerName STRING[LOG_STRLEN_LOGGERNAME] Name of the logbook to write to
In errorID UINT User-defined code written into the event ID
In errorString STRING[LOG_STRLEN_MESSAGE] Message text, optionally containing format specifiers
In pMsgData UDINT Address of a StrExtArgs_typ with the format arguments, or 0 for none
Return status DINT 0 on success, otherwise a status value
logError("App", 200, "Drive fault, machine stopped", 0);

logWarning

Writes an entry with warning severity. Arguments are identical to logError.

void _CYCLIC ProgramCyclic(void)
{
	unsigned short errorCount = 2;

	StrExtArgs_typ msgData;

	if (faultEdge) {
		memset(&msgData, 0, sizeof(msgData));
		msgData.i[0] = errorCount;

		logWarning("App", 100, "Infeed reported %i faults", (UDINT)&msgData);
		// -> "Infeed reported 2 faults"
	}
}

logInfo

Writes an entry with informational severity. Arguments are identical to logError.

logInfo("App", 0, "Machine started", 0);

logSuccess

Writes an entry with success severity. Arguments are identical to logError.

logSuccess("App", 10, "Recipe loaded", 0);

logEventID

Writes an entry using a complete event ID instead of a severity and code pair. Use this to forward an event ID produced elsewhere.

Direction Name Type Description
In loggerName STRING[LOG_STRLEN_LOGGERNAME] Name of the logbook to write to
In eventID DINT Event ID containing severity, facility, and code
In eventString STRING[LOG_STRLEN_MESSAGE] Message text, optionally containing format specifiers
In pMsgData UDINT Address of a StrExtArgs_typ with the format arguments, or 0 for none
Return status DINT 0 on success, otherwise a status value
logEventID("App", forwardedEventID, "Forwarded event", 0);

Note: LogThat sets the customer bit on the event ID before writing. ArEventLog rejects system event IDs written from user code.

logEventID and logSuccess postdate the severity functions, which is why LogThat.fun carries a Legacy comment above logWarning, logError, and logInfo. That comment is a note about their age rather than their status: they are the same thin wrappers over the internal write that logSuccess is, and remain the usual way to write an entry.

logStateChange

Function block that monitors a state value and writes a log entry whenever it changes. Call it cyclically.

Direction Name Type Description
In LoggerName STRING[LOG_STRLEN_LOGGERNAME] Name of the logbook to write to. If empty on the first call, the literal string "State" is written back into this input, once only.
In ModuleName STRING[LOG_STRLEN_MODULENAME] Name of the module being monitored, used in the message. If empty on the first call, the literal string "State" is written back into this input, once only.
In State UDINT Current state value
In StateName STRING[LOG_STRLEN_STATENAME] Optional name or description for the current state
// Declaration
logStateChange_typ stateLogger;

void _CYCLIC ProgramCyclic(void)
{
	strcpy(stateLogger.LoggerName, "App");
	strcpy(stateLogger.ModuleName, "Infeed");
	stateLogger.State = infeed.state;
	strcpy(stateLogger.StateName, infeed.stateName);
	logStateChange(&stateLogger);
}

With infeed.state at 0 and infeed.stateName at Idle, the first call logs Infeed start in state Idle (0). Moving to state 1 named Running then logs Infeed change from Idle to Running (0 to 1).

Note: The start entry reports the current state number as of LogThat 1.0.1. In 1.0.0 it always reported state 0, whatever the real starting state was. The state name was correct in both versions.

Entries are written with informational severity and code 0. If StateName is empty, only the numeric state is logged.

logDelete

Function block that deletes a logbook and all of its entries. Call it cyclically and hold execute true until done or error goes true, then set execute back to 0. The input is level triggered: clearing it early stops driving the delete, rather than cancelling work already handed to Automation Runtime. The outputs keep being re-derived from the underlying function blocks after execute is cleared, so done or error can still change.

Direction Name Type Description
In name STRING[LOG_STRLEN_LOGGERNAME] Name of the logbook to delete
In execute BOOL Hold TRUE until done or error. Clearing it early stops driving the delete without cancelling it
Out done BOOL Delete finished successfully
Out busy BOOL Delete in progress
Out error BOOL An error occurred
Out errorID DINT Status of the failed operation, see status
// Declaration
logDelete_typ deleter;

void _CYCLIC ProgramCyclic(void)
{
	if (deleteRequested) {
		strcpy(deleter.name, "App");
		deleter.execute = 1;
	}

	logDelete(&deleter);

	if (deleter.done || deleter.error) {
		deleter.execute = 0;
		deleteRequested = 0;
	}
}

ManageLoggers

Removed in 0.05.0. Logbooks are now created directly with createLogInit, and the number of logbooks is no longer limited by LogThat. Replace calls of the form

ManageLoggers(ADR(gLoggers), SIZEOF(gLoggers) / SIZEOF(gLoggers[0]));

with one createLogInit call per logbook in _INIT.