Skip to content

Commit

Permalink
Tracing and Logging improvements for the UA Core and libraries (#1631)
Browse files Browse the repository at this point in the history
- support for Microsoft.Extensions.Logger.ILogger in Opc.Ua.Core as the new logging interface
- backward compatible with config and TraceEvents
- new API Utils.SetLogger allows to set ILogger
- updated Console samples to demonstrate ILogger support with Serilog
- support for EventSource logging
- see Docs/Logging.md for more info
  • Loading branch information
mregen committed Dec 15, 2021
1 parent b55ef38 commit a147eb5
Show file tree
Hide file tree
Showing 139 changed files with 4,531 additions and 2,065 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ jobs:
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main


- name: Set up .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.x'

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ artifacts/
*.pidb
*.svclog
*.scc
*.nettrace


# Chutzpah Test files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ private void BrowseTV_BeforeExpand(object sender, TreeViewCancelEventArgs e)
}
catch (Exception exception)
{
Utils.Trace(exception, "Error loading image.");
Utils.LogError(exception, "Error loading image.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ public void SetAvailableUrls(IList<string> urls)
catch (Exception e)
{
UpdateStatus(true, DateTime.Now, "Connected, failed to load complex type system.");
Utils.Trace(e, "Failed to load complex type system.");
Utils.LogWarning(e, "Failed to load complex type system.");
}

// return the new session.
Expand Down Expand Up @@ -398,7 +398,7 @@ public Task<Session> Connect()
catch (Exception e)
{
UpdateStatus(true, DateTime.Now, "Connected, failed to load complex type system.");
Utils.Trace(e, "Failed to load complex type system.");
Utils.LogError(e, "Failed to load complex type system.");
}

// return the new session.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ private void OnDiscoverServersOnNetwork(object state)
}
catch (Exception e)
{
Utils.Trace(e, "Unexpected error discovering servers.");
Utils.LogError(e, "Unexpected error discovering servers.");
}
}

Expand Down Expand Up @@ -254,7 +254,7 @@ private bool DiscoverServersOnNetwork(Uri discoveryUrl)
}
catch (Exception e)
{
Utils.Trace("Error retrieving FindServersOnNetwork paramters. Error=({1}){0}", e.Message, e.GetType());
Utils.LogError("Error retrieving FindServersOnNetwork parameters. Error=({1}){0}", e.Message, e.GetType());
return false;
}

Expand All @@ -265,7 +265,7 @@ private bool DiscoverServersOnNetwork(Uri discoveryUrl)
}
catch (Exception e)
{
Utils.Trace("DISCOVERY ERROR - Could not fetch servers from url: {0}. Error=({2}){1}", discoveryUrl, e.Message, e.GetType());
Utils.LogError("DISCOVERY ERROR - Could not fetch servers from url: {0}. Error=({2}){1}", discoveryUrl, e.Message, e.GetType());
return false;
}
finally
Expand Down
2 changes: 1 addition & 1 deletion Applications/ClientControls.Net4/Common/HostListCtrl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private void OnFetchAddresses(object state)
}
catch (Exception e)
{
Utils.Trace(e, "Could not get ip addresses for host: {0}", hostname);
Utils.LogError(e, "Could not get ip addresses for host: {0}", hostname);
ThreadPool.QueueUserWorkItem(new WaitCallback(OnUpdateAddress), new object[] { listItem, e.Message });
}
}
Expand Down
23 changes: 21 additions & 2 deletions Applications/ConsoleReferenceClient/ConsoleReferenceClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,31 @@
<PackageId>ConsoleReferenceClient</PackageId>
<Company>OPC Foundation</Company>
<Description>.NET Console Reference Client</Description>
<Copyright>Copyright © 2004-2020 OPC Foundation, Inc</Copyright>
<Copyright>Copyright © 2004-2021 OPC Foundation, Inc</Copyright>
<RootNamespace>Quickstarts.ConsoleReferenceClient</RootNamespace>
</PropertyGroup>

<ItemGroup Condition=" '$(NoHttps)' != 'true' ">
<ProjectReference Include="..\..\Stack\Opc.Ua.Bindings.Https\Opc.Ua.Bindings.Https.csproj" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.21" />
</ItemGroup>

<ItemGroup Condition=" '$(NoHttps)' == 'true' ">
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\ConsoleReferenceServer\ConsoleUtils.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Mono.Options" Version="6.12.0.148" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Expressions" Version="3.2.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -22,7 +41,7 @@
</ItemGroup>

