Merge pull request #158 from Moonlight-Panel/ImproveStatistics

Added better statistics calculation and active user messurement
This commit is contained in:
Marcel Baumgartner 2023-06-11 17:57:01 +02:00 committed by GitHub
commit 0a1b93b8fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 1193 additions and 9 deletions

View file

@ -43,6 +43,7 @@ public class User
// Date stuff
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
public DateTime LastVisitedAt { get; set; } = DateTime.UtcNow;
// Subscriptions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Moonlight.App.Database.Migrations
{
/// <inheritdoc />
public partial class AddLastVisitedTimestamp : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "LastVisitedAt",
table: "Users",
type: "datetime(6)",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LastVisitedAt",
table: "Users");
}
}
}

View file

@ -762,6 +762,9 @@ namespace Moonlight.App.Database.Migrations
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("LastVisitedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("longtext");

View file

@ -0,0 +1,39 @@
using Moonlight.App.Database.Entities;
namespace Moonlight.App.Helpers;
public static class AvgHelper
{
public static StatisticsData[] Calculate(StatisticsData[] data, int splitSize = 40)
{
if (data.Length <= splitSize)
return data;
var result = new List<StatisticsData>();
var i = data.Length / (float)splitSize;
var pc = (int)Math.Round(i);
foreach (var part in data.Chunk(pc))
{
double d = 0;
var res = new StatisticsData();
foreach (var entry in part)
{
d += entry.Value;
}
res.Chart = part.First().Chart;
res.Date = part.First().Date;
if (d == 0)
res.Value = 0;
res.Value = d / part.Length;
result.Add(res);
}
return result.ToArray();
}
}

View file

@ -9,6 +9,7 @@ namespace Moonlight.App.Services.Sessions;
public class SessionService
{
private readonly SessionRepository SessionRepository;
private Repository<User> UserRepository;
private readonly IdentityService IdentityService;
private readonly NavigationManager NavigationManager;
private readonly AlertService AlertService;
@ -21,13 +22,15 @@ public class SessionService
IdentityService identityService,
NavigationManager navigationManager,
AlertService alertService,
DateTimeService dateTimeService)
DateTimeService dateTimeService,
Repository<User> userRepository)
{
SessionRepository = sessionRepository;
IdentityService = identityService;
NavigationManager = navigationManager;
AlertService = alertService;
DateTimeService = dateTimeService;
UserRepository = userRepository;
}
public async Task Register()
@ -46,6 +49,12 @@ public class SessionService
};
SessionRepository.Add(OwnSession);
if (user != null) // Track last session init of user as last visited timestamp
{
user.LastVisitedAt = DateTimeService.GetCurrent();
UserRepository.Update(user);
}
}
public void Refresh()

View file

@ -7,20 +7,33 @@ namespace Moonlight.App.Services.Statistics;
public class StatisticsViewService
{
private readonly StatisticsRepository StatisticsRepository;
private readonly Repository<User> UserRepository;
private readonly DateTimeService DateTimeService;
public StatisticsViewService(StatisticsRepository statisticsRepository, DateTimeService dateTimeService)
public StatisticsViewService(StatisticsRepository statisticsRepository, DateTimeService dateTimeService, Repository<User> userRepository)
{
StatisticsRepository = statisticsRepository;
DateTimeService = dateTimeService;
UserRepository = userRepository;
}
public StatisticsData[] GetData(string chart, StatisticsTimeSpan timeSpan)
{
var startDate = DateTimeService.GetCurrent() - TimeSpan.FromHours((int)timeSpan);
var objs = StatisticsRepository.Get().Where(x => x.Date > startDate && x.Chart == chart);
var objs = StatisticsRepository
.Get()
.Where(x => x.Date > startDate && x.Chart == chart);
return objs.ToArray();
}
public int GetActiveUsers(StatisticsTimeSpan timeSpan)
{
var startDate = DateTimeService.GetCurrent() - TimeSpan.FromHours((int)timeSpan);
return UserRepository
.Get()
.Count(x => x.LastVisitedAt > startDate);
}
}

View file

@ -66,6 +66,20 @@
}
</div>
}
<div class="row">
<div class="col-sm-6">
<div class="card mt-4">
<div class="card-header">
<div class="card-title">
<TL>Active users</TL>
</div>
</div>
<div class="card-body">
<span class="fs-2">@(ActiveUsers)</span>
</div>
</div>
</div>
</div>
</LazyLoader>
</OnlyAdmin>
@ -73,7 +87,9 @@
{
private StatisticsTimeSpan StatisticsTimeSpan = StatisticsTimeSpan.Day;
private LazyLoader Loader;
private Dictionary<string, StatisticsData[]> Charts = new();
private int ActiveUsers = 0;
private int TimeSpanBind
{
@ -91,34 +107,48 @@
Charts.Add(
SmartTranslateService.Translate("Servers"),
StatisticsViewService.GetData("serversCount", StatisticsTimeSpan)
AvgHelper.Calculate(
StatisticsViewService.GetData("serversCount", StatisticsTimeSpan)
)
);
Charts.Add(
SmartTranslateService.Translate("Users"),
StatisticsViewService.GetData("usersCount", StatisticsTimeSpan)
AvgHelper.Calculate(
StatisticsViewService.GetData("usersCount", StatisticsTimeSpan)
)
);
Charts.Add(
SmartTranslateService.Translate("Domains"),
StatisticsViewService.GetData("domainsCount", StatisticsTimeSpan)
AvgHelper.Calculate(
StatisticsViewService.GetData("domainsCount", StatisticsTimeSpan)
)
);
Charts.Add(
SmartTranslateService.Translate("Databases"),
StatisticsViewService.GetData("databasesCount", StatisticsTimeSpan)
AvgHelper.Calculate(
StatisticsViewService.GetData("databasesCount", StatisticsTimeSpan)
)
);
Charts.Add(
SmartTranslateService.Translate("Webspaces"),
StatisticsViewService.GetData("webspacesCount", StatisticsTimeSpan)
AvgHelper.Calculate(
StatisticsViewService.GetData("webspacesCount", StatisticsTimeSpan)
)
);
Charts.Add(
SmartTranslateService.Translate("Sessions"),
StatisticsViewService.GetData("sessionsCount", StatisticsTimeSpan)
AvgHelper.Calculate(
StatisticsViewService.GetData("sessionsCount", StatisticsTimeSpan)
)
);
ActiveUsers = StatisticsViewService.GetActiveUsers(StatisticsTimeSpan);
return Task.CompletedTask;
}