Added query cache entry count and capacity to front-end, Fixed ServerGetStatsResult field naming
This commit is contained in:
@@ -286,7 +286,7 @@ public class SearchdomainController : ControllerBase
|
||||
{
|
||||
(Searchdomain? searchdomain_, int? httpStatusCode, string? message) = SearchdomainHelper.TryGetSearchdomain(_domainManager, searchdomain, _logger);
|
||||
if (searchdomain_ is null || httpStatusCode is not null) return StatusCode(httpStatusCode ?? 500, new SearchdomainUpdateResults(){Success = false, Message = message});
|
||||
long sizeInBytes = DatabaseHelper.GetSearchdomainDatabaseSize(searchdomain_.helper, searchdomain);
|
||||
return Ok(new SearchdomainGetDatabaseSizeResult() { SearchdomainDatabaseSizeBytes = sizeInBytes, Success = true });
|
||||
long EmbeddingCacheUtilization = DatabaseHelper.GetSearchdomainDatabaseSize(searchdomain_.helper, searchdomain);
|
||||
return Ok(new SearchdomainGetDatabaseSizeResult() { SearchdomainDatabaseSizeBytes = EmbeddingCacheUtilization, Success = true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ public class ServerController : ControllerBase
|
||||
var sqlHelper = DatabaseHelper.GetSQLHelper(_options.Value);
|
||||
Task<long> entityCountTask = DatabaseHelper.CountEntities(sqlHelper);
|
||||
long queryCacheUtilization = 0;
|
||||
long queryCacheElementCount = 0;
|
||||
long queryCacheMaxElementCountAll = 0;
|
||||
long queryCacheMaxElementCountLoadedSearchdomainsOnly = 0;
|
||||
foreach (string searchdomain in _searchdomainManager.ListSearchdomains())
|
||||
{
|
||||
if (SearchdomainHelper.IsSearchdomainLoaded(_searchdomainManager, searchdomain))
|
||||
@@ -87,10 +90,29 @@ public class ServerController : ControllerBase
|
||||
(Searchdomain? searchdomain_, int? httpStatusCode, string? message) = SearchdomainHelper.TryGetSearchdomain(_searchdomainManager, searchdomain, _logger);
|
||||
if (searchdomain_ is null || httpStatusCode is not null) return StatusCode(httpStatusCode ?? 500, new ServerGetStatsResult(){Success = false, Message = message});
|
||||
queryCacheUtilization += searchdomain_.GetSearchCacheSize();
|
||||
queryCacheElementCount += searchdomain_.queryCache.Count;
|
||||
queryCacheMaxElementCountAll += searchdomain_.queryCache.Capacity;
|
||||
queryCacheMaxElementCountLoadedSearchdomainsOnly += searchdomain_.queryCache.Capacity;
|
||||
} else
|
||||
{
|
||||
var searchdomainSettings = DatabaseHelper.GetSearchdomainSettings(sqlHelper, searchdomain);
|
||||
queryCacheMaxElementCountAll += searchdomainSettings.QueryCacheSize;
|
||||
}
|
||||
};
|
||||
long entityCount = await entityCountTask;
|
||||
return new ServerGetStatsResult() { Success = true, EntityCount = entityCount, QueryCacheUtilization = queryCacheUtilization, SizeInBytes = size, MaxElementCount = _searchdomainManager.EmbeddingCacheMaxCount, ElementCount = elementCount, EmbeddingsCount = embeddingsCount};
|
||||
|
||||
return new ServerGetStatsResult() {
|
||||
Success = true,
|
||||
EntityCount = entityCount,
|
||||
QueryCacheUtilization = queryCacheUtilization,
|
||||
QueryCacheElementCount = queryCacheElementCount,
|
||||
QueryCacheMaxElementCountAll = queryCacheMaxElementCountAll,
|
||||
QueryCacheMaxElementCountLoadedSearchdomainsOnly = queryCacheMaxElementCountLoadedSearchdomainsOnly,
|
||||
EmbeddingCacheUtilization = size,
|
||||
EmbeddingCacheMaxElementCount = _searchdomainManager.EmbeddingCacheMaxCount,
|
||||
EmbeddingCacheElementCount = elementCount,
|
||||
EmbeddingsCount = embeddingsCount
|
||||
};
|
||||
} catch (Exception ex)
|
||||
{
|
||||
ElmahExtensions.RaiseError(ex);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Configuration;
|
||||
using System.Data.Common;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Server.Exceptions;
|
||||
using Server.Models;
|
||||
@@ -244,4 +245,22 @@ public class DatabaseHelper(ILogger<DatabaseHelper> logger)
|
||||
searchdomainSumReader.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SearchdomainSettings GetSearchdomainSettings(SQLHelper helper, string searchdomain)
|
||||
{
|
||||
Dictionary<string, dynamic> parameters = new()
|
||||
{
|
||||
["name"] = searchdomain
|
||||
};
|
||||
DbDataReader reader = helper.ExecuteSQLCommand("SELECT settings from searchdomain WHERE name = @name", parameters);
|
||||
try
|
||||
{
|
||||
reader.Read();
|
||||
string settingsString = reader.GetString(0);
|
||||
return JsonSerializer.Deserialize<SearchdomainSettings>(settingsString);
|
||||
} finally
|
||||
{
|
||||
reader.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,4 +300,19 @@
|
||||
<data name="Unable to fetch searchdomain database utilization" xml:space="preserve">
|
||||
<value>Searchdomain Datenbank-Auslastung konnte nicht abgerufen werden</value>
|
||||
</data>
|
||||
<data name="Query cache entry count" xml:space="preserve">
|
||||
<value>Query-Cache Einträge</value>
|
||||
</data>
|
||||
<data name="Query cache capacity (all)" xml:space="preserve">
|
||||
<value>Query-Cache Kapazität (alle)</value>
|
||||
</data>
|
||||
<data name="queryCacheEntryCountAllInfo" xml:space="preserve">
|
||||
<value>Anzahl der Einträge, die insgesamt in den Query-Cache passen. Ungeladene Searchdomains werden berücksichtigt.</value>
|
||||
</data>
|
||||
<data name="Query cache capacity (loaded)" xml:space="preserve">
|
||||
<value>Query-Cache Kapazität (geladen)</value>
|
||||
</data>
|
||||
<data name="queryCacheEntryCountLoadedInfo" xml:space="preserve">
|
||||
<value>Anzahl der Einträge, die insgesamt in den Query-Cache der geladenen Searchdomains passen.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -300,4 +300,19 @@
|
||||
<data name="Unable to fetch searchdomain database utilization" xml:space="preserve">
|
||||
<value>Unable to fetch searchdomain database utilization</value>
|
||||
</data>
|
||||
<data name="Query cache entry count" xml:space="preserve">
|
||||
<value>Query cache entry count</value>
|
||||
</data>
|
||||
<data name="Query cache capacity (all)" xml:space="preserve">
|
||||
<value>Query cache capacity (all)</value>
|
||||
</data>
|
||||
<data name="queryCacheEntryCountAllInfo" xml:space="preserve">
|
||||
<value>Number of query cache entries that can be stored in the query cache, including searchdomains that are currently not loaded.</value>
|
||||
</data>
|
||||
<data name="Query cache capacity (loaded)" xml:space="preserve">
|
||||
<value>Query cache capacity (loaded)</value>
|
||||
</data>
|
||||
<data name="queryCacheEntryCountLoadedInfo" xml:space="preserve">
|
||||
<value>Number of query cache entries that can be stored in the query cache of all loaded searchdomains.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -278,15 +278,7 @@ public class Searchdomain
|
||||
|
||||
public SearchdomainSettings GetSettings()
|
||||
{
|
||||
Dictionary<string, dynamic> parameters = new()
|
||||
{
|
||||
["name"] = searchdomain
|
||||
};
|
||||
DbDataReader reader = helper.ExecuteSQLCommand("SELECT settings from searchdomain WHERE name = @name", parameters);
|
||||
reader.Read();
|
||||
string settingsString = reader.GetString(0);
|
||||
reader.Close();
|
||||
return JsonSerializer.Deserialize<SearchdomainSettings>(settingsString);
|
||||
return DatabaseHelper.GetSearchdomainSettings(helper, searchdomain);
|
||||
}
|
||||
|
||||
public void ReconciliateOrInvalidateCacheForNewOrUpdatedEntity(Entity entity)
|
||||
@@ -343,13 +335,13 @@ public class Searchdomain
|
||||
|
||||
public long GetSearchCacheSize()
|
||||
{
|
||||
long sizeInBytes = 0;
|
||||
long EmbeddingCacheUtilization = 0;
|
||||
foreach (var entry in queryCache)
|
||||
{
|
||||
sizeInBytes += sizeof(int); // string length prefix
|
||||
sizeInBytes += entry.Key.Length * sizeof(char); // string characters
|
||||
sizeInBytes += entry.Value.EstimateSize();
|
||||
EmbeddingCacheUtilization += sizeof(int); // string length prefix
|
||||
EmbeddingCacheUtilization += entry.Key.Length * sizeof(char); // string characters
|
||||
EmbeddingCacheUtilization += entry.Value.EstimateSize();
|
||||
}
|
||||
return sizeInBytes;
|
||||
return EmbeddingCacheUtilization;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,43 @@
|
||||
<span>@T["Total query cache utilization"]</span>
|
||||
<strong id="totalQuerycacheUtilization"></strong>
|
||||
</div>
|
||||
|
||||
<!-- Query cache -->
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<span>@T["Query cache entry count"]</span>
|
||||
<strong id="querycacheCount"></strong>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<span>
|
||||
@T["Query cache capacity (loaded)"]
|
||||
<i class="bi bi-info-circle-fill text-info"
|
||||
data-bs-toggle="tooltip"
|
||||
title="@T["queryCacheEntryCountLoadedInfo"]"></i>
|
||||
</span>
|
||||
<strong id="querycacheLoadedMaxElementCount"></strong>
|
||||
</div>
|
||||
|
||||
<div class="progress mt-3" style="height: 8px;">
|
||||
<div id="querycacheLoadedMaxElementCountProgressBar" class="progress-bar"
|
||||
style="width: 0.00%"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<span>
|
||||
@T["Query cache capacity (all)"]
|
||||
<i class="bi bi-info-circle-fill text-info"
|
||||
data-bs-toggle="tooltip"
|
||||
title="@T["queryCacheEntryCountAllInfo"]"></i>
|
||||
</span>
|
||||
<strong id="querycacheMaxElementCount"></strong>
|
||||
</div>
|
||||
|
||||
<div class="progress mt-3" style="height: 8px;">
|
||||
<div id="querycacheMaxElementCountProgressBar" class="progress-bar"
|
||||
style="width: 0.00%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -135,6 +172,17 @@
|
||||
let embeddingcacheEmbeddingCount = document.getElementById("embeddingcacheEmbeddingCount");
|
||||
showThrobber(embeddingcacheEmbeddingCount);
|
||||
let embeddingcacheElementCountProgressBar = document.getElementById("embeddingcacheElementCountProgressBar");
|
||||
|
||||
let querycacheCount = document.getElementById("querycacheCount");
|
||||
showThrobber(querycacheCount);
|
||||
let querycacheMaxElementCount = document.getElementById("querycacheMaxElementCount");
|
||||
showThrobber(querycacheMaxElementCount);
|
||||
let querycacheMaxElementCountProgressBar = document.getElementById("querycacheMaxElementCountProgressBar");
|
||||
let querycacheLoadedMaxElementCount = document.getElementById("querycacheLoadedMaxElementCount");
|
||||
showThrobber(querycacheLoadedMaxElementCount);
|
||||
let querycacheLoadedElementCountProgressBar = document.getElementById("querycacheLoadedElementCountProgressBar");
|
||||
|
||||
|
||||
let healthchecksServer = document.getElementById("healthchecksServer");
|
||||
let healthchecksAiProvider = document.getElementById("healthchecksAiProvider");
|
||||
|
||||
@@ -145,23 +193,34 @@
|
||||
searchdomainCount.textContent = searchdomains.length;
|
||||
});
|
||||
getServerStats().then(result => {
|
||||
let utilization = result.SizeInBytes;
|
||||
let maxElementCount = result.MaxElementCount;
|
||||
let elementCount = result.ElementCount;
|
||||
let utilization = result.EmbeddingCacheUtilization;
|
||||
let embeddingCacheMaxElementCount = result.EmbeddingCacheMaxElementCount;
|
||||
let embeddingCacheElementCount = result.ElementCount;
|
||||
let embeddingCount = result.EmbeddingsCount;
|
||||
let entityCount = result.EntityCount;
|
||||
let queryCacheUtilization = result.QueryCacheUtilization;
|
||||
let queryCacheElementCount = result.QueryCacheElementCount;
|
||||
let queryCacheMaxElementCountAll = result.QueryCacheMaxElementCountAll;
|
||||
let queryCacheMaxElementCountLoadedSearchdomainsOnly = result.QueryCacheMaxElementCountLoadedSearchdomainsOnly;
|
||||
hideThrobber(embeddingcacheSize);
|
||||
embeddingcacheSize.textContent = NumberOfBytesAsHumanReadable(utilization);
|
||||
hideThrobber(embeddingcacheElementCount);
|
||||
embeddingcacheElementCount.textContent = `${elementCount.toLocaleString()} / ${maxElementCount.toLocaleString()}`;
|
||||
embeddingcacheElementCount.textContent = `${embeddingCacheElementCount.toLocaleString()} / ${embeddingCacheMaxElementCount.toLocaleString()}`;
|
||||
hideThrobber(embeddingcacheEmbeddingCount);
|
||||
embeddingcacheEmbeddingCount.textContent = embeddingCount;
|
||||
embeddingcacheElementCountProgressBar.style.width = `${elementCount / maxElementCount * 100}%`;
|
||||
embeddingcacheElementCountProgressBar.style.width = `${embeddingCacheElementCount / embeddingCacheMaxElementCount * 100}%`;
|
||||
hideThrobber(searchdomainEntityCount);
|
||||
searchdomainEntityCount.textContent = entityCount;
|
||||
hideThrobber(totalQuerycacheUtilization);
|
||||
totalQuerycacheUtilization.textContent = NumberOfBytesAsHumanReadable(queryCacheUtilization);
|
||||
hideThrobber(querycacheMaxElementCount);
|
||||
querycacheCount.textContent = queryCacheElementCount;
|
||||
hideThrobber(querycacheCount);
|
||||
querycacheMaxElementCount.textContent = queryCacheMaxElementCountAll.toLocaleString();
|
||||
querycacheMaxElementCountProgressBar.style.width = `${queryCacheElementCount / queryCacheMaxElementCountAll * 100}%`;
|
||||
hideThrobber(querycacheLoadedMaxElementCount);
|
||||
querycacheLoadedMaxElementCount.textContent = queryCacheMaxElementCountLoadedSearchdomainsOnly.toLocaleString();
|
||||
querycacheLoadedMaxElementCountProgressBar.style.width = `${queryCacheElementCount / queryCacheMaxElementCountLoadedSearchdomainsOnly * 100}%`;
|
||||
});
|
||||
getHealthCheckStatusAndApply(healthchecksServer, "/healthz/Database");
|
||||
getHealthCheckStatusAndApply(healthchecksAiProvider, "/healthz/AIProvider");
|
||||
|
||||
Reference in New Issue
Block a user