The LogObjectType is an ObjectType that is used to define an instance that collects log messages and make them available to a Client. A LogObject can contain LogRecords that were generated internally. It can also contain LogRecords that result from Events that have a ConditionClassId or ConditionSubClassId of LogEntryConditionClassType that are reported by the Object on which the LogObject instance is declared (see 6). The LogObject can also generate Events for LogRecords that were generated internally.

The underlying storage of LogRecords is not defined. The LogRecords could be stored as part of an EventHistory or stored in SYSLOG or OpenTelemetry or in some application specific manner (see Annex A for illustrations).

Although this specification does not define how data is stored, a requirement to persist LogRecords (i.e. LogRecords will be retained following a restart) is defined in a ConformanceUnit and may be added to a Profile.

The LogObject exposes a Method that allows a Client to retrieve the LogRecords. This Method does not provide complex filtering, only a time range and Severity. It also provides a RequestMask that allows the Client to select which fields in a LogRecord to return and a maximum number of LogRecords to return. Some LogObjects may optionally expose HistoricalEvents which would allow a more complex Event retrieval filter (see HistoricalEvent retrieval in OPC 10000-11).

The LogObjectType is illustrated in Figure 3.

image006.png

Figure 3 – LogObjectType illustration

The LogObjectType is formally defined in Table 1. The LogRecord Structure that is returned by the GetRecords Method is described in 5.5.

Table 1 – LogObjectType definition

Attribute

Value

BrowseName

0:LogObjectType

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of the 0:BaseObjectType defined in OPC 10000-5

0:HasComponent

Method

0:GetRecords

Defined in 5.3

M

0:HasProperty

Variable

0:MaxRecords

0:UInt32

0:PropertyType

O

0:HasProperty

Variable

0:MaxStorageDuration

0:Duration

0:PropertyType

O

0:HasProperty

Variable

0:MinimumSeverity

0:UInt16

0:PropertyType

O

0:HasComponent

Method

0:ReleaseContinuationPoint

Defined in 5.4

O

ConformanceUnits

LogObject Base

Optional MaxRecords defines the maximum number of LogRecords in a buffer associated with this LogObject. When this maximum is reached, a new LogRecord will trigger the deletion of the oldest LogRecord. If this Variable is not provided, then there is no Server published limit on the log buffer. Zero is an invalid value for MaxRecords.

Optional MaxStorageDuration defines the maximum time period that the LogObject will buffer LogRecords associated with this LogObject . LogRecords that are older than the maximum duration may be deleted. If this Variable is not provided, then no maximum duration is configured. Zero is an invalid duration. In the case of persistent storage, on startup a number of LogRecords may be deleted, depending on the duration of the downtime for the application.

The two maximum settings are used to limit the storage requirements for a Server. MaxRecords is typically a hard limit while MaxStorageDuration is more a soft limit in that LogRecords may be retained past the MaxStorageDuration if space allows. If MaxRecords is exceeded before MaxStorageDuration, the system should generate a LogOverflowEventType Event indicating an overflow of LogRecords (see 6.4).

The MinimumSeverity describes the minimum Severity of LogRecords associated with this LogObject. LogRecords with a Severity that is less than this number will not be available from this LogObject. If omitted, there is no restriction on the Severity associated with LogRecords associated with this LogObject. This number shall be between 1 and 1000, any other number is Invalid. Servers may allow this value to be written. The Severity is only checked when a LogRecord is being generated, a change to the value shall not affect the LogRecords that are already associated with this LogObject.

This Method allows a Client to retrieve LogRecords associated with this LogObject.

The signature of the Method is described below, and the arguments are described in Table 2.

Signature

GetRecords (

[in] 0:DateTime StartTime,

[in] 0:DateTime EndTime,

[in] 0:UInt32 MaxReturnRecords,

[in] 0:UInt16 MinimumSeverity,

[in] 0:LogRecordMask RequestMask,

[in] 0:ByteString ContinuationPointIn,

[out] LogRecordsDataTypeResults,

[out] 0:ByteString ContinuationPointOut

);

Table 2 – GetRecords Method arguments

Argument

Description

StartTime

The time associated with the first LogRecord returned in the array in Results, or if no there is no LogRecord at this time, then the first LogRecord returned will have the time closest to, but greater than StartTime.

