QuickOPC does not log events on itself, but allows you to implement such functionality. It generates notifications with log entries that contain the necessary data. You can receive these notifications, and implement any kind of event logging with them in your code.
Note that you should not programmatically use the logging event notifications for any kind of direct actions on the OPC subsystem. For example, the notifications that inform you about the connections and disconnections to/from OPC servers have no direct relation to your OPC method calls, because the component internally merges the requests from multiple objects, and also makes optimizations to prevent unnecessary disconnections etc. The purpose of event logging is different from OPC communication.
The data generated by event logging can contain security sensitive information. Make sure that when consuming and processing such data, it is properly secured.
Event Logging for OPC UA Client-Server
The EasyUAClient component has a static LogEntry event. This event is raised for loggable entries originating in the OPC-UA client engine and the EasyUAClient component. Each event notification carries a LogEntryEventArgs object, which contains information such as the source of the event, the event message, event type, timestamp, etc.
In COM, you cannot access static members of the EasyUAClient object, and therefore you cannot directly use its LogEntry event. To get around this, create an instance of the EasyUAClientManagement object instead, and use its (non-static) LogEntry event to achieve the same result.
Example
.NET
// This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
using System;
using OpcLabs.BaseLib.Instrumentation;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;
namespace UADocExamples._EasyUAClient
{
class LogEntry
{
public static void Main1()
{
UAEndpointDescriptor endpointDescriptor =
"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
// or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
// or "https://opcua.demo-this.com:51212/UA/SampleServer/"
// Hook static events
EasyUAClient.LogEntry += EasyUAClientOnLogEntry;
try
{
// Do something - invoke an OPC read, to trigger some loggable entries.
var client = new EasyUAClient();
try
{
client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853");
}
catch (UAException uaException)
{
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
return;
}
Console.WriteLine("Processing log entry events for 1 minute...");
System.Threading.Thread.Sleep(60 * 1000);
Console.WriteLine("Finished.");
}
finally
{
// Unhook static events
EasyUAClient.LogEntry -= EasyUAClientOnLogEntry;
}
}
// Event handler for the LogEntry event. It simply prints out the event.
private static void EasyUAClientOnLogEntry(object sender, LogEntryEventArgs logEntryEventArgs)
{
Console.WriteLine(logEntryEventArgs);
}
}
}
# This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time
# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *
# Event handler for the LogEntry event. It simply prints out the event.
def onLogEntry(sender, logEntryEventArgs):
print(logEntryEventArgs)
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'
# Hook static events.
EasyUAClient.LogEntry += onLogEntry
# Instantiate the client object.
client = EasyUAClient()
# Do something - invoke an OPC read, to trigger some loggable entries.
try:
value = IEasyUAClientExtension.ReadValue(client,
endpointDescriptor,
UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'))
except UAException as uaException:
print('*** Failure: ' + uaException.GetBaseException().Message)
exit()
print('Processing log entry events for 1 minute...')
time.sleep(60)
print()
print('Finished.')
' This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
Imports OpcLabs.BaseLib.Instrumentation
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.OperationModel
Namespace _EasyUAClient
Friend Class LogEntry
Public Shared Sub Main1()
Dim endpointDescriptor As UAEndpointDescriptor =
"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
' or "https://opcua.demo-this.com:51212/UA/SampleServer/"
' Hook static events
AddHandler EasyUAClient.LogEntry, AddressOf EasyUAClientOnLogEntry
Try
' Do something - invoke an OPC read, to trigger some loggable entries.
Dim client = New EasyUAClient()
Try
client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853")
Catch uaException As UAException
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
Exit Sub
End Try
Console.WriteLine("Processing log entry events for 1 minute...")
Threading.Thread.Sleep(60 * 1000)
Console.WriteLine("Finished.")
Finally
' Unhook static events
RemoveHandler EasyUAClient.LogEntry, AddressOf EasyUAClientOnLogEntry
End Try
End Sub
' Event handler for the LogEntry event. It simply prints out the event.
Private Shared Sub EasyUAClientOnLogEntry(ByVal sender As Object, ByVal logEntryEventArgs As LogEntryEventArgs)
Console.WriteLine(logEntryEventArgs)
End Sub
End Class
End Namespace
COM
// This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
#include "stdafx.h" // Includes "QuickOpc.h", and other commonly used files
#include <atlcom.h>
#include "LogEntry.h"
namespace _EasyUAClientManagement
{
// CEasyUAClientManagementEvents
class CEasyUAClientManagementEvents : public IDispEventImpl<1, CEasyUAClientManagementEvents>
{
public:
BEGIN_SINK_MAP(CEasyUAClientManagementEvents)
// Event handlers must have the __stdcall calling convention
SINK_ENTRY(1, 1 /*DISPID_EASYUACLIENTManagementEVENTS_LOGENTRY*/, &CEasyUAClientManagementEvents::LogEntry)
END_SINK_MAP()
public:
// Event handler for the LogEntry event. It simply prints out the event.
STDMETHOD(LogEntry)(VARIANT varSender, _LogEntryEventArgs* pEventArgs)
{
_tprintf(_T("%s\n"), (LPCTSTR)CW2CT(pEventArgs->ToString));
return S_OK;
}
};
void LogEntry::Main()
{
// Initialize the COM library
CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
// The management object allows access to static behavior - here, the shared LogEntry event.
_EasyUAClientManagementPtr ClientManagementPtr(__uuidof(EasyUAClientManagement));
// Hook events
CEasyUAClientManagementEvents* pClientManagementEvents = new CEasyUAClientManagementEvents();
AtlGetObjectSourceInterface(ClientManagementPtr, &pClientManagementEvents->m_libid,
&pClientManagementEvents->m_iid,
&pClientManagementEvents->m_wMajorVerNum, &pClientManagementEvents->m_wMinorVerNum);
pClientManagementEvents->m_iid = _uuidof(DEasyUAClientManagementEvents);
pClientManagementEvents->DispEventAdvise(ClientManagementPtr, &pClientManagementEvents->m_iid);
// Do something - invoke an OPC read, to trigger some loggable entries.
_EasyUAClientPtr ClientPtr(__uuidof(EasyUAClient));
ClientPtr->ReadValue(
//L"http://opcua.demo-this.com:51211/UA/SampleServer",
L"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
L"nsu=http://test.org/UA/Data/ ;i=10853");
_tprintf(_T("Processing log entry events for 1 minute...\n"));
Sleep(60*1000);
// Unhook events
pClientManagementEvents->DispEventUnadvise(ClientManagementPtr, &pClientManagementEvents->m_iid);
}
// Release all interface pointers BEFORE calling CoUninitialize()
CoUninitialize();
}
}
// This example demonstrates the loggable entries originating in the OPC-UA
// client engine and the EasyUAClient component.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
type
TClientManagementEventHandlers = class
procedure OnLogEntry(
Sender: TObject;
sender0: OleVariant;
eventArgs: _LogEntryEventArgs);
end;
// Event handler for the LogEntry event. It simply prints out the event.
procedure TClientManagementEventHandlers.OnLogEntry(
Sender: TObject;
sender0: OleVariant;
eventArgs: _LogEntryEventArgs);
begin
WriteLn(eventArgs.ToString);
end;
class procedure LogEntry.Main;
var
Client: EasyUAClient;
EvsClientManagement: TEvsEasyUAClientManagement;
ClientManagement: EasyUAClientManagement;
ClientManagementEventHandlers: TClientManagementEventHandlers;
Value: OleVariant;
begin
// The Management object allows access to static behavior - here, the
// shared LogEntry event.
EvsClientManagement := TEvsEasyUAClientManagement.Create(nil);
ClientManagement := EvsClientManagement.ComServer;
ClientManagementEventHandlers := TClientManagementEventHandlers.Create;
EvsClientManagement.OnLogEntry := @ClientManagementEventHandlers.OnLogEntry;
// Do something - invoke an OPC read, to trigger some loggable entries.
Client := CoEasyUAClient.Create;
Value := Client.ReadValue(
//'http://opcua.demo-this.com:51211/UA/SampleServer',
'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer',
'nsu=http://test.org/UA/Data/ ;i=10853');
WriteLn('Processing log entry events for 1 minute...');
PumpSleep(60*1000);
end;
// This example demonstrates the loggable entries originating in the OPC-UA
// client engine and the EasyUAClient component.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
type
TClientManagementEventHandlers130 = class
procedure OnLogEntry(
ASender: TObject;
sender: OleVariant;
const eventArgs: _LogEntryEventArgs);
end;
// Event handler for the LogEntry event. It simply prints out the event.
procedure TClientManagementEventHandlers130.OnLogEntry(
ASender: TObject;
sender: OleVariant;
const eventArgs: _LogEntryEventArgs);
begin
WriteLn(eventArgs.ToString);
end;
class procedure LogEntry.Main;
var
Client: OpcLabs_EasyOpcUA_TLB._EasyUAClient;
ClientManagement: TEasyUAClientManagement;
ClientManagementEventHandlers: TClientManagementEventHandlers130;
Value: OleVariant;
begin
// The management object allows access to static behavior - here, the
// shared LogEntry event.
ClientManagement := TEasyUAClientManagement.Create(nil);
ClientManagementEventHandlers := TClientManagementEventHandlers130.Create;
ClientManagement.OnLogEntry := ClientManagementEventHandlers.OnLogEntry;
ClientManagement.Connect;
// Do something - invoke an OPC read, to trigger some loggable entries.
Client := CoEasyUAClient.Create;
try
Value := Client.ReadValue(
//'http://opcua.demo-this.com:51211/UA/SampleServer',
//'https://opcua.demo-this.com:51212/UA/SampleServer/',
'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer',
'nsu=http://test.org/UA/Data/ ;i=10853');
except
on E: EOleException do
begin
WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
//Exit;
end;
end;
WriteLn('Processing log entry events for 1 minute...');
PumpSleep(60*1000);
WriteLn('Finished.');
FreeAndNil(ClientManagement);
FreeAndNil(ClientManagementEventHandlers);
end;
// This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
class ClientManagementEvents {
// Event handler for the LogEntry event. It simply prints out the event.
function LogEntry($Sender, $E)
{
printf("%s\n", $E);
}
}
// The management object allows access to static behavior - here, the shared LogEntry event.
$ClientManagement = new COM("OpcLabs.EasyOpc.UA.EasyUAClientManagement");
$ClientManagementEvents = new ClientManagementEvents();
com_event_sink($ClientManagement, $ClientManagementEvents, "DEasyUAClientManagementEvents");
// Do something - invoke an OPC read, to trigger some loggable entries.
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
try
{
$value = $Client->ReadValue(
//"http://opcua.demo-this.com:51211/UA/SampleServer",
"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
"nsu=http://test.org/UA/Data/ ;i=10853");
}
catch (com_exception $e)
{
printf("*** Failure: %s\n", $e->getMessage());
Exit();
}
printf("Processing log entry events for 1 minute...");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 60);
REM This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
REM
REM Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' The management object allows access to static behavior - here, the shared LogEntry event.
'Public WithEvents ClientManagement1 As EasyUAClientManagement
Private Sub LogEntry_Main_Command_Click()
OutputText = ""
Set ClientManagement1 = New EasyUAClientManagement
' Do something - invoke an OPC read, to trigger some loggable entries.
Dim client As New EasyUAClient
On Error Resume Next
Dim value As Variant
value = client.ReadValue("opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853")
If Err.Number <> 0 Then
OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf
Exit Sub
End If
On Error GoTo 0
OutputText = OutputText & "Processing log entry events for 1 minute..." & vbCrLf
Pause 60000
Set ClientManagement1 = Nothing
OutputText = OutputText & "Finished..." & vbCrLf
End Sub
' Event handler for the LogEntry event. It simply prints out the event.
Private Sub ClientManagement1_LogEntry(ByVal sender As Variant, ByVal eventArgs As OpcLabs_BaseLib.LogEntryEventArgs)
OutputText = OutputText & eventArgs & vbCrLf
End Sub
Rem This example demonstrates the loggable entries originating in the OPC-UA client engine and the EasyUAClient component.
Rem
Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
Option Explicit
' The management object allows access to static behavior - here, the shared LogEntry event.
Dim ClientManagement: Set ClientManagement = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClientManagement")
WScript.ConnectObject ClientManagement, "ClientManagement_"
' Do something - invoke an OPC read, to trigger some loggable entries.
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")
On Error Resume Next
Dim value: value = Client.ReadValue("opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853")
If Err.Number <> 0 Then
WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description
WScript.Quit
End If
On Error Goto 0
WScript.Echo "Processing log entry events for 1 minute..."
WScript.Sleep 60*1000
' Event handler for the LogEntry event. It simply prints out the event.
Sub ClientManagement_LogEntry(Sender, e)
WScript.Echo e
End Sub
Event Logging for OPC UA PubSub
Event logging for OPC UA PubSub works similarly to event logging for OPC UA Client-Server (described above), except that you will use the LogEntry Event on the EasyUASubscriber Class.
Event Logging for OPC "Classic"
Event logging for OPC “Classic” specifications works similarly to event logging for OPC UA Client-Server (described above), except that you will use the LogEntry Event on the EasyDAClient Class or the EasyAEClient Class.
Currently, only limited contents is provided for OPC Classic: Basically, logged entries only cover callback errors, (some) queue errors, and licensing information.
See Also