@page "/admin/db-stats"
@page "/admin/db-stats/{DatabaseStr}"
@page "/admin/db-stats/{DatabaseStr}/{DatabaseInstanceStr}"
@using ChartJs.Blazor
@using ChartJs.Blazor.BarChart
@using ChartJs.Blazor.BarChart.Axes
@using ChartJs.Blazor.Common.Axes
@using ChartJs.Blazor.Common.Enums
@using Rms.Risk.Mango.Pivot.Core.MongoDb
@using Rms.Risk.Mango.Services.Models
@attribute [Authorize]
@inject NavigationManager NavigationManager
@inject IUserSession UserSession
@inject IJSRuntime JsRuntime
@*
* dbMango
*
* Copyright 2025 Deutsche Bank AG
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*@
Storage size
@if (Error != null)
{
}
@code {
[CascadingParameter] public IModalService Modal { get; set; } = null!;
[Parameter] public string? DatabaseStr { get; set; }
[Parameter] public string? DatabaseInstanceStr { get; set; }
private string Database
{
get => UserSession.Database;
set
{
if (UserSession.Database == value)
return;
UserSession.Database = value;
SyncUrl();
}
}
private string DatabaseInstance
{
get => UserSession.DatabaseInstance;
set
{
if (UserSession.DatabaseInstance == value)
return;
UserSession.DatabaseInstance = value;
SyncUrl();
}
}
private Exception? Error { get; set; }
private DatabaseStatsModel Result { get; set; } = new();
private string ChartClass => Result.Raw.Count == 0 || Error != null
? "d-none"
: ""
;
private static readonly string[] _colors = [
"rgba(255, 99, 132, 0.6)",
"rgba(255, 159, 64, 0.6)",
"rgba(255, 205, 86, 0.6)",
"rgba(75, 192, 192, 0.6)",
"rgba(54, 162, 235, 0.6)",
// "rgba(153, 102, 255, 0.4)",
// "rgba(201, 203, 207, 0.4)"
];
private string _unit = "B";
private double _divider = 1.0;
private readonly BarConfig _chartConfig = new()
{
Data =
{
Datasets =
{
new BarDataset
{
Label = "Index used",
BackgroundColor = _colors[2],
BorderColor = _colors[2]
},
new BarDataset
{
Label = "Index free",
BackgroundColor = _colors[3],
BorderColor = _colors[3]
},
new BarDataset
{
Label = "Storage used",
BackgroundColor = _colors[0],
BorderColor = _colors[0]
},
new BarDataset
{
Label = "Storage free",
BackgroundColor = _colors[1],
BorderColor = _colors[1]
},
// new BarDataset
// {
// Label = "Other free",
// BackgroundColor = _colors[4],
// BorderColor = _colors[4]
// }
}
},
Options = new()
{
MaintainAspectRatio = true,
Responsive = true,
Legend = new()
{
Display = true,
Position = Position.Bottom
},
Scales = new()
{
YAxes = new List
{
new BarLinearCartesianAxis
{
Stacked = true,
// OffsetGridLines = false,
// Offset = true,
// Display = AxisDisplay.False
}
},
XAxes = new List
{
new BarCategoryAxis
{
Stacked = true,
// OffsetGridLines = false,
// Offset = false,
// Display = AxisDisplay.False,
// BarThickness = 45
}
}
}
}
};
protected override void OnAfterRender(bool firstRender)
{
if (!firstRender)
return;
if (string.IsNullOrWhiteSpace(DatabaseStr))
DatabaseStr = Database;
else
Database = DatabaseStr;
if (string.IsNullOrWhiteSpace(DatabaseInstanceStr))
DatabaseInstanceStr = DatabaseInstance;
else
DatabaseInstance = DatabaseInstanceStr;
SyncUrl();
StateHasChanged();
Task.Run(Run);
}
private async Task Run()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
try
{
await InvokeAsync(StateHasChanged);
var res = await UserSession.MongoDbAdmin.DbStats(cts.Token);
await Display(res);
}
catch (Exception e)
{
await Display(e);
}
finally
{
await InvokeAsync(StateHasChanged);
}
}
private void UpdateChart(
DatabaseStatsModel data
)
{
_chartConfig.Data.XLabels.Clear();
foreach (var key in data.Raw.Keys)
{
var parts = key.Split('/');
_chartConfig.Data.XLabels.Add(parts[0]); // replica set name
}
var dataMax = data.Raw.Values.Max(x => x.StorageSize+x.IndexSize);
// Decide unit
if (dataMax > 1024 * 1024 * 1024) // > 1 GB
{
_unit = "GB";
_divider = 1024 * 1024 * 1024;
}
else
{
_unit = "MB";
_divider = 1024 * 1024;
}
var indexUsed = (BarDataset)_chartConfig.Data.Datasets[0];
var indexFree = (BarDataset)_chartConfig.Data.Datasets[1];
var storageUsed = (BarDataset)_chartConfig.Data.Datasets[2];
var storageFree = (BarDataset)_chartConfig.Data.Datasets[3];
// var otherFree = (BarDataset)_chartConfig.Data.Datasets[4];
storageUsed.Clear();
storageFree.Clear();
indexUsed .Clear();
indexFree .Clear();
// otherFree .Clear();
storageUsed.AddRange(data.Raw.Values.Select(x => (x.StorageSize - x.FreeStorageSize) / _divider));
storageFree.AddRange(data.Raw.Values.Select(x => x.FreeStorageSize / _divider));
indexUsed .AddRange(data.Raw.Values.Select(x => (x.IndexSize - x.IndexFreeStorageSize) / _divider));
indexFree .AddRange(data.Raw.Values.Select(x => x.IndexFreeStorageSize / _divider));
// otherFree.AddRange(data.Raw.Values.Select(x => (x.FsUsedSize - x.StorageSize - x.IndexSize) / _divider));
_chartConfig.Data.Datasets.Add(storageUsed);
_chartConfig.Data.Datasets.Add(storageFree);
_chartConfig.Data.Datasets.Add(indexUsed );
_chartConfig.Data.Datasets.Add(indexFree );
// _chartConfig.Data.Datasets.Add(otherFree );
_chartConfig.Options.Scales.YAxes.Clear();
_chartConfig.Options.Scales.YAxes.Add(new BarLinearCartesianAxis
{
Stacked = true,
ScaleLabel = new ()
{
Display = true,
LabelString = $"Size {_unit}"
},
Ticks = new ()
{
Min = 0.0,
Max = dataMax / _divider,
}
});
}
private Task Display(DatabaseStatsModel model)
{
Error = null;
Result = model;
UpdateChart(model);
return InvokeAsync(StateHasChanged);
}
private Task Display(Exception e)
{
Error = e;
Result.Raw.Clear();
return InvokeAsync(StateHasChanged);
}
private void SyncUrl()
{
var url = NavigationManager.BaseUri + $"admin/db-stats/{Database}";
if (!string.IsNullOrWhiteSpace(DatabaseInstance))
url += $"/{DatabaseInstance}";
JsRuntime.InvokeAsync("DashboardUtils.ChangeUrl", url);
}
}