EndTime

The time associated with the last LogRecord. EndTime must be equal to or greater than StartTime. No LogRecords more recent then EndTime are returned. If there are no LogRecords at EndTime, then the most recent LogRecord before EndTime is the last LogRecord in the Results array.

MaxReturnRecords

The maximum number of LogRecords to be returned, 0 indicates that no limit is specified. If this limit is specified then the LogRecords will start at StartTime, but may end before EndTime if the limit is reached. This shall result in a ContinuationPointOut being generated by the Server. On subsequent calls with the continuation point, the remaining LogRecords can be retrieved. The Server can also impose a limit that is less than this limit and can return a continuation point.

MinimumSeverity

The minimum Severity (all LogRecords with a Severity equal to this number or greater are returned).

RequestMask

The RecordMask indicates which optional fields in the LogRecord Structure are to be returned, if they are available. The LogRecordMask is defined in 5.8.

ContinuationPointIn

An opaque identifier provided by the Server from a previous call to GetRecords. This input parameter shall be null on an initial call to GetRecords. If not all LogRecords were returned on a previous call, the ContinuationPointOut can be provided to continue the retrieval of LogRecords. If a ContinuationPointIn is passed in, all other input arguments shall be the same as provided on the call that returned the ContinuationPointOut. If any of the input parameters are changed, the Server can ignore the updated parameters, it can detect any changes to the parameters and report an error or it can process the request as if it was a new request. If the Client specifies a ContinuationPointIn that is no longer valid, then the Server shall return a Bad_ContinuationPointInvalid error.

Results

Is a structure (see 5.10) that contains an array of the LogRecord Structure (see 5.5). The LogRecords shall be returned in chronological order from oldest to newest. Results can contain an empty array if no LogRecords match the request.

ContinuationPointOut

An opaque identifier that is used if the number of LogRecords to be returned is too large to be returned in a single response or if the Server requires the Client to call again. When this parameter is not used, its value is null. This identifier can be used to continue the retrieval of LogRecords in subsequent calls.

StartTime and EndTime together form the range in which LogRecords are returned. If StartTime equals EndTime, then only LogRecord(s) that have the provided time are returned. If EndTime is earlier than StartTime, then the error Bad_InvalidArgument shall be returned.

MinimumSeverity is a number between 1 and 1000 inclusive, a number outside of this range shall result in the error Bad_InvalidArgument (see Table 9 for additional details).

A ContinuationPointOut shall be generated if the number of LogRecords to return between StartTime and EndTime is larger than what can be returned in a single Method call. It can also be returned due to an internal error or any issue in the Server.

Method result codes in Table 3 (defined in Call Serv ice).

Table 3 – GetRecords Result Codes

Result Code

Description

Bad_OutOfRange

The provided Severity is outside the range 1-1000

Bad_InvalidArgument

One or more arguments are invalid, or StartTime is greater than EndTime

Bad_ContinuationPointInvalid

The continuation point provided is no longer valid.

Bad_UserAccessDenied

User does not have permission to perform the requested operation.

Bad_NoContinuationPoints

The operation could not be processed because all continuation points have been allocated.

The GetRecords Method representation in the AddressSpace is formally defined in Table 4.

Table 4 – GetRecords Method AddressSpace definition

Attribute

Value

BrowseName

0:GetRecords

References

Node Class

BrowseName

DataType

TypeDefinition

Other

0:HasProperty

Variable

0:InputArguments

0:Argument[]

0:PropertyType

M

0:HasProperty

Variable

0:OutputArguments

0:Argument[]

0:PropertyType

M

ConformanceUnits

LogObject Base

This Method allows a Client to release a LogObject ContinuationPoint that was returned to it.

The signature of the Method is described below, and the arguments are described in Table 5.

Signature

ReleaseContinuationPoint (

[in] 0:ByteString ContinuationPointIn

);

Table 5 – ReleaseContinuationPoint Method arguments

Argument

Description

ContinuationPointIn

An opaque identifier provided by the Server from a previous call to GetRecords that is to be released.

Method result codes in Table 6

Table 6 – ReleaseContinuationPoint Result Codes

Result Code

Description

