Ü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:
@@ -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,14 +165,28 @@ 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
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
Imports System.Runtime.Serialization
|
|
||||||
|
|
||||||
Public Class GetServiceStatus
|
|
||||||
|
|
||||||
|
|
||||||
End Class
|
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user