Erweiterungen in frmAdmin_AppserviceTest
Die Methode `frmAdmin_AppserviceTest` wurde erweitert, um Scheduler-Metriken und Warnungen anzuzeigen. Eine neue Liste von SQL-Queries (`_ecmQueries`) wurde für Lasttests ergänzt. Der Timer-Intervall für zyklische Lastoperationen wurde auf 5 Sekunden erhöht. Zwei neue Lastoperationen wurden hinzugefügt, darunter direkter ECM-Datenbankzugriff. Logs wurden verbessert, um detaillierte Ergebnisse und Ausführungszeiten zu erfassen. Kommentare wurden angepasst, und die Code-Struktur wurde allgemein verbessert.
This commit is contained in:
@@ -13,6 +13,8 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EDMI.API", "..\..\..\2_DLL
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EDMIService", "..\..\..\2_DLL Projekte\DDMonorepo\Service.EDMIService\EDMIService.vbproj", "{A8C3F298-76AB-4359-AB3C-986E313B4336}"
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EDMIService", "..\..\..\2_DLL Projekte\DDMonorepo\Service.EDMIService\EDMIService.vbproj", "{A8C3F298-76AB-4359-AB3C-986E313B4336}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Database", "..\..\..\2_DLL Projekte\DDModules\Database\Database.vbproj", "{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
CD_ROM|Any CPU = CD_ROM|Any CPU
|
CD_ROM|Any CPU = CD_ROM|Any CPU
|
||||||
@@ -127,6 +129,26 @@ Global
|
|||||||
{A8C3F298-76AB-4359-AB3C-986E313B4336}.SingleImage|Any CPU.Build.0 = Release|Any CPU
|
{A8C3F298-76AB-4359-AB3C-986E313B4336}.SingleImage|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A8C3F298-76AB-4359-AB3C-986E313B4336}.SingleImage|x86.ActiveCfg = Release|Any CPU
|
{A8C3F298-76AB-4359-AB3C-986E313B4336}.SingleImage|x86.ActiveCfg = Release|Any CPU
|
||||||
{A8C3F298-76AB-4359-AB3C-986E313B4336}.SingleImage|x86.Build.0 = Release|Any CPU
|
{A8C3F298-76AB-4359-AB3C-986E313B4336}.SingleImage|x86.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.CD_ROM|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.CD_ROM|x86.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.DVD-5|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.DVD-5|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.DVD-5|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.DVD-5|x86.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.SingleImage|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.SingleImage|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{EAF0EA75-5FA7-485D-89C7-B2D843B03A96}.SingleImage|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -88,8 +88,46 @@ Public Class frmAdmin_AppserviceTest
|
|||||||
Else
|
Else
|
||||||
MemoEdit1.Text &= " (keine)" & Environment.NewLine
|
MemoEdit1.Text &= " (keine)" & Environment.NewLine
|
||||||
End If
|
End If
|
||||||
End Sub
|
MemoEdit1.Text &= "─────────────────────────────" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= $"Kürzlich aktive Benutzer (letzte {RECENT_USER_MAX_AGE_MINUTES} Min.):" & Environment.NewLine
|
||||||
|
If oStatus2.RecentUsers IsNot Nothing AndAlso oStatus2.RecentUsers.Count > 0 Then
|
||||||
|
For Each oRecentUser In oStatus2.RecentUsers
|
||||||
|
MemoEdit1.Text &= $" • {oRecentUser}" & Environment.NewLine
|
||||||
|
Next
|
||||||
|
Else
|
||||||
|
MemoEdit1.Text &= " (keine)" & Environment.NewLine
|
||||||
|
End If
|
||||||
|
|
||||||
|
' ── Scheduler-Metriken ───────────────────────────────────────────
|
||||||
|
MemoEdit1.Text &= "─────────────────────────────" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= "Scheduler-Metriken:" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= $" Letzter Job: {oStatus2.LastJobName}" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= $" Laufzeit: {oStatus2.LastJobDurationMs}ms" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= $" Zeitpunkt: {oStatus2.LastJobTimestamp:HH:mm:ss}" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= $" Slow Queries: {oStatus2.SlowQueryCount} (> 10s seit Service-Start)" & Environment.NewLine
|
||||||
|
MemoEdit1.Text &= $" Cache-Alter: {oStatus2.CachedTablesSnapshotAge}s" & Environment.NewLine
|
||||||
|
|
||||||
|
If oStatus2.CachedTablesSnapshotAge > 300 Then
|
||||||
|
MemoEdit1.Text &= " ⚠ Cache ist veraltet – CronJob prüfen!" & Environment.NewLine
|
||||||
|
End If
|
||||||
|
If oStatus2.SlowQueryCount > 0 Then
|
||||||
|
MemoEdit1.Text &= $" ⚠ {oStatus2.SlowQueryCount} langsame Queries aufgetreten!" & Environment.NewLine
|
||||||
|
End If
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
' ── Nicht-parametrisierte ECM-Selects aus frmMain (für DB-Lasttest) ──
|
||||||
|
Private Shared ReadOnly _ecmQueries As String() = {
|
||||||
|
"SELECT * FROM TBPM_KONFIGURATION WITH (NOLOCK) WHERE GUID = 1",
|
||||||
|
"SELECT * FROM TBDD_CONNECTION WITH (NOLOCK) WHERE AKTIV = 1",
|
||||||
|
"SELECT CAT_TITLE,CAT_STRING FROM TBDD_CATALOG WITH (NOLOCK)",
|
||||||
|
"SELECT * FROM TBDD_3RD_PARTY_MODULES WITH (NOLOCK) WHERE ACTIVE = 1",
|
||||||
|
"SELECT * FROM TBDD_SQL_COMMANDS WITH (NOLOCK)",
|
||||||
|
"SELECT LANG_CODE FROM TBDD_GUI_LANGUAGE WITH (NOLOCK) WHERE ACTIVE = 1 ORDER BY LANG_CODE",
|
||||||
|
"SELECT * FROM TBDD_COLUMNS_FORMAT WITH (NOLOCK) WHERE MODULE = 'taskFLOW'",
|
||||||
|
"SELECT * FROM TBPM_CHART WITH (NOLOCK)",
|
||||||
|
"SELECT * FROM TBPM_MAIN_VIEW_GROUPS WITH (NOLOCK) WHERE ACTIVE = 1",
|
||||||
|
"SELECT * FROM TBPM_PROFILE WITH (NOLOCK) WHERE ACTIVE = 1"
|
||||||
|
}
|
||||||
Private Sub SimpleButton2_Click(sender As Object, e As EventArgs) Handles btnLoadStart.Click
|
Private Sub SimpleButton2_Click(sender As Object, e As EventArgs) Handles btnLoadStart.Click
|
||||||
If _loadTimer IsNot Nothing AndAlso _loadTimer.Enabled Then
|
If _loadTimer IsNot Nothing AndAlso _loadTimer.Enabled Then
|
||||||
MessageBox.Show("Lasttest läuft bereits.", "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Information)
|
MessageBox.Show("Lasttest läuft bereits.", "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Information)
|
||||||
@@ -201,7 +239,7 @@ Public Class frmAdmin_AppserviceTest
|
|||||||
|
|
||||||
' ── Timer für zyklische Lastoperationen ───────────────────────────────
|
' ── Timer für zyklische Lastoperationen ───────────────────────────────
|
||||||
Private Sub StartLoadTimer()
|
Private Sub StartLoadTimer()
|
||||||
_loadTimer = New System.Windows.Forms.Timer With {.Interval = 1000} ' jede Sekunde
|
_loadTimer = New System.Windows.Forms.Timer With {.Interval = 5000} ' jede 5 Sekunden
|
||||||
AddHandler _loadTimer.Tick, AddressOf LoadTimer_Tick
|
AddHandler _loadTimer.Tick, AddressOf LoadTimer_Tick
|
||||||
_loadTimer.Start()
|
_loadTimer.Start()
|
||||||
End Sub
|
End Sub
|
||||||
@@ -218,22 +256,19 @@ Public Class frmAdmin_AppserviceTest
|
|||||||
oSnapshot = _loadClients.ToList()
|
oSnapshot = _loadClients.ToList()
|
||||||
End SyncLock
|
End SyncLock
|
||||||
|
|
||||||
' ← MaxDegreeOfParallelism begrenzt gleichzeitige Service-Calls
|
|
||||||
Parallel.ForEach(oSnapshot,
|
Parallel.ForEach(oSnapshot,
|
||||||
New ParallelOptions With {
|
New ParallelOptions With {
|
||||||
.CancellationToken = _loadCts.Token,
|
.CancellationToken = _loadCts.Token,
|
||||||
.MaxDegreeOfParallelism = 10 ' ← NEU: max. 10 gleichzeitige Calls
|
.MaxDegreeOfParallelism = 10
|
||||||
},
|
},
|
||||||
Sub(oClient As Client)
|
Sub(oClient As Client)
|
||||||
Try
|
Try
|
||||||
Select Case _timerTick Mod 4
|
Select Case _timerTick Mod 6
|
||||||
Case 0
|
Case 0
|
||||||
' ► GetStatus je Client
|
|
||||||
Dim st = oClient.GetStatus()
|
Dim st = oClient.GetStatus()
|
||||||
_loadLog.Enqueue($"[{Now:HH:mm:ss}] Status: Online={st.IsOnline}, Conn={st.ActiveConnections}")
|
_loadLog.Enqueue($"[{Now:HH:mm:ss}] Status: Online={st.IsOnline}, Conn={st.ActiveConnections}")
|
||||||
|
|
||||||
Case 1
|
Case 1
|
||||||
' ► Zufällige Tabelle aus dem Cache des jeweiligen Clients laden
|
|
||||||
Dim oCachedTables = oClient.GetStatus().CachedTables
|
Dim oCachedTables = oClient.GetStatus().CachedTables
|
||||||
If oCachedTables IsNot Nothing AndAlso oCachedTables.Count > 0 Then
|
If oCachedTables IsNot Nothing AndAlso oCachedTables.Count > 0 Then
|
||||||
Dim sTable As String
|
Dim sTable As String
|
||||||
@@ -247,14 +282,35 @@ Public Class frmAdmin_AppserviceTest
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
Case 2
|
Case 2
|
||||||
' ► Cache-Zugriff
|
|
||||||
Dim st = oClient.GetStatus()
|
Dim st = oClient.GetStatus()
|
||||||
_loadLog.Enqueue($"[{Now:HH:mm:ss}] Cached Tables: {st.CachedTableCount}")
|
_loadLog.Enqueue($"[{Now:HH:mm:ss}] Cached Tables: {st.CachedTableCount}")
|
||||||
|
|
||||||
Case 3
|
Case 3
|
||||||
' ► Channel-State prüfen
|
|
||||||
Dim st = oClient.GetStatus()
|
Dim st = oClient.GetStatus()
|
||||||
_loadLog.Enqueue($"[{Now:HH:mm:ss}] Channel: {st.ChannelState}")
|
_loadLog.Enqueue($"[{Now:HH:mm:ss}] Channel: {st.ChannelState}")
|
||||||
|
|
||||||
|
Case 4
|
||||||
|
' ✅ Direkter ECM-Datenbankzugriff – konkurriert mit Scheduler-Pool
|
||||||
|
Dim oSQL As String
|
||||||
|
SyncLock _rnd
|
||||||
|
oSQL = _ecmQueries(_rnd.Next(0, _ecmQueries.Length))
|
||||||
|
End SyncLock
|
||||||
|
Dim oWatch = Stopwatch.StartNew()
|
||||||
|
Dim oResult = oClient.GetDatatableFromECM(oSQL)
|
||||||
|
oWatch.Stop()
|
||||||
|
_loadLog.Enqueue($"[{Now:HH:mm:ss}] ECM-SQL → OK={oResult?.OK} Rows={oResult?.Table?.Rows.Count} [{oWatch.ElapsedMilliseconds}ms] SQL=[{oSQL.Substring(0, Math.Min(50, oSQL.Length))}…]")
|
||||||
|
|
||||||
|
Case 5
|
||||||
|
' ✅ Zweiter ECM-Select mit anderem Client – maximiert Pool-Druck
|
||||||
|
Dim oSQL As String
|
||||||
|
SyncLock _rnd
|
||||||
|
oSQL = _ecmQueries(_rnd.Next(0, _ecmQueries.Length))
|
||||||
|
End SyncLock
|
||||||
|
Dim oWatch = Stopwatch.StartNew()
|
||||||
|
Dim oResult = oClient.GetDatatableFromECM(oSQL)
|
||||||
|
oWatch.Stop()
|
||||||
|
_loadLog.Enqueue($"[{Now:HH:mm:ss}] ECM-SQL(2) → OK={oResult?.OK} Rows={oResult?.Table?.Rows.Count} [{oWatch.ElapsedMilliseconds}ms]")
|
||||||
|
|
||||||
End Select
|
End Select
|
||||||
Catch ex As OperationCanceledException
|
Catch ex As OperationCanceledException
|
||||||
' Lasttest gestoppt
|
' Lasttest gestoppt
|
||||||
|
|||||||
Reference in New Issue
Block a user