Skip to content

Commit 4218bb3

Browse files
committed
Add event to update session when diagnostic counters changes
1 parent e032dae commit 4218bb3

File tree

4 files changed

+151
-3
lines changed

4 files changed

+151
-3
lines changed

Libraries/Opc.Ua.Server/Session/ISessionManager.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public interface ISessionManager : IDisposable
5858
/// </summary>
5959
event SessionEventHandler SessionClosing;
6060

61+
/// <summary>
62+
/// Raised after diagnostics of an existing session were changed.
63+
/// </summary>
64+
event SessionEventHandler SessionDiagnosticsChanged;
65+
6166
/// <summary>
6267
/// Raised to signal a channel that the session is still alive.
6368
/// </summary>
@@ -141,6 +146,11 @@ ValueTask<CreateSessionResult> CreateSessionAsync(
141146
/// and that the sequence number is not out of order (update requests only).
142147
/// </remarks>
143148
OperationContext ValidateRequest(RequestHeader requestHeader, SecureChannelContext secureChannelContext, RequestType requestType);
149+
150+
/// <summary>
151+
/// Triggers the <see cref="ISessionManager.SessionDiagnosticsChanged"/> event so subscribers can react.
152+
/// </summary>
153+
void RaiseSessionDiagnosticsChangedEvent(ISession session);
144154
}
145155

146156
/// <summary>
@@ -194,6 +204,11 @@ public enum SessionEventReason
194204
/// </summary>
195205
Activated,
196206

207+
/// <summary>
208+
/// The diagnostics of an existing session were changed.
209+
/// </summary>
210+
DiagnosticsChanged,
211+
197212
/// <summary>
198213
/// A session is about to be closed.
199214
/// </summary>

Libraries/Opc.Ua.Server/Session/Session.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,6 @@ public virtual void ValidateRequest(RequestHeader requestHeader, SecureChannelCo
350350

351351
lock (m_lock)
352352
{
353-
354353
if (secureChannelContext == null || !IsSecureChannelValid(secureChannelContext.SecureChannelId))
355354
{
356355
UpdateDiagnosticCounters(requestType, true, true);
@@ -1141,6 +1140,8 @@ private void UpdateDiagnosticCounters(
11411140
bool error,
11421141
bool authorizationError)
11431142
{
1143+
ServiceCounterDataType counter = null;
1144+
11441145
lock (DiagnosticsLock)
11451146
{
11461147
if (!error)
@@ -1160,8 +1161,6 @@ private void UpdateDiagnosticCounters(
11601161
}
11611162
}
11621163

1163-
ServiceCounterDataType counter = null;
1164-
11651164
switch (requestType)
11661165
{
11671166
case RequestType.Read:
@@ -1271,6 +1270,11 @@ private void UpdateDiagnosticCounters(
12711270
}
12721271
}
12731272
}
1273+
1274+
if (counter != null)
1275+
{
1276+
m_server.SessionManager.RaiseSessionDiagnosticsChangedEvent(this);
1277+
}
12741278
}
12751279

12761280
private readonly Lock m_lock = new();

Libraries/Opc.Ua.Server/Session/SessionManager.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,17 @@ protected virtual ISession CreateSession(
571571
m_maxHistoryContinuationPoints);
572572
}
573573

574+
/// <inheritdoc />
575+
public virtual void RaiseSessionDiagnosticsChangedEvent(ISession session)
576+
{
577+
if (session == null)
578+
{
579+
throw new ArgumentNullException(nameof(session));
580+
}
581+
582+
RaiseSessionEvent(session, SessionEventReason.DiagnosticsChanged);
583+
}
584+
574585
/// <summary>
575586
/// Raises an event related to a session.
576587
/// </summary>
@@ -592,6 +603,9 @@ protected virtual void RaiseSessionEvent(ISession session, SessionEventReason re
592603
case SessionEventReason.Closing:
593604
handler = m_SessionClosing;
594605
break;
606+
case SessionEventReason.DiagnosticsChanged:
607+
handler = m_SessionDiagnosticsChanged;
608+
break;
595609
case SessionEventReason.ChannelKeepAlive:
596610
handler = m_SessionChannelKeepAlive;
597611
break;
@@ -688,6 +702,7 @@ await m_server.CloseSessionAsync(null, session.Id, false)
688702
private event SessionEventHandler m_SessionCreated;
689703
private event SessionEventHandler m_SessionActivated;
690704
private event SessionEventHandler m_SessionClosing;
705+
private event SessionEventHandler m_SessionDiagnosticsChanged;
691706
private event SessionEventHandler m_SessionChannelKeepAlive;
692707
private event ImpersonateEventHandler m_ImpersonateUser;
693708
private event EventHandler<ValidateSessionLessRequestEventArgs> m_ValidateSessionLessRequest;
@@ -730,6 +745,25 @@ public event SessionEventHandler SessionActivated
730745
}
731746
}
732747