<ItemGroup>
<None Update="ConsoleReferenceClient.Config.xml">
<None Update="Quickstarts.ReferenceClient.Config.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Expand Down
22 changes: 0 additions & 22 deletions Applications/ConsoleReferenceClient/Output.cs

This file was deleted.

153 changes: 123 additions & 30 deletions Applications/ConsoleReferenceClient/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* ========================================================================
* Copyright (c) 2005-2020 The OPC Foundation, Inc. All rights reserved.
* Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
Expand Down Expand Up @@ -28,59 +28,152 @@
* ======================================================================*/

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Opc.Ua;
using Opc.Ua.Configuration;

namespace Quickstarts.ConsoleReferenceClient
{
/// <summary>
/// The program.
/// </summary>
public static class Program
{
/// <summary>
/// Main entry point.
/// </summary>
public static async Task Main(string[] args)
{
IOutput console = new ConsoleOutput();
console.WriteLine("OPC UA Console Reference Client");
TextWriter output = Console.Out;
output.WriteLine("OPC UA Console Reference Client");

// The application name and config file names
var applicationName = "ConsoleReferenceClient";
var configSectionName = "Quickstarts.ReferenceClient";
var usage = $"Usage: dotnet {applicationName}.dll [OPTIONS]";

// command line options
bool showHelp = false;
bool autoAccept = false;
bool logConsole = false;
bool appLog = false;
bool renewCertificate = false;
string password = null;
int timeout = Timeout.Infinite;

Mono.Options.OptionSet options = new Mono.Options.OptionSet {
usage,
{ "h|help", "show this message and exit", h => showHelp = h != null },
{ "a|autoaccept", "auto accept certificates (for testing only)", a => autoAccept = a != null },
{ "c|console", "log to console", c => logConsole = c != null },
{ "l|log", "log app output", c => appLog = c != null },
{ "p|password=", "optional password for private key", (string p) => password = p },
{ "r|renew", "renew application certificate", r => renewCertificate = r != null },
{ "t|timeout=", "timeout in seconds to exit application", (int t) => timeout = t * 1000 },
};

try
{
// Define the UA Client application
ApplicationInstance application = new ApplicationInstance();
application.ApplicationName = "Quickstart Console Reference Client";
application.ApplicationType = ApplicationType.Client;
// parse command line and set options
var extraArg = ConsoleUtils.ProcessCommandLine(output, args, options, ref showHelp, false);

// load the application configuration.
await application.LoadApplicationConfiguration("ConsoleReferenceClient.Config.xml", silent: false);
// check the application certificate.
await application.CheckApplicationInstanceCertificate(silent: false, minimumKeySize: 0);
// connect Url?
Uri serverUrl = new Uri("opc.tcp://localhost:62541/Quickstarts/ReferenceServer");
if (!string.IsNullOrEmpty(extraArg))
{
serverUrl = new Uri(extraArg);
}

// create the UA Client object and connect to configured server.
UAClient uaClient = new UAClient(application.ApplicationConfiguration, console, ClientBase.ValidateResponse);
bool connected = await uaClient.ConnectAsync();
if (connected)
// log console output to logger
if (logConsole && appLog)
{
// Run tests for available methods.
uaClient.ReadNodes();
uaClient.WriteNodes();
uaClient.Browse();
uaClient.CallMethod();
output = new LogWriter();
}

// Define the UA Client application
ApplicationInstance.MessageDlg = new ApplicationMessageDlg(output);
CertificatePasswordProvider PasswordProvider = new CertificatePasswordProvider(password);
ApplicationInstance application = new ApplicationInstance {
ApplicationName = applicationName,
ApplicationType = ApplicationType.Client,
ConfigSectionName = configSectionName,
CertificatePasswordProvider = PasswordProvider
};

// load the application configuration.
var config = await application.LoadApplicationConfiguration(silent: false);

uaClient.SubscribeToDataChanges();
// Wait for some DataChange notifications from MonitoredItems
await Task.Delay(20_000);
// setup the logging
ConsoleUtils.ConfigureLogging(config, applicationName, logConsole, LogLevel.Information);

uaClient.Disconnect();
// delete old certificate
if (renewCertificate)
{
await application.DeleteApplicationInstanceCertificate().ConfigureAwait(false);
}
else

// check the application certificate.
bool haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, minimumKeySize: 0).ConfigureAwait(false);
if (!haveAppCertificate)
{
console.WriteLine("Could not connect to server!");
throw new ErrorExitException("Application instance certificate invalid!", ExitCode.ErrorCertificate);
}

console.WriteLine("\nProgram ended.");
console.WriteLine("Press any key to finish...");
Console.ReadKey();
// wait for timeout or Ctrl-C
var quitEvent = ConsoleUtils.CtrlCHandler();

// connect to a server until application stopped
bool quit = false;
DateTime start = DateTime.UtcNow;
int waitTime = int.MaxValue;
do
{
if (timeout > 0)
{
waitTime = timeout - (int)DateTime.UtcNow.Subtract(start).TotalMilliseconds;
if (waitTime <= 0)
{
break;
}
}

// create the UA Client object and connect to configured server.
UAClient uaClient = new UAClient(application.ApplicationConfiguration, output, ClientBase.ValidateResponse) {
AutoAccept = autoAccept
};

bool connected = await uaClient.ConnectAsync(serverUrl.ToString());
if (connected)
{
// Run tests for available methods.
uaClient.ReadNodes();
uaClient.WriteNodes();
uaClient.Browse();
uaClient.CallMethod();

uaClient.SubscribeToDataChanges();

// Wait for some DataChange notifications from MonitoredItems
quit = quitEvent.WaitOne(Math.Min(30_000, waitTime));

uaClient.Disconnect();
}
else
{
output.WriteLine("Could not connect to server! Retry in 10 seconds or Ctrl-C to quit.");
quit = quitEvent.WaitOne(Math.Min(10_000, waitTime));
}

} while (!quit);

output.WriteLine("\nClient stopped.");
}
catch (Exception ex)
{
console.WriteLine(ex.Message);
output.WriteLine(ex.Message);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,35 @@
xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd"
>
<ApplicationName>Quickstart Console Reference Client</ApplicationName>
<ApplicationUri>urn:localhost:Quickstarts:Console ReferenceClient</ApplicationUri>
<ProductUri>uri:opcfoundation.org:Quickstarts:Console ReferenceClient</ProductUri>
<ApplicationUri>urn:localhost:UA:Quickstarts:ReferenceClient</ApplicationUri>
<ProductUri>uri:opcfoundation.org:Quickstarts:ReferenceClient</ProductUri>
<ApplicationType>Client_1</ApplicationType>

<SecurityConfiguration>

<!-- Where the application instance certificate is stored (MachineDefault) -->
<ApplicationCertificate>
<StoreType>Directory</StoreType>
<StorePath>%CommonApplicationData%\OPC Foundation\pki\own</StorePath>
<SubjectName>CN=Quickstart Console Reference Client, C=US, S=Arizona, O=OPC Foundation, DC=localhost</SubjectName>
<StorePath>%LocalApplicationData%/OPC Foundation/pki/own</StorePath>
<SubjectName>CN=Console Reference Client, C=US, S=Arizona, O=OPC Foundation, DC=localhost</SubjectName>
</ApplicationCertificate>

<!-- Where the issuer certificate are stored (certificate authorities) -->
<TrustedIssuerCertificates>
<StoreType>Directory</StoreType>
<StorePath>%CommonApplicationData%\OPC Foundation\pki\issuer</StorePath>
<StorePath>%LocalApplicationData%/OPC Foundation/pki/issuer</StorePath>
</TrustedIssuerCertificates>

<!-- Where the trust list is stored -->
<TrustedPeerCertificates>
<StoreType>Directory</StoreType>
<StorePath>%CommonApplicationData%\OPC Foundation\pki\trusted</StorePath>
<StorePath>%LocalApplicationData%/OPC Foundation/pki/trusted</StorePath>
</TrustedPeerCertificates>

<!-- The directory used to store invalid certficates for later review by the administrator. -->
<RejectedCertificateStore>
<StoreType>Directory</StoreType>
<StorePath>%CommonApplicationData%\OPC Foundation\pki\rejected</StorePath>
<StorePath>%LocalApplicationData%/OPC Foundation/pki/rejected</StorePath>
</RejectedCertificateStore>

<!-- WARNING: The following setting (to automatically accept untrusted certificates) should be used
Expand Down Expand Up @@ -70,7 +70,7 @@
</Extensions>

<TraceConfiguration>
<OutputFilePath>%CommonApplicationData%\OPC Foundation\Logs\Quickstarts.ConsoleReferenceClient.log.txt</OutputFilePath>
<OutputFilePath>%LocalApplicationData%/OPC Foundation/Logs/Quickstarts.ReferenceClient.log.txt</OutputFilePath>
<DeleteOnLoad>true</DeleteOnLoad>
<!-- Show Only Errors -->
<!-- <TraceMasks>1</TraceMasks> -->
Expand Down

0 comments on commit a147eb5

Please sign in to comment.