Bad_ContinuationPointInvalid

The continuation point provided is not valid or no longer valid.

The ReleaseContinuationPoint Method representation in the AddressSpace is formally defined in Table 7.

Table 7 – ReleaseContinuationPoint Method AddressSpace definition

Attribute

Value

BrowseName

0:ReleaseContinuationPoint

References

Node Class

BrowseName

DataType

TypeDefinition

Other

0:HasProperty

Variable

0:InputArguments

0:Argument[]

0:PropertyType

M

ConformanceUnits

LogObject Base

This structured DataType describes the required information in a LogRecord. An array of this structure type is returned as a field in a structure in the LogObject GetRecords Method call.

The structure is formally defined in Table 8.

Table 8 – LogRecord structure

Name

Type

Description

Optional

LogRecord

Structure

Subtype of Structure defined in OPC 10000-5

Time

0:DateTime

Time associated with this record.

False

Severity

0:UInt16

Is a number between 1 and 1000 inclusive and corresponds to the range provided in the OPC UA BaseEventType (see OPC 10000-3). Additional details for mapping of the severity defined for OPC BaseEvents to LogRecords is described in Table 9.

False

EventType

0:NodeId

Describes the specific type of Event. It corresponds to the EventType field defined in BaseEventType.

If AdditionalData is provided then an EventType should be provided.

True

SourceNode

0:NodeId

Identifies the Node this record originated from. If the LogRecord is not related to a specific Node then this shall be set to a null NodeId.. Additional rules may be defined by other specifications that utilize the LogObject.

True

SourceName

0:String

Provides a description of the source of the LogRecord, this could be the string-part of the BrowseName of the SourceNode.

True

Message

0:LocalizedText

Provides a human-readable and localizable text description of the occurrence that is being represented in the LogRecord.

False

TraceContext

0:TraceContextDataType

This structure is used to correlate records inside of a Server along with corelating records between other Servers and Clients. The TraceContextDataType is described in 5.6.3.

True

AdditionalData

0:NameValuePair[]

Additional data for the log entry. This field contains the additional event fields of an LogEvent.

True

Severity ranges for Alarms and alerts are discussed further in OPC 10000-9. Table 9 provides the Severity ranges that shall be used for LogRecords. Other specifications, vendors or end users may further subset these ranges or generate thier own names for the ranges. For example, the Emergency range described in SYSLOG is commonly used for process alarms and would have multiple sub ranges defined by end users. In the manufacturing industry, typically the SYSLOG Alert range would be considered as Warnings and the Emergency range would have been renamed Error and have multiple sub ranges (i.e. CriticalError, MiniorError...).

Table 9 – LogRecord Severity Mapping

Syslog Names

Severity Range

Diagnostics classification

Emergency

401 – 1000

Incidents that are potentially fatal to the overall process/system and need to be addressed immediately.

Alert

300 – 400

Incidents that affect the overall process/system and need to be addressed.

Critical

251 – 300

Incidents that could affect the overall process/system and needs to be addressed.

Error

201 – 250

Incidents that have negative effects but does not affect the overall process/system.

Warning

151 – 200

Incidents that should be noted but need not be addressed.

Notice

101-150

Significant or unusual or unexpected successful incident.

Information

51-100

General information.

Debug

1-50

Verbose tracing information that can be used to debug the flow of an application.

The LogRecord representation in the AddressSpace is formally defined in Table 10

Table 10 – LogRecord definition

Attribute

Value

BrowseName

LogRecord

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of the 0:Structure defined in OPC 10000-5

ConformanceUnits

LogObject Base

The LogContext contains information required to trace distributed transactions or requests made to a distributed system. Such a trace may produce multiple log messages in one OPC UA Application and/or multiple log messages across multiple OPC UA Applications.

The TraceId is a unique identifier for a trace. Once assigned it never changes for that trace. If log messages for a given trace are across applications, they have the same TraceId.

A span represents a unit of work or operation. Spans are the building blocks of traces. A span is local to an OPC UA Application. The SpanId is a unique identifier assigned by an OPC UA Application for a local span in a trace. Spans can be nested. The ParentSpanId provides the reference to the parent span. The ParentSpanId is used to build a tree of spans inside a trace. If a nested span is created, the SpanId of the parent is used as ParentSpanId in the new child span.

