QuickOPC: How to enable extended tracing

From OPC Labs Knowledge Base
Revision as of 10:33, 18 January 2021 by User (talk | contribs)

This information applies to version 2021.1 or newer. -> Earlier versions

Enabling the extended tracing

For advanced troubleshooting, it is sometimes necessary to obtain information about QuickOPC internal status and activities. This can be done by enabling extended tracing, as described in this application note. Most of the tracing is for OPC UA, but there is some tracing for other OPC specifications as well.

The logging is enabled by various .NET trace switches, and settings in configuration file sections. Unless you are able to observe the output in the debugger or using a special tool, you also need to direct the trace to a proper listener, using the standard means provided by .NET tracing facility. It is up to you how you enable the switches or configure the listener(s). Typically, it is done using the application configuration file, with the advantage that it can be done without rebuilding the application.

The example below shows the application configuration file with common parts of the extended tracing enabled.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="OpcLabs.EasyOpc.UA.Toolkit.SdkTrace" type="OpcLabs.EasyOpc.UA.Toolkit.SdkTraceSection,OpcLabs.EasyOpcUA" />
  </configSections>
  <OpcLabs.EasyOpc.UA.Toolkit.SdkTrace traceOutput="3" >
  </OpcLabs.EasyOpc.UA.Toolkit.SdkTrace>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
  </startup>
  <system.diagnostics>
    <switches>
      <!-- Source switches -->
      <add name="OpcLabs.Boxing.Applications" value="Verbose" />
      <add name="OpcLabs.Boxing.Progress" value="Verbose" />
      <add name="OpcLabs.Configuration.Retrieve" value="Verbose" />
      <add name="OpcLabs.EasyOpc.UA.EasyUAClientEngineBase" value="Verbose" />
      <add name="OpcLabs.EasyOpc.UA.NetSdkEasyUAClient" value="Verbose" />
      <add name="OpcLabs.EasyOpc.UA.NetSdkEasyUASubscriber" value="Verbose" />
      <add name="OpcLabs.EasyOpc.UA.UAEngineBase" value="Verbose" />
      <add name="OpcLabs.EasyOpc.UA.UASmartClientEngine" value="Verbose" />
      <add name="OpcLabs.EventTracing.LogEntries" value="Verbose" />
      <add name="OpcLabs.EventTracing.SafeCritical" value="Verbose" />
      <add name="OpcLabs.Licensing.Invoke" value="Verbose" />
      <add name="OpcLabs.Licensing.Verify" value="Verbose" />
      <add name="OpcLabs.Reflection.AssemblyLoading" value="Verbose" />

       <!-- Other switches -->
      <add name="OpcLabs.CallDiagnostics.Display.CallPort" value="1" />
      <add name="OpcLabs.CallDiagnostics.Display.Enabled" value="1" />
      <add name="OpcLabs.CallDiagnostics.Display.EnterPort" value="1" />
      <add name="OpcLabs.CallDiagnostics.Display.ExitPort" value="1" />
      <add name="OpcLabs.CallDiagnostics.Display.LeavePort" value="1" />
      <add name="OpcLabs.CallDiagnostics.Display.TickCount" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.Configuration" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.Sdk" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.SdkCallback" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.SdkEnvironment" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.SdkMethod" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.SdkTarget" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.TraceSelectEndpoint" value="1" />
      <add name="OpcLabs.EasyOpc.UA.Toolkit.TraceSdk" value="1" />
    </switches>
  </system.diagnostics>
</configuration>

The relevant parts of the file are highlighted. Specifically, following information will be contained in the traces:

  • All trace information from inside OPC UA .NET Stack and SDK.
  • Calls to and from OPC UA .NET Stack and SDK.
  • Log entries generated by the component.

Please refer to Microsoft documentation for details on the application configuration files, the diagnostic switches, the trace listeners, and so on. The application configuration file needs to be named the same as your application, with an added “.config” extension, and placed alongside the application. For example, for “MyApp.exe”, the configuration file is “MyApp.exe.config”. Note that the development tools sometimes provide “shortcuts” for the naming and placing procedure. For example, Visual Studio C# projects contain an app.config file, which becomes the application configuration file automatically – Visual Studio copies it to the output folder and renames it appropriately.

Note2-icon.png

Note: Under COM platform, QuickOPC objects get loaded into the process of the application that creates and calls them. You therefore need to create or modify the configuration file for the application itself (as if it were a .NET application). In hosted environments, such as ASP.NET, the name and location of the configuration file may be different as well.

By default, the traces are directed to the Windows debug output, which you can observe e.g. when you run the program under a debugger, or it can be viewed and captured using specialized tools such Sysinternals’ DebugView (http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx ).

Differences under .NET Core

