mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-15 13:13:48 +00:00
Shorten large numbers and remove redundant database details
This commit is contained in:
5 files changed
+45
-66
No files matched your search
@@ -26,7 +26,6 @@ public sealed class NoIndexStoreClient(string name, string? unavailableReason, D
|
|||||||
// user sees, so this is the one place where those details matter most.
|
// user sees, so this is the one place where those details matter most.
|
||||||
//
|
//
|
||||||
yield return (TB("Native library"), OrUnknown(SqliteRuntimeInfo.GetNativeLibraryName()));
|
yield return (TB("Native library"), OrUnknown(SqliteRuntimeInfo.GetNativeLibraryName()));
|
||||||
yield return (TB("Native library path"), OrUnknown(SqliteRuntimeInfo.GetNativeLibraryPath()));
|
|
||||||
yield return (TB("Process architecture"), OrUnknown(SqliteRuntimeInfo.GetProcessArchitecture()));
|
yield return (TB("Process architecture"), OrUnknown(SqliteRuntimeInfo.GetProcessArchitecture()));
|
||||||
|
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
|
|||||||
+4
-16
@@ -71,9 +71,7 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
var snapshot = await this.ReadDisplaySnapshotAsync();
|
var snapshot = await this.ReadDisplaySnapshotAsync();
|
||||||
|
|
||||||
yield return (TB("Reported version"), version);
|
yield return (TB("Reported version"), version);
|
||||||
yield return (TB("Library source ID"), OrUnknown(snapshot.LibrarySourceId));
|
|
||||||
yield return (TB("Native library"), OrUnknown(SqliteRuntimeInfo.GetNativeLibraryName()));
|
yield return (TB("Native library"), OrUnknown(SqliteRuntimeInfo.GetNativeLibraryName()));
|
||||||
yield return (TB("Native library path"), OrNotDetermined(SqliteRuntimeInfo.GetNativeLibraryPath()));
|
|
||||||
yield return (TB("Wrapper version"), OrUnknown(SqliteRuntimeInfo.GetWrapperVersion()));
|
yield return (TB("Wrapper version"), OrUnknown(SqliteRuntimeInfo.GetWrapperVersion()));
|
||||||
yield return (TB("Process architecture"), OrUnknown(SqliteRuntimeInfo.GetProcessArchitecture()));
|
yield return (TB("Process architecture"), OrUnknown(SqliteRuntimeInfo.GetProcessArchitecture()));
|
||||||
|
|
||||||
@@ -83,14 +81,12 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
yield return (TB("System architecture"), systemArchitecture);
|
yield return (TB("System architecture"), systemArchitecture);
|
||||||
|
|
||||||
yield return (TB("Full-text search (FTS5)"), OrUnknown(snapshot.FullTextSearch));
|
yield return (TB("Full-text search (FTS5)"), OrUnknown(snapshot.FullTextSearch));
|
||||||
yield return (TB("Database path"), this.databasePath);
|
|
||||||
yield return (TB("Journal mode"), OrUnknown(snapshot.JournalMode));
|
yield return (TB("Journal mode"), OrUnknown(snapshot.JournalMode));
|
||||||
yield return (TB("Schema version"), OrUnknown(snapshot.SchemaVersion));
|
yield return (TB("Schema version"), OrUnknown(snapshot.SchemaVersion));
|
||||||
yield return (TB("Database tables"), OrUnknown(snapshot.TableCount));
|
yield return (TB("Database tables"), OrUnknown(snapshot.TableCount));
|
||||||
yield return (TB("Storage size"), this.GetStorageSize());
|
yield return (TB("Storage size"), this.GetStorageSize());
|
||||||
yield return (TB("Indexed data sources"), OrUnknown(snapshot.DataSourceCount));
|
yield return (TB("Indexed data sources"), OrUnknown(snapshot.DataSourceCount));
|
||||||
yield return (TB("Indexed files"), OrUnknown(snapshot.FileCount));
|
yield return (TB("Indexed files"), OrUnknown(snapshot.FileCount));
|
||||||
yield return (TB("Search chunks"), OrUnknown(snapshot.ChunkCount));
|
|
||||||
yield return (TB("Permanently skipped files"), OrUnknown(snapshot.FailureCount));
|
yield return (TB("Permanently skipped files"), OrUnknown(snapshot.FailureCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,8 +402,6 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
private sealed record DisplaySnapshot
|
private sealed record DisplaySnapshot
|
||||||
{
|
{
|
||||||
public string LibrarySourceId { get; init; } = string.Empty;
|
|
||||||
|
|
||||||
public string FullTextSearch { get; init; } = string.Empty;
|
public string FullTextSearch { get; init; } = string.Empty;
|
||||||
|
|
||||||
public string JournalMode { get; init; } = string.Empty;
|
public string JournalMode { get; init; } = string.Empty;
|
||||||
@@ -420,15 +414,11 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
|
|
||||||
public string FileCount { get; init; } = string.Empty;
|
public string FileCount { get; init; } = string.Empty;
|
||||||
|
|
||||||
public string ChunkCount { get; init; } = string.Empty;
|
|
||||||
|
|
||||||
public string FailureCount { get; init; } = string.Empty;
|
public string FailureCount { get; init; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string OrUnknown(string value) => string.IsNullOrWhiteSpace(value) ? TB("unknown") : value;
|
private static string OrUnknown(string value) => string.IsNullOrWhiteSpace(value) ? TB("unknown") : value;
|
||||||
|
|
||||||
private static string OrNotDetermined(string value) => string.IsNullOrWhiteSpace(value) ? TB("not determined") : value;
|
|
||||||
|
|
||||||
private async Task<DisplaySnapshot> ReadDisplaySnapshotAsync()
|
private async Task<DisplaySnapshot> ReadDisplaySnapshotAsync()
|
||||||
{
|
{
|
||||||
var token = CancellationToken.None;
|
var token = CancellationToken.None;
|
||||||
@@ -437,14 +427,12 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
await using var context = this.CreateContext();
|
await using var context = this.CreateContext();
|
||||||
return new DisplaySnapshot
|
return new DisplaySnapshot
|
||||||
{
|
{
|
||||||
LibrarySourceId = await QueryScalarTextAsync(context, "SELECT sqlite_source_id()", token),
|
|
||||||
FullTextSearch = await GetFullTextSearchStateAsync(context, token),
|
FullTextSearch = await GetFullTextSearchStateAsync(context, token),
|
||||||
JournalMode = (await QueryScalarTextAsync(context, "PRAGMA journal_mode;", token)).ToUpperInvariant(),
|
JournalMode = (await QueryScalarTextAsync(context, "PRAGMA journal_mode;", token)).ToUpperInvariant(),
|
||||||
SchemaVersion = await GetSchemaVersionAsync(context, token),
|
SchemaVersion = await GetSchemaVersionAsync(context, token),
|
||||||
TableCount = await GetTableCountAsync(context, token),
|
TableCount = await GetTableCountAsync(context, token),
|
||||||
DataSourceCount = await FormatCountAsync(context.DataSources, token),
|
DataSourceCount = await FormatCountAsync(context.DataSources, token),
|
||||||
FileCount = await FormatCountAsync(context.EmbeddedFiles, token),
|
FileCount = await FormatCountAsync(context.EmbeddedFiles, token),
|
||||||
ChunkCount = (await this.GetTotalChunkCountAsync(token))?.ToString("N0", I18N.I.Culture) ?? string.Empty,
|
|
||||||
FailureCount = await FormatCountAsync(context.PermanentIndexingFailures, token),
|
FailureCount = await FormatCountAsync(context.PermanentIndexingFailures, token),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -503,7 +491,7 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
// is the point: a missing shadow table is a finding, not noise.
|
// is the point: a missing shadow table is a finding, not noise.
|
||||||
//
|
//
|
||||||
var tables = await QueryScalarTextAsync(context, "SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'", token);
|
var tables = await QueryScalarTextAsync(context, "SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'", token);
|
||||||
return int.TryParse(tables, NumberStyles.Integer, CultureInfo.InvariantCulture, out var tableCount) ? tableCount.ToString("N0", I18N.I.Culture) : string.Empty;
|
return int.TryParse(tables, NumberStyles.Integer, CultureInfo.InvariantCulture, out var tableCount) ? tableCount.CompactCount() : string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<string> GetSchemaVersionAsync(IndexStoreDbContext context, CancellationToken token)
|
private static async Task<string> GetSchemaVersionAsync(IndexStoreDbContext context, CancellationToken token)
|
||||||
@@ -521,8 +509,8 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
|
|
||||||
var pendingMigrations = (await context.Database.GetPendingMigrationsAsync(token)).ToList();
|
var pendingMigrations = (await context.Database.GetPendingMigrationsAsync(token)).ToList();
|
||||||
return pendingMigrations.Count == 0
|
return pendingMigrations.Count == 0
|
||||||
? string.Format(I18N.I.Culture, TB("{0} ({1} applied)"), appliedMigrations[^1], appliedMigrations.Count)
|
? string.Format(I18N.I.Culture, TB("{0} ({1} applied)"), appliedMigrations[^1], appliedMigrations.Count.CompactCount())
|
||||||
: string.Format(I18N.I.Culture, TB("{0} ({1} applied, {2} pending)"), appliedMigrations[^1], appliedMigrations.Count, pendingMigrations.Count);
|
: string.Format(I18N.I.Culture, TB("{0} ({1} applied, {2} pending)"), appliedMigrations[^1], appliedMigrations.Count.CompactCount(), pendingMigrations.Count.CompactCount());
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -534,7 +522,7 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (await query.CountAsync(token)).ToString("N0", I18N.I.Culture);
|
return (await query.CountAsync(token)).CompactCount();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,42 +33,6 @@ internal static class SqliteRuntimeInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Where the native library sits on disk.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This probes the file system instead of enumerating the loaded modules: Process.Modules throws
|
|
||||||
/// on macOS, and NativeLibrary hands out no path at all. For our single-file builds, the base
|
|
||||||
/// directory is where the runtime extracts the native assets to, so that is the first candidate.
|
|
||||||
/// </remarks>
|
|
||||||
public static string GetNativeLibraryPath()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var libraryName = GetNativeLibraryName();
|
|
||||||
if (string.IsNullOrWhiteSpace(libraryName))
|
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
var fileName = GetNativeFileName(libraryName);
|
|
||||||
var baseDirectory = AppContext.BaseDirectory;
|
|
||||||
string[] candidates =
|
|
||||||
[
|
|
||||||
Path.Combine(baseDirectory, fileName),
|
|
||||||
Path.Combine(baseDirectory, "runtimes", RuntimeInformation.RuntimeIdentifier, "native", fileName),
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach (var candidate in candidates)
|
|
||||||
if (File.Exists(candidate))
|
|
||||||
return candidate;
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The version of the managed SQLitePCLRaw wrapper, which is a different thing than the SQLite version.
|
/// The version of the managed SQLitePCLRaw wrapper, which is a different thing than the SQLite version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -121,15 +85,4 @@ internal static class SqliteRuntimeInfo
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetNativeFileName(string libraryName)
|
|
||||||
{
|
|
||||||
if (OperatingSystem.IsWindows())
|
|
||||||
return $"{libraryName}.dll";
|
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
|
||||||
return $"lib{libraryName}.dylib";
|
|
||||||
|
|
||||||
return $"lib{libraryName}.so";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -91,8 +91,8 @@ public sealed class QdrantEdgeClientImplementation(
|
|||||||
|
|
||||||
yield return (TB("Reported version"), displayVersion);
|
yield return (TB("Reported version"), displayVersion);
|
||||||
yield return (TB("Storage size"), $"{this.GetStorageSize()}");
|
yield return (TB("Storage size"), $"{this.GetStorageSize()}");
|
||||||
yield return (TB("Number of vector stores"), displayStoresCount.ToString("N0", I18N.I.Culture));
|
yield return (TB("Number of vector stores"), displayStoresCount.CompactCount());
|
||||||
yield return (TB("Stored vectors"), storedVectors?.ToString("N0", I18N.I.Culture) ?? TB("unknown"));
|
yield return (TB("Stored vectors"), storedVectors?.CompactCount() ?? TB("unknown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,7 +1,46 @@
|
|||||||
|
using AIStudio.Tools.PluginSystem;
|
||||||
|
|
||||||
namespace AIStudio.Tools;
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
public static class LongExtensions
|
public static class LongExtensions
|
||||||
{
|
{
|
||||||
|
private static readonly string[] COUNT_SUFFIXES = ["k", "M", "B", "T"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a count so that large numbers stay readable: 1456 becomes 1.46k, 4512900 becomes 4.51M.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Counts scale in thousands, not in steps of 1024 — that is what FileSize is for, and storage
|
||||||
|
/// sizes keep using it. Numbers below 1000 stay exact, because shortening them would hide the
|
||||||
|
/// difference between 4 and 999. The decimal separator follows the culture of the active language
|
||||||
|
/// plugin rather than the one of the thread, which never moves along with the app's language.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="count">The number to format.</param>
|
||||||
|
/// <returns>The formatted number.</returns>
|
||||||
|
public static string CompactCount(this long count)
|
||||||
|
{
|
||||||
|
var culture = I18N.I.Culture;
|
||||||
|
if (count is > -1_000 and < 1_000)
|
||||||
|
return count.ToString("N0", culture);
|
||||||
|
|
||||||
|
var order = -1;
|
||||||
|
double value = count;
|
||||||
|
while (Math.Abs(value) >= 1_000 && order < COUNT_SUFFIXES.Length - 1)
|
||||||
|
{
|
||||||
|
order++;
|
||||||
|
value /= 1_000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{value.ToString("0.##", culture)}{COUNT_SUFFIXES[order]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats a count so that large numbers stay readable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">The number to format.</param>
|
||||||
|
/// <returns>The formatted number.</returns>
|
||||||
|
public static string CompactCount(this int count) => ((long)count).CompactCount();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Formats the file size in a human-readable format.
|
/// Formats the file size in a human-readable format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in new issue
Block a user