At the very start (the root span) there is no ParentSpanId, only a new SpanId. This would be the base of a tree. See C.1 for additional discussion on SpanId and ParentSpanId.

The SpanContextDataType Structure is defined in Table 11. It defines a TraceId and SpanId. This Structure can be passed between Clients and Servers (see 5.6.4).

Table 11 – SpanContextDataType

Name

Type

Description

SpanContextDataType

Structure

Subtype of Structure defined in OPC 10000-5

TraceId

0:Guid

A unique identifier assigned to a trace.

SpanId

0:UInt64

Identifier for a span in a trace. 0 is an invalid value for a SpanId. The value shall be unique within a ParentSpanId within an Application.

The SpanContextDataType representation in the AddressSpace is formally defined in Table 12

Table 12 – SpanContextDataType definition

Attribute

Value

BrowseName

SpanContextDataType

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of the 0:Structure defined in OPC 10000-5

ConformanceUnits

LogObject TraceContext

The TraceContextDataType Structure is defined in Table 13. This structure is a subtype of the SpanContextDataType and is used in the LogRecord. It extends the SpanContextDataType Structure adding two additional fields. The ParentSpanId (together with the SpanId) allows for the creation of a tree of related LogRecords. The ParentIdentifier can be used to provide context information related to the parent.

Table 13 – TraceContextDataType

Name

Type

Description

TraceContextDataType

Structure

Subtype of SpanContextDataType defined in 5.6.2

ParentSpanId

0:UInt64

The identifier of the parent span. The value is 0 for a root span.

ParentIdentifier

0:String

If the parent span is from another OPC UA Application, the ParentIdentifier contains the ApplicationUri of the other OPC UA Application.

If the parent span is an internal span, the ParentIdentifier shall be null or empty.

If the ParentSpanId is 0, the ParentIdentifier shall be null or empty.

The TraceContextDataType representation in the AddressSpace is formally defined in Table 14.

Table 14 – TraceContextDataType definition

Attribute

Value

BrowseName

TraceContextDataType

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of the SpanContextDataType defined in 5.6.2

ConformanceUnits

LogObject TraceContext

If the Server is to be part of a Client trace, the Client passes the SpanContextDataType structure to a Server.

The SpanContextDataType Structure, defined in Table 11, is passed in the RequestHeader of any OPC UA Service call. The SpanContextDataType is transported with the AdditionalParametersType in the AdditionalHeader field of the RequestHeader (see OPC 10000-4). The Key for the parameter is “SpanContext and the Value is the SpanContextDataType Structure.

If a Server receives the optional AdditionalHeader, it uses the provided SpanConextDataType Structure when generating any LogRecords that are generated related to the Service invocation that provided the AdditionalHeader. It is possible that lower level functionality that is invoked as part of the Service call, may not have access to the provided AdditionalHeader, in which case it maybe omitted.

Inside the Server, the SpanId from the RequestHeader is used as ParentId for the LogContext structure defined in Table 13.

The NameValuePair structure is formally defined in Table 15. This structure has a Name field that is a name that is associated with the value that is reported in the second field. The Value may be of any DataType. Specifications may define standard names that are used to transport specific values that are to be included in the LogRecord as AdditionalData.

Table 15 – NameValuePair structure

Name

Type

Description

NameValuePair

Structure

Subtype of Structure defined in OPC 10000-5

Name

String

The name of the value.

Value

BaseDataType

The value associated with the name.

The NameValuePair Structure representation in the AddressSpace is formally defined in Table 16

Table 16 – NameValuePair definition

Attribute

Value

BrowseName

NameValuePair

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of the 0:Structure defined in OPC 10000-5

ConformanceUnits

LogObject AdditionalData

The LogRecordMask is formally defined in Table 17. It indicates which of the optional fields that may be available in a LogRecord are to be returned by GetRecords.

Table 17 – LogRecordMask Structure

Value

Bit No.

Description

EventType

0

Indicates if the EventType is returned in the LogRecords if available.

SourceNode

1

Indicates if the SourceNode is returned in the LogRecords if available.

SourceName

2

Indicates if the SourceName is returned in the LogRecords if available.

TraceContext

