Überwachung kürzlich aktiver Benutzer hinzugefügt

Die Klasse `EDMIService` wurde erweitert, um kürzlich aktive Benutzer zu überwachen. Eine neue `ConcurrentDictionary` namens `_RecentUsers` speichert die letzten Aktivitäten von Benutzern, die maximal 15 Minuten zurückliegen. Die Methode `GetServiceStatus` wurde angepasst, um diese Informationen bereitzustellen und ältere Einträge zu bereinigen.
Die Klasse `ServiceStatusResponse` enthält nun eine neue Eigenschaft `RecentUsers`, die die kürzlich aktiven Benutzer zurückgibt. Die Datei `GetServiceStatus.vb` wurde entfernt und durch eine neue Struktur im Namespace `Messages` ersetzt. Die Projektdatei `EDMIService.vbproj` wurde entsprechend aktualisiert.
Zusätzlich wurden die Datenkontrakte in `ServiceStatusResponse` optimiert, indem die Eigenschaften mit einer expliziten Reihenfolge (`Order`) versehen wurden.
This commit is contained in:
Developer01
2026-10-12 15:51:22 +02:00
parent 2d1b21d728
commit 205e0ad302
4 changed files with 32 additions and 19 deletions

View File

@@ -31,6 +31,9 @@ Public Class EDMIService
Public Const TBIDB_ACCESSRIGHT = "TBIDB_ACCESSRIGHT" Public Const TBIDB_ACCESSRIGHT = "TBIDB_ACCESSRIGHT"
' ── Aktive Sessions: SessionId → Username (thread-safe) ────────────────── ' ── Aktive Sessions: SessionId → Username (thread-safe) ──────────────────
Private Shared ReadOnly _ActiveSessions As New Collections.Concurrent.ConcurrentDictionary(Of String, String) Private Shared ReadOnly _ActiveSessions As New Collections.Concurrent.ConcurrentDictionary(Of String, String)
' ► NEU: Letzte Aktivität je Benutzer (für Monitoring auch nach Session-Close)
Private Shared ReadOnly _RecentUsers As New Collections.Concurrent.ConcurrentDictionary(Of String, DateTime)
Private Shared ReadOnly _RecentUserMaxAge As TimeSpan = TimeSpan.FromMinutes(15)
Public Shared ReadOnly Property ActiveSessions As Integer Public Shared ReadOnly Property ActiveSessions As Integer
Get Get
@@ -121,6 +124,8 @@ Public Class EDMIService
End If End If
_ActiveSessions(oSessionId) = _Username _ActiveSessions(oSessionId) = _Username
' ► NEU: Letzten Zugriff für diesen Benutzer aktualisieren
_RecentUsers(_Username) = DateTime.Now
' ← Neu: Session-Start loggen ' ← Neu: Session-Start loggen
_Logger.Debug("Session opened | User=[{0}] | SessionId=[{1}] | ActiveSessions=[{2}]", _Logger.Debug("Session opened | User=[{0}] | SessionId=[{1}] | ActiveSessions=[{2}]",
_Username, oSessionId, _ActiveSessions.Count) _Username, oSessionId, _ActiveSessions.Count)
@@ -160,15 +165,29 @@ Public Class EDMIService
''' Returns a snapshot of all currently active sessions for monitoring purposes ''' Returns a snapshot of all currently active sessions for monitoring purposes
''' </summary> ''' </summary>
Public Function GetServiceStatus() As Messages.ServiceStatusResponse Implements IEDMIService.GetServiceStatus Public Function GetServiceStatus() As Messages.ServiceStatusResponse Implements IEDMIService.GetServiceStatus
_Logger.Debug("GetServiceStatus called by User=[{0}]", _Username) ' Aktuell offene Sessions
' Snapshot nur einmal erstellen, nicht zweimal iterieren:
Dim oSnapshot = _ActiveSessions.ToArray() Dim oSnapshot = _ActiveSessions.ToArray()
' ► NEU: Kürzlich aktive Benutzer (max. 15 Min. alt) bereinigen und zurückgeben
Dim oCutoff = DateTime.Now.Subtract(_RecentUserMaxAge)
Dim oStaleKeys = _RecentUsers.Where(Function(p) p.Value < oCutoff).Select(Function(p) p.Key).ToList()
For Each oKey In oStaleKeys
Dim oIgnored As DateTime
_RecentUsers.TryRemove(oKey, oIgnored)
Next
Dim oRecentUserList = _RecentUsers.
OrderByDescending(Function(p) p.Value).
Select(Function(p) $"{p.Key} (zuletzt: {p.Value:HH:mm:ss})").
ToList()
Return New Messages.ServiceStatusResponse With { Return New Messages.ServiceStatusResponse With {
.ActiveSessionCount = oSnapshot.Length, .ActiveSessionCount = oSnapshot.Length,
.ActiveUsers = oSnapshot.Select(Function(p) p.Value).Distinct().OrderBy(Function(u) u).ToList(), .ActiveUsers = oSnapshot.Select(Function(p) p.Value).Distinct().OrderBy(Function(u) u).ToList(),
.ActiveSessions = oSnapshot.ToDictionary(Function(p) p.Key, Function(p) p.Value), .ActiveSessions = oSnapshot.ToDictionary(Function(p) p.Key, Function(p) p.Value),
.Timestamp = DateTime.Now .Timestamp = DateTime.Now,
} .RecentUsers = oRecentUserList ' ◄ NEU – im Response-Objekt ergänzen
}
End Function End Function
#End Region #End Region

View File

@@ -155,7 +155,6 @@
<Compile Include="BaseMethod.vb" /> <Compile Include="BaseMethod.vb" />
<Compile Include="ClassConstants.vb" /> <Compile Include="ClassConstants.vb" />
<Compile Include="Config.vb" /> <Compile Include="Config.vb" />
<Compile Include="GetServiceStatus.vb" />
<Compile Include="Messages\GetServiceStatus.vb" /> <Compile Include="Messages\GetServiceStatus.vb" />
<Compile Include="Methods\Base\GetClientConfig\GetClientConfigMethod.vb" /> <Compile Include="Methods\Base\GetClientConfig\GetClientConfigMethod.vb" />
<Compile Include="Methods\Base\GetClientConfig\GetClientConfigResponse.vb" /> <Compile Include="Methods\Base\GetClientConfig\GetClientConfigResponse.vb" />

View File

@@ -1,6 +0,0 @@
Imports System.Runtime.Serialization
Public Class GetServiceStatus
End Class

View File

@@ -1,11 +1,12 @@
Imports System.Runtime.Serialization Imports System.Runtime.Serialization
Namespace Messages Namespace Messages
<DataContract> <DataContract(Name:="ServiceStatusResponse", [Namespace]:="http://schemas.datacontract.org/2004/07/DigitalData.Services.EDMIService.Messages")>
Public Class ServiceStatusResponse Public Class ServiceStatusResponse
<DataMember> Public Property ActiveSessionCount As Integer <DataMember(Order:=1)> Public Property ActiveSessionCount As Integer
<DataMember> Public Property ActiveUsers As List(Of String) ' Distinct, sortiert <DataMember(Order:=2)> Public Property ActiveUsers As List(Of String)
<DataMember> Public Property ActiveSessions As Dictionary(Of String, String) ' SessionId → Username <DataMember(Order:=3)> Public Property ActiveSessions As Dictionary(Of String, String)
<DataMember> Public Property Timestamp As DateTime <DataMember(Order:=4)> Public Property Timestamp As DateTime
<DataMember(Order:=5)> Public Property RecentUsers As List(Of String) = New List(Of String)()
End Class End Class
End Namespace End Namespace