Ü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"
' ── Aktive Sessions: SessionId → Username (thread-safe) ──────────────────
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
Get
@@ -121,6 +124,8 @@ Public Class EDMIService
End If
_ActiveSessions(oSessionId) = _Username
' ► NEU: Letzten Zugriff für diesen Benutzer aktualisieren
_RecentUsers(_Username) = DateTime.Now
' ← Neu: Session-Start loggen
_Logger.Debug("Session opened | User=[{0}] | SessionId=[{1}] | ActiveSessions=[{2}]",
_Username, oSessionId, _ActiveSessions.Count)
@@ -160,15 +165,29 @@ Public Class EDMIService
''' Returns a snapshot of all currently active sessions for monitoring purposes
''' </summary>
Public Function GetServiceStatus() As Messages.ServiceStatusResponse Implements IEDMIService.GetServiceStatus
_Logger.Debug("GetServiceStatus called by User=[{0}]", _Username)
' Snapshot nur einmal erstellen, nicht zweimal iterieren:
' Aktuell offene Sessions
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 {
.ActiveSessionCount = oSnapshot.Length,
.ActiveUsers = oSnapshot.Select(Function(p) p.Value).Distinct().OrderBy(Function(u) u).ToList(),
.ActiveSessions = oSnapshot.ToDictionary(Function(p) p.Key, Function(p) p.Value),
.Timestamp = DateTime.Now
}
.ActiveSessionCount = oSnapshot.Length,
.ActiveUsers = oSnapshot.Select(Function(p) p.Value).Distinct().OrderBy(Function(u) u).ToList(),
.ActiveSessions = oSnapshot.ToDictionary(Function(p) p.Key, Function(p) p.Value),
.Timestamp = DateTime.Now,
.RecentUsers = oRecentUserList ' ◄ NEU – im Response-Objekt ergänzen
}
End Function
#End Region

View File

@@ -155,7 +155,6 @@
<Compile Include="BaseMethod.vb" />
<Compile Include="ClassConstants.vb" />
<Compile Include="Config.vb" />
<Compile Include="GetServiceStatus.vb" />
<Compile Include="Messages\GetServiceStatus.vb" />
<Compile Include="Methods\Base\GetClientConfig\GetClientConfigMethod.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
Namespace Messages
<DataContract>
<DataContract(Name:="ServiceStatusResponse", [Namespace]:="http://schemas.datacontract.org/2004/07/DigitalData.Services.EDMIService.Messages")>
Public Class ServiceStatusResponse
<DataMember> Public Property ActiveSessionCount As Integer
<DataMember> Public Property ActiveUsers As List(Of String) ' Distinct, sortiert
<DataMember> Public Property ActiveSessions As Dictionary(Of String, String) ' SessionId → Username
<DataMember> Public Property Timestamp As DateTime
<DataMember(Order:=1)> Public Property ActiveSessionCount As Integer
<DataMember(Order:=2)> Public Property ActiveUsers As List(Of String)
<DataMember(Order:=3)> Public Property ActiveSessions As Dictionary(Of String, String)
<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 Namespace