3

Indicates if the TraceContext is returned in the LogRecords if available.

AdditionalData

4

Indicates if the AdditionalData is returned in the LogRecords if available.

The LogRecordMask representation in the AddressSpace is formally defined in Table 18

Table 18 – LogRecordMask definition

Attribute

Value

BrowseName

LogRecordMask

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of UInt32 defined in OPC 10000-3

HasProperty

Variable

OptionSetValues

LocalizedText []

PropertyType

ConformanceUnits

LogObject Base

When generating LogRecords it is important that a context be associated with each LogRecord. This context information can be used to show a relationship between various LogRecords in a Server as well as relationships between LogRecords that are in different Servers. This context information is stored in the TraceContext field in the LogRecord (see definition in 5.6.2). If a hierarchy of related LogRecords is to be created, SpanId and ParentSpanId fields shall be used. When a function in a Server invokes another function in the same Server or in another Server as part of the same TraceId, the lower level function shall promote the SpanId of the higher level to be the ParentSpanId in the called function and a new SpanId shall be generated in the called function. This daisy chain of SpanId to ParentSpanId will allow a tree to be created for the LogRecords.

image007.png

Figure 4 – TraceContext hierarchy example

Figure 4 provides an illustration of the LogRecords that could result from calls between two Applications that include TraceContext information. The first line is each table is a list of the fields in the comma-separated-value records. These field names correspond to the names used in the LogRecord structure.

The key points being illustrated for the hierarchy are the TraceId, SpandId, ParentSpanId and ParentIdentifier field, which are the last 4 items in each LogRecord entry. The TraceId is shown as the GUID and is constant for this illustration (it is one action from the Client/Server). Additional actions would result in separate TraceIds, but are not illustrated.

In the Client/Server there is no ParentIdentifier, since all action are internal to the Server. In the RemoteServer the ParentIdentifier indicates the Client/Server. The ParentIdentifier is the ApplicationUri of the Client that called into the Server. The ApplicationUri of the first Server is “Https:CM1…”( it has been truncated to allow it to fit in the example).

The SpanId and ParentSpanId shows where calls have been made. At the beginning of the first table, the ParentSpanId is zero, since this is the root SpanId (see Annex C for more explanation of SpanId). In the first table, when a sub function is called, the SpanId is promoted to the ParentSpanId and a new SpanId is generated (see the third LogRecord in the table).

The large arrow shows that the Client/Server calls into the RemoteServer twice. It passes in the TraceId and the SpanId on each call. The TraceId is the same, but the SpanId changes on each call.

The second table shows the LogRecords that are generated that resulted from the two innovations of the Method in the RemoteServer. The passed in SpanId becomes the ParentSpanId in the LogRecords and a new SpanId is generated. The RemoteServer also makes a call to a sub-function where the SpanId is promoted to the ParentSpanId.

This structured DataType is used as the return DataType in the LogObject GetRecords Method call.

The structure is formally defined in Table 19.

Table 19 – LogRecordsDataType structure

Name

Type

Description

LogRecordsDataType

Structure

Subtype of Structure defined in OPC 10000-5

LogRecordArray

LogRecord[]

An array of LogRecords.

The LogRecordsDataType representation in the AddressSpace is formally defined in Table 20.

Table 20 – LogRecordsDataType definition

Attribute

Value

BrowseName

LogRecordsDataType

IsAbstract

False

References

NodeClass

BrowseName

DataType

TypeDefinition

Other

Subtype of the 0:Structure defined in OPC 10000-5

ConformanceUnits

LogObject Base

The LogObject can include information that maybe sensitive or include security related information. LogObjects that contain security related information should not be made accessible to all users, but only to authorised users.

A LogObject can restrict a Client’s access to the GetRecords Method using standard OPC UA security features. This all or nothing approach can work well if multiple LogObjects are defined in a Server and security related information is collected in a separate LogObject. It becomes more problematic if a single LogObject collects a mixture of security related information and non-security related information.

LogObjects should implement permissions similar to what Event systems implement. In Event systems each Event has permissions assigned to it, in a LogObject each LogRecord can have permissions assigned to it. These permissions can be used to determine if a LogRecord should be returned to the Client that is invoking the GetRecords Method.