Under .NET Core, add one more section under the <configSections> element:

    <section name="system.diagnostics" type="OpcLabs.BaseLib.Configuration.SystemDiagnosticsConfigurationSection,OpcLabs.BaseLib" />

The configuration file name might be different under .NET Core. For a standalone program whose main assembly is in a DLL and that is run through the 'dotnet' command, the configuration file is <programName>.dll.config. There are also machine-wide, user-specific and roaming configuration files (refer to .NET Core documentation for details). In hosted environments (Web apps, for example), the configuration model might be different as well. Following trace listeners are not available under .NET Core 2.1:

  • System.Diagnostics.ConsoleTraceListener
  • System.Diagnostics.EventLogTraceListener
  • System.Diagnostics.EventSchemaTraceListener
  • Microsoft.VisualBasic.Logging.FileLogTraceListener
  • System.Diagnostics.XmlWriterTraceListener

Trace Switches

Following table lists some selected trace switches and their meaning.

Name Type Name Description Default value
OpcLabs.EasyOpc.DataAccess.OCKClient.BrowseNodes BooleanSwitch Browsing for OPC DA nodes. 0[1]
OpcLabs.Licensing.Invoke BooleanSwitch License invocation. Error[2]
OpcLabs.Licensing.Verify BooleanSwitch License verification. Error[2]

Switches in Debug configurations

The switches listed here are only functional in Debug configurations. Note that Debug configurations of the software are not normally made available to customers.

Name Type Name Description Default value
OpcLabs.DotProlog.Engine.DebugTracingDebugger BooleanSwitch Tracing debugger. 0

Trace Listener Configuration

If you do not want to use the default debug trace configuration (directing the traces to the debug output), you can configure the trace listener(s) in various ways. Please refer to Microsoft documentation for details.

In the configuration snippet below, we have included shared listener definitions for various types of listeners provided by Microsoft (you can remove or comment out the ones that you do not need). With the shared listeners definitions, you can then configure every trace source simply by adding a (shared) listener to it, using the listener name. For example, to store the output into a comma-delimited file “TraceOutput-DelimitedList.csv” (in the same folder as the application), use the following configuration part:

  <system.diagnostics>
    <sharedListeners>
      <!-- Console -->
      <add name="Console" type="System.Diagnostics.ConsoleTraceListener" />

      <!-- DelimitedList -->
      <add name="DelimitedList"
           type="System.Diagnostics.DelimitedListTraceListener"
           traceOutputOptions="DateTime, ProcessId, ThreadId"
           initializeData="TraceOutput-DelimitedList.csv" 
           delimiter="," />

      <!-- EventLog -->
      <add name="EventLog"
           type="System.Diagnostics.EventLogTraceListener"
           initializeData="TraceListenerLog" />

      <!-- EventSchema -->
      <add name="EventSchema"
           type="System.Diagnostics.EventSchemaTraceListener, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
           traceOutputOptions="ProcessId, DateTime, Timestamp"
           initializeData="TraceOutput-EventSchema.xml"
           bufferSize="65536"
           logRetentionOption="LimitedCircularFiles"
           maximumFileSize="20480000"
           maximumNumberOfFiles="2" />

      <!-- FileLog -->
      <add name="FileLog"
           type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
           initializeData="FileLogWriter" 
           baseFileName="TraceOutput-FileLog"
           location="ExecutableDirectory" />

      <!-- TextWriter -->
      <add name="TextWriter"
           type="System.Diagnostics.TextWriterTraceListener"
           initializeData="TraceOutput-TextWriter.txt" />

      <!-- Xml -->
      <add name="Xml"
           type="System.Diagnostics.XmlWriterTraceListener"
           traceOutputOptions="ProcessId, DateTime" 
           initializeData="TraceOutput-Xml.xml" />
    </sharedListeners>

    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="DelimitedList" />
        <remove name="Default" />
      </listeners>
    </trace>

    <sources>
      <source name="OpcLabs.Boxing.Applications"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.Boxing.Progress"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.Configuration.Retrieve"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EasyOpc.UA.EasyUAClientEngineBase"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EasyOpc.UA.NetSdkEasyUAClient"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EasyOpc.UA.NetSdkEasyUASubscriber"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EasyOpc.UA.UASmartClientEngine"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EasyOpc.UA.UAEngineBase"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EventTracing.LogEntries"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.EventTracing.SafeCritical"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.Licensing.Invoke"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.Licensing.Verify"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
      <source name="OpcLabs.Reflection.AssemblyLoading"> <listeners> <add name="DelimitedList"/> <remove name="Default"/> </listeners> </source>
    </sources>

  </system.diagnostics>

Earlier versions


  1. Default value is 1 in Debug configurations
  2. 2.0 2.1 Default value is Verbose in Debug configurations