Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log threads #379

Merged
merged 6 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/OpcPlcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ namespace OpcPlc;

public class OpcPlcServer
{
private const int DefaultMinThreads = 20;
private const int DefaultCompletionPortThreads = 20;

private string[] _args;
private CancellationTokenSource _cancellationTokenSource;
private ImmutableList<IPluginNodes> _pluginNodes;
Expand Down Expand Up @@ -87,9 +90,16 @@ public async Task StartAsync(string[] args, CancellationToken cancellationToken

LogLogo();

Logger.LogInformation("Current directory: {currentDirectory}", Directory.GetCurrentDirectory());
Logger.LogInformation("Log file: {logFileName}", Path.GetFullPath(Config.LogFileName));
Logger.LogInformation("Log level: {logLevel}", Config.LogLevelCli);
ThreadPool.SetMinThreads(DefaultMinThreads, DefaultCompletionPortThreads);
ThreadPool.GetMinThreads(out int minWorkerThreads, out int minCompletionPortThreads);
Logger.LogInformation(
"Min worker threads: {MinWorkerThreads}, min completion port threads: {MinCompletionPortThreads}",
minWorkerThreads,
minCompletionPortThreads);

Logger.LogInformation("Current directory: {CurrentDirectory}", Directory.GetCurrentDirectory());
Logger.LogInformation("Log file: {LogFileName}", Path.GetFullPath(Config.LogFileName));
Logger.LogInformation("Log level: {LogLevel}", Config.LogLevelCli);

// Show OPC PLC version.
var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
Expand Down
159 changes: 124 additions & 35 deletions src/PlcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace OpcPlc;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;

Expand Down Expand Up @@ -50,10 +51,25 @@ public PlcServer(OpcPlcConfiguration config, PlcSimulation plcSimulation, TimeSe
(state) => {
try
{
var curProc = Process.GetCurrentProcess();

ThreadPool.GetAvailableThreads(out int availWorkerThreads, out int availCompletionPortThreads);

_logger.LogInformation(
"Open sessions: {Sessions}, open subscriptions: {Subscriptions}",
"\n\t# Open sessions: {Sessions}\n" +
"\t# Open subscriptions: {Subscriptions}\n" +
"\t# Monitored items: {MonitoredItems:N0}\n" +
"\t# Working set {WorkingSet:N0} MB\n" +
"\t# Available worker threads: {AvailWorkerThreads:N0}\n" +
"\t# Available completion port threads: {AvailCompletionPortThreads:N0}\n" +
"\t# Thread count: {ThreadCount:N0}",
ServerInternal.SessionManager.GetSessions().Count,
ServerInternal.SubscriptionManager.GetSubscriptions().Count);
ServerInternal.SubscriptionManager.GetSubscriptions().Count,
ServerInternal.SubscriptionManager.GetSubscriptions().Sum(s => s.MonitoredItemCount),
curProc.WorkingSet64 / 1024 / 1024,
availWorkerThreads,
availCompletionPortThreads,
curProc.Threads.Count);
}
catch
{
Expand Down Expand Up @@ -148,6 +164,9 @@ public override ResponseHeader CreateMonitoredItems(
out MonitoredItemCreateResultCollection results,
out DiagnosticInfoCollection diagnosticInfos)
{
results = default;
diagnosticInfos = default;

try
{
OperationContext context = ValidateRequest(requestHeader, RequestType.CreateMonitoredItems);
Expand All @@ -164,9 +183,43 @@ public override ResponseHeader CreateMonitoredItems(

return responseHeader;
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadNoSubscription)
{
MetricsHelper.RecordTotalErrors(nameof(CreateMonitoredItems));

_logger.LogDebug(
ex,
"Failed creating monitored items: {StatusCode}",
StatusCodes.BadNoSubscription.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadNoSubscription };
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadSessionIdInvalid)
{
MetricsHelper.RecordTotalErrors(nameof(CreateMonitoredItems));

_logger.LogDebug(
ex,
"Failed creating monitored items: {StatusCode}",
StatusCodes.BadSessionIdInvalid.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadSessionIdInvalid };
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadSecureChannelIdInvalid)
{
MetricsHelper.RecordTotalErrors(nameof(CreateMonitoredItems));

_logger.LogDebug(
ex,
"Failed creating monitored items: {StatusCode}",
StatusCodes.BadSecureChannelIdInvalid.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadSecureChannelIdInvalid };
}
catch (Exception ex)
{
MetricsHelper.RecordTotalErrors(nameof(CreateMonitoredItems));

_logger.LogError(ex, "Error creating monitored items");
throw;
}
Expand All @@ -182,6 +235,13 @@ public override ResponseHeader Publish(
out StatusCodeCollection results,
out DiagnosticInfoCollection diagnosticInfos)
{
subscriptionId = default;
availableSequenceNumbers = default;
moreNotifications = default;
notificationMessage = default;
results = default;
diagnosticInfos = default;

try
{
OperationContext context = ValidateRequest(requestHeader, RequestType.Publish);
Expand Down Expand Up @@ -216,48 +276,40 @@ public override ResponseHeader Publish(

return responseHeader;
}
catch (ServiceResultException ex)
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadNoSubscription)
{
MetricsHelper.RecordTotalErrors(nameof(Publish));

subscriptionId = default;
availableSequenceNumbers = default;
moreNotifications = default;
notificationMessage = default;
results = default;
diagnosticInfos = default;

if (ex.StatusCode == StatusCodes.BadNoSubscription)
{
_logger.LogDebug(
"Failed to publish: {StatusCode}",
StatusCodes.BadNoSubscription.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadNoSubscription };
}
_logger.LogDebug(
ex,
"Failed to publish: {StatusCode}",
StatusCodes.BadNoSubscription.ToString());

if (ex.StatusCode == StatusCodes.BadSessionIdInvalid)
{
_logger.LogDebug(
"Failed to publish: {StatusCode}",
StatusCodes.BadSessionIdInvalid.ToString());
return new ResponseHeader { ServiceResult = StatusCodes.BadNoSubscription };
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadSessionIdInvalid)
{
MetricsHelper.RecordTotalErrors(nameof(Publish));

return new ResponseHeader { ServiceResult = StatusCodes.BadSessionIdInvalid };
}
_logger.LogDebug(
ex,
"Failed to publish: {StatusCode}",
StatusCodes.BadSessionIdInvalid.ToString());

if (ex.StatusCode == StatusCodes.BadSecureChannelIdInvalid)
{
_logger.LogDebug(
"Failed to publish: {StatusCode}",
StatusCodes.BadSecureChannelIdInvalid.ToString());
return new ResponseHeader { ServiceResult = StatusCodes.BadSessionIdInvalid };
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadSecureChannelIdInvalid)
{
MetricsHelper.RecordTotalErrors(nameof(Publish));

return new ResponseHeader { ServiceResult = StatusCodes.BadSecureChannelIdInvalid };
}
_logger.LogDebug(
ex,
"Failed to publish: {StatusCode}",
StatusCodes.BadSecureChannelIdInvalid.ToString());

_logger.LogError(ex, "Error publishing");
throw;
return new ResponseHeader { ServiceResult = StatusCodes.BadSecureChannelIdInvalid };
}
catch(Exception ex)
catch (Exception ex)
{
MetricsHelper.RecordTotalErrors(nameof(Publish));

Expand All @@ -274,6 +326,9 @@ public override ResponseHeader Read(
out DataValueCollection results,
out DiagnosticInfoCollection diagnosticInfos)
{
results = default;
diagnosticInfos = default;

try
{
var responseHeader = base.Read(requestHeader, maxAge, timestampsToReturn, nodesToRead, out results, out diagnosticInfos);
Expand All @@ -282,9 +337,43 @@ public override ResponseHeader Read(

return responseHeader;
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadNoSubscription)
{
MetricsHelper.RecordTotalErrors(nameof(Read));

_logger.LogDebug(
ex,
"Failed to read: {StatusCode}",
StatusCodes.BadNoSubscription.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadNoSubscription };
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadSessionIdInvalid)
{
MetricsHelper.RecordTotalErrors(nameof(Read));

_logger.LogDebug(
ex,
"Failed to read: {StatusCode}",
StatusCodes.BadSessionIdInvalid.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadSessionIdInvalid };
}
catch (ServiceResultException ex) when (ex.StatusCode == StatusCodes.BadSecureChannelIdInvalid)
{
MetricsHelper.RecordTotalErrors(nameof(Read));

_logger.LogDebug(
ex,
"Failed to read: {StatusCode}",
StatusCodes.BadSecureChannelIdInvalid.ToString());

return new ResponseHeader { ServiceResult = StatusCodes.BadSecureChannelIdInvalid };
}
catch (Exception ex)
{
MetricsHelper.RecordTotalErrors(nameof(Read));

_logger.LogError(ex, "Error reading");
throw;
}
Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "2.12.19",
"version": "2.12.20",
"versionHeightOffset": -1,
"publicReleaseRefSpec": [
"^refs/heads/main$",
Expand Down
Loading