748+
/// <inheritdoc/>
749+
public event SessionEventHandler SessionDiagnosticsChanged
750+
{
751+
add
752+
{
753+
lock (m_eventLock)
754+
{
755+
m_SessionDiagnosticsChanged += value;
756+
}
757+
}
758+
remove
759+
{
760+
lock (m_eventLock)
761+
{
762+
m_SessionDiagnosticsChanged -= value;
763+
}
764+
}
765+
}
766+
733767
/// <inheritdoc/>
734768
public event SessionEventHandler SessionClosing
735769
{
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System.Threading.Tasks;
2+
using NUnit.Framework;
3+
4+
using Assert = NUnit.Framework.Legacy.ClassicAssert;
5+
6+
namespace Opc.Ua.Server.Tests
7+
{
8+
[TestFixture]
9+
[Category("Event")]
10+
public class SessionTests
11+
{
12+
[Test]
13+
public async Task UpdateDiagnosticCounters_RaisesEvent_WhenPerRequestCounterChanged()
14+
{
15+
var fixture = new ServerFixture<StandardServer>();
16+
await fixture.StartAsync().ConfigureAwait(false);
17+
18+
try
19+
{
20+
StandardServer server = fixture.Server;
21+
22+
(RequestHeader requestHeader, SecureChannelContext secureChannelContext) =
23+
await ServerFixtureUtils.CreateAndActivateSessionAsync(server, "UpdateDiagnosticCountersTest").ConfigureAwait(false);
24+
25+
ISession session = server.CurrentInstance.SessionManager.GetSession(requestHeader.AuthenticationToken);
26+
Assert.NotNull(session, "Session should exist after Create/Activate.");
27+
28+
bool eventRaised = false;
29+
30+
server.CurrentInstance.SessionManager.SessionDiagnosticsChanged += (s, reason)
31+
=> eventRaised = true;
32+
33+
uint before = session.SessionDiagnostics.ReadCount.TotalCount;
34+
35+
// Call ValidateRequest for a request type that maps to a counter (Read).
36+
session.ValidateRequest(requestHeader, secureChannelContext, RequestType.Read);
37+
38+
Assert.IsTrue(eventRaised, "SessionDiagnosticsChanged event should be raised when a per-request counter changes.");
39+
Assert.Greater(session.SessionDiagnostics.ReadCount.TotalCount, before, "ReadCount.TotalCount should have incremented.");
40+
}
41+
finally
42+
{
43+
await fixture.StopAsync().ConfigureAwait(false);
44+
}
45+
}
46+
47+
[Test]
48+
[Category("Event")]
49+
[TestCase(RequestType.Unknown)]
50+
[TestCase(RequestType.FindServers)]
51+
[TestCase(RequestType.GetEndpoints)]
52+
[TestCase(RequestType.CreateSession)]
53+
[TestCase(RequestType.ActivateSession)]
54+
[TestCase(RequestType.CloseSession)]
55+
[TestCase(RequestType.Cancel)]
56+
public async Task UpdateDiagnosticCounters_DoesNotRaiseEvent_ForIgnoredRequestTypes(RequestType requestType)
57+
{
58+
var fixture = new ServerFixture<StandardServer>();
59+
await fixture.StartAsync().ConfigureAwait(false);
60+
61+
try
62+
{
63+
StandardServer server = fixture.Server;
64+
65+
(RequestHeader requestHeader, SecureChannelContext secureChannelContext) =
66+
await ServerFixtureUtils.CreateAndActivateSessionAsync(server, "UpdateDiagnosticCountersIgnoredTest").ConfigureAwait(false);
67+
68+
ISession session = server.CurrentInstance.SessionManager.GetSession(requestHeader.AuthenticationToken);
69+
Assert.NotNull(session, "Session should exist after Create/Activate.");
70+
71+
bool eventRaised = false;
72+
73+
server.CurrentInstance.SessionManager.SessionDiagnosticsChanged += (s, reason)
74+
=> eventRaised = true;
75+
76+
// Capture total requests before; UpdateDiagnosticCounters always increments TotalRequestCount.
77+
uint totalBefore = session.SessionDiagnostics.TotalRequestCount.TotalCount;
78+
79+
// Call ValidateRequest with one of the ignored request types.
80+
session.ValidateRequest(requestHeader, secureChannelContext, requestType);
81+
82+
Assert.AreEqual(
83+
totalBefore + 1,
84+
session.SessionDiagnostics.TotalRequestCount.TotalCount,
85+
"TotalRequestCount should increment for all request types.");
86+
87+
Assert.IsFalse(eventRaised, $"SessionDiagnosticsChanged event must NOT be raised for request type {requestType}.");
88+
}
89+
finally
90+
{
91+
await fixture.StopAsync().ConfigureAwait(false);
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)