Inizio pagina stats licenze

This commit is contained in:
Samuele Locatelli
2025-01-13 09:53:25 +01:00
parent 2b6c330ba6
commit 9f8d01ff02
22 changed files with 396 additions and 17 deletions
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class Utils
{
/// <summary>
/// Effettua arrotondamento di un timespan ad un dato step di minuti
///
/// vedere qui: https://stackoverflow.com/questions/1393696/rounding-datetime-objects
/// </summary>
/// <param name="TSpanOrig">DataOra originale</param>
/// <param name="roundMin">Minuti di arrotondamento richeisti</param>
/// <param name="isFloor">Arrotondamento x difetto (floor = true) o eccesso (false)</param>
/// <returns></returns>
public static TimeSpan TSpanRounded(TimeSpan TSpanOrig, int roundMin, bool isFloor)
{
long ticks = 0;
roundMin = roundMin <= 0 ? 1 : roundMin;
TimeOnly step = new TimeOnly(0, roundMin);
if (isFloor)
{
ticks = TSpanOrig.Ticks / step.Ticks;
}
else
{
ticks = (TSpanOrig.Ticks + step.Ticks - 1) / step.Ticks;
}
TimeSpan answ = new TimeSpan(ticks * step.Ticks);
return answ;
}
/// <summary>
/// Effettua arrotondamento di un timespan ad un dato step di minuti
///
/// vedere qui: https://stackoverflow.com/questions/1393696/rounding-datetime-objects
/// </summary>
/// <param name="DateOrig">DataOra originale</param>
/// <param name="roundMin">Minuti di arrotondamento richeisti</param>
/// <returns></returns>
public static TimeSpan TSpanRounded(TimeSpan TSpanOrig, int roundMin)
{
long ticks = 0;
roundMin = roundMin <= 0 ? 1 : roundMin;
TimeOnly step = new TimeOnly(0, roundMin);
ticks = (TSpanOrig.Ticks + step.Ticks / 2) / step.Ticks;
TimeSpan answ = new TimeSpan(ticks * step.Ticks);
return answ;
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>License Manager</i>
<h4>Versione: 2.1.2501.1112</h4>
<h4>Versione: 2.1.2501.1309</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
2.1.2501.1112
2.1.2501.1309
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>2.1.2501.1112</version>
<version>2.1.2501.1309</version>
<url>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/LiMan.UI.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+76
View File
@@ -1468,6 +1468,82 @@ namespace LiMan.DB.Controllers
return fatto;
}
/// <summary>
/// Calcola statistiche install per il periodo indicato
/// </summary>
/// <param name="dtStart"></param>
/// <param name="dtEnd"></param>
/// <returns></returns>
public InstallStatusDTO InstallStatusGetInfo(DateTime dtStart, DateTime dtEnd)
{
InstallStatusDTO answ = new InstallStatusDTO();
using (LMDbContext localDbCtx = new LMDbContext(_configuration))
{
// conteggio preliminare licenze impiegate
var countSubLic = localDbCtx
.DbSetSubLicenze
.GroupBy(x => x.IdxLic)
.Select(g => new
{
IdxLic = g.Key,
NumLic = g.Count()
});
// raccolgo in primis info riguardo updater...
answ.UpdaterList = localDbCtx
.DbSetLicenze
.Where(x => x.CodApp == "UpdateManager")
.Select(x => new ApplicativoDTO()
{
IdxLic = x.IdxLic,
Chiave = x.Chiave,
CodApp = x.CodApp,
CodInst = x.CodInst,
Descrizione = x.Descrizione,
Tipo = x.Tipo,
Scadenza = x.Scadenza,
NumLicenze = x.NumLicenze,
NumLicenzeAttive = countSubLic.Where(s => s.IdxLic == x.IdxLic).Select(c => c.NumLic).FirstOrDefault(),
DataEnigma = x.DataEnigma,
Enigma = x.Enigma,
Payload = x.Payload
})
.ToList();
// recupero info x calcolare num chiamate nel periodo indicato...
var rawCallList = localDbCtx
.DbSetLogCall
.Where(x => x.DataRif >= dtStart && x.DataRif < dtEnd && x.TargetUrl.Contains("api/release"))
.ToList();
// eseguo conteggio x applicazione...
var countAppCall = rawCallList
.GroupBy(x => x.CodApp)
.OrderByDescending(x => x.Count())
.ToDictionary(g => g.Key, g => g.Count());
answ.ReqCountApp = countAppCall;
// ora conteggio per ORA chiamata...
var countHour = rawCallList
.GroupBy(x => x.DataRif.Date.AddHours(x.DataRif.Hour))
.ToDictionary(g => g.Key, g => g.Count());
answ.ReqCountHour = countHour;
// ora conteggio per GIORNO chiamata...
var countDay = rawCallList
.GroupBy(x => x.DataRif.Date)
.ToDictionary(g => g.Key, g => g.Count());
answ.ReqCountDay= countDay;
// ora passo a valorizzare i numeri relativi ad app e versioni...
}
return answ;
}
/// <summary>
/// Effettua refresh del payload della licenza dato info + enigma generato dal client
/// </summary>
+52 -1
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
@@ -16,11 +17,61 @@ namespace LiMan.DB.DTO
public class AppRelStatusDTO
{
/// <summary>
/// CodApp Richiesta
/// </summary>
public string CodApp { get; set; } = "";
/// <summary>
/// Licenza Updater
/// </summary>
public int IdxLic { get; set; } = 0;
/// <summary>
/// Codice cliente
/// </summary>
public string Cliente { get; set; } = "";
/// <summary>
/// Istanza Updater (PC)
/// </summary>
public int IdxSubLic { get; set; } = 0;
/// <summary>
/// PC/Installazione specifica
/// </summary>
public string PcInst { get; set; } = "";
/// <summary>
/// Conteggio del numero totale degli impieghi attivi (es conteggio IOB)
/// </summary>
public int NumLicenzeAttive { get; set; } = 1;
public int NumImp { get; set; } = 1;
/// <summary>
/// Versione Installata
/// </summary>
public string VersNumInstall { get; set; } = "0.0.0.0";
/// <summary>
/// Versione Release corrente
/// </summary>
public string VersNumCurrent { get; set; } = "0.0.0.0";
/// <summary>
/// Status aggiornamento:
/// 4 = corrente, 4 blocchi uguali (0.0.0.0)
/// 3 = 3 uguali, cambia 4 blocco (0.0.0.x)
/// 2 = 2 uguali, cambia 3 blocco (0.0.x.x)
/// 1 = 1 uguali, cambia 2 blocco (0.x.x.x)
/// 0 = 0 uguali, cambia 1 blocco (x.x.x.x)
/// </summary>
public int UpToDateStatus { get;set; } = 0;
/// <summary>
/// Data Ora ultimo controllo
/// </summary>
public DateTime DtCheck { get; set; } = DateTime.Now;
}
}
+15 -1
View File
@@ -22,6 +22,11 @@ namespace LiMan.DB.DTO
/// </summary>
public List<ApplicativoDTO> UpdaterList { get; set; } = new List<ApplicativoDTO>();
/// <summary>
/// Elenco chiamate con conteggio x CodApp
/// </summary>
public Dictionary<string, int> ReqCountApp { get; set; } = new Dictionary<string, int>();
/// <summary>
/// Lista delle ultime richieste registrate (TargetUrl like '%release%') come conteggio orario (tipicamente 15 gg)
/// </summary>
@@ -37,6 +42,15 @@ namespace LiMan.DB.DTO
/// </summary>
public List<AppRelStatusDTO> InstallRelList { get; set; } = new List<AppRelStatusDTO>();
[NotMapped]
public int TotalUpdaterAct
{
get
{
return UpdaterList.Sum(x => x.NumLicenzeAttive);
}
}
/// <summary>
/// Conteggio totale di tutte le applicazioni gestite, come somma CONTEGGIO degli applicativi diversi gestiti (per cliente)
/// </summary>
@@ -57,7 +71,7 @@ namespace LiMan.DB.DTO
{
get
{
return UpdaterList.Sum(x => x.NumLicenzeAttive) + InstallRelList.Sum(x => x.NumLicenzeAttive);
return UpdaterList.Sum(x => x.NumLicenzeAttive) + InstallRelList.Sum(x => x.NumImp);
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>License Manager</i>
<h4>Versione: 2.1.2501.1111</h4>
<h4>Versione: 2.1.2501.1309</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
2.1.2501.1111
2.1.2501.1309
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>2.1.2501.1111</version>
<version>2.1.2501.1309</version>
<url>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/LiMan.Transfer.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+11 -5
View File
@@ -103,14 +103,14 @@ else if (SelRecord != null)
</div>
</div>
<div class="modal-footer">
@if(SelIdxLic>0)
@if (SelIdxLic > 0)
{
<button class="btn btn-success btn-lg w-100" @onclick="() => AddActivations()" title="Aggiunta attivazioni a licenza selezionata"><i class="fa-solid fa-circle-plus"></i> 10 Attivazioni Licenza</button>
<button class="btn btn-success btn-lg w-100" @onclick="() => AddActivations()" title="Aggiunta attivazioni a licenza selezionata"><i class="fa-solid fa-circle-plus"></i> 10 Attivazioni Licenza</button>
}
else
{
else
{
<button class="btn btn-secondary btn-lg w-100" disabled><i class="fa-solid fa-circle-plus"></i> 10 Attivazioni Licenza</button>
}
}
</div>
</div>
</div>
@@ -230,6 +230,12 @@ else
}
</ul>
</div>
<div class="card-footer">
<div class="d-flex justify-content-between small">
<div class="px-1">UpdateManager</div>
<div class="px-1 fw-bold">@(DescrLic(item.IdxLic))</div>
</div>
</div>
</div>
</div>
}
+20
View File
@@ -152,6 +152,7 @@ namespace LiMan.UI.Components
protected override async Task OnParametersSetAsync()
{
await ReloadLicData();
await ReloadData();
}
@@ -286,6 +287,25 @@ namespace LiMan.UI.Components
ListInstall = await LMDService.InstallazioniNextGetAll();
}
/// <summary>
/// Recupera info licenza dato Idx x indicare licenza di assegnazione dell'enroll
/// </summary>
/// <param name="idxLic"></param>
/// <returns></returns>
protected string DescrLic(int idxLic)
{
string answ = "NA";
if (idxLic > 0 && ListLicenze != null && ListLicenze.Count > 0)
{
var sRec = ListLicenze.FirstOrDefault(x => x.IdxLic == idxLic);
if (sRec != null)
{
answ = $"{sRec.CodInst}";
}
}
return answ;
}
#endregion Private Methods
}
}
@@ -0,0 +1,54 @@
<div class="card shadow">
<div class="card-header">
<h4>Statistiche Update & Versioni</h4>
</div>
<div class="card-body">
@if (isLoading)
{
<LoadingData></LoadingData>
}
else
{
<div class="row">
<div class="col-2">
<div class="list-group">
<li class="list-group-item active">
<b>Updater</b> info
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div>
Licenze
</div>
<span class="badge text-bg-primary rounded-pill">@InfoStats.UpdaterList.Count</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div>
Istanze
</div>
<span class="badge text-bg-primary rounded-pill">@InfoStats.TotalUpdaterAct</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div>
Call / Hour
</div>
<span class="badge text-bg-primary rounded-pill">???</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div>
Call / Day
</div>
<span class="badge text-bg-primary rounded-pill">???</span>
</li>
</div>
</div>
<div class="col-2">
</div>
</div>
}
</div>
<div class="card-footer text-end small">
last updated: @InfoStats.LastUpdated
</div>
</div>
@@ -0,0 +1,35 @@
using LiMan.DB.DTO;
using LiMan.UI.Data;
using Microsoft.AspNetCore.Components;
using System;
using System.Threading.Tasks;
namespace LiMan.UI.Components
{
public partial class InstallInfoStats
{
protected override async Task OnInitializedAsync()
{
await ReloadData();
}
[Inject]
protected LiManDataService LMDService { get; set; } = null!;
private DateTime DtInizio { get; set; } = DateTime.Today.AddMonths(-1);
private DateTime DtFine { get; set; } = DateTime.Today.AddHours(DateTime.Now.Hour);
private async Task ReloadData()
{
isLoading = true;
InfoStats = await LMDService.InstallStatusGetInfo(DtInizio, DtFine);
isLoading = false;
}
private bool isLoading { get; set; } = false;
private InstallStatusDTO InfoStats { get; set; } = new InstallStatusDTO();
}
}
+49
View File
@@ -885,6 +885,55 @@ namespace LiMan.UI.Data
}
#endif
/// <summary>
/// Recupera info statistiche installazione dato periodo riferimento, da cache o da db
/// </summary>
/// <param name="dtStart"></param>
/// <param name="dtEnd"></param>
public async Task<InstallStatusDTO> InstallStatusGetInfo(DateTime dtStart, DateTime dtEnd)
{
string source = "DB";
InstallStatusDTO dbResult = new InstallStatusDTO();
try
{
string currKey = $"{Const.rKeyConfig}:InstVerSta:{dtStart:yyyyMMdd-HHmmss}:{dtEnd:yyyyMMdd-HHmmss}";
Stopwatch sw = new Stopwatch();
sw.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<InstallStatusDTO>(rawData);
if (tempResult == null)
{
dbResult = new InstallStatusDTO();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbControllerNext.InstallStatusGetInfo(dtStart, dtEnd);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new InstallStatusDTO();
}
sw.Stop();
TimeSpan ts = sw.Elapsed;
Log.Debug($"InstallStatusGetInfo | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during InstallStatusGetInfo:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary>
/// invalida tutta la cache in caso di update
/// </summary>
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Version>2.1.2501.1112</Version>
<Version>2.1.2501.1309</Version>
<RootNamespace>LiMan.UI</RootNamespace>
<AssemblyName>LiMan.UI</AssemblyName>
</PropertyGroup>
+7
View File
@@ -0,0 +1,7 @@
@page "/InstallVersStats"
@attribute [Authorize]
<div class="px-0">
<InstallInfoStats></InstallInfoStats>
</div>
+7
View File
@@ -0,0 +1,7 @@
namespace LiMan.UI.Pages
{
public partial class InstallVersStats
{
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>License Manager</i>
<h4>Versione: 2.1.2501.1112</h4>
<h4>Versione: 2.1.2501.1309</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
2.1.2501.1112
2.1.2501.1309
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>2.1.2501.1112</version>
<version>2.1.2501.1309</version>
<url>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/LiMan.UI.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/LiMan/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+5
View File
@@ -24,6 +24,11 @@
<NavMenuItem IconClass="fa-solid fa-square-binary" Text="Enroll Request" />
</NavLink>
</li>
<li class="nav-item px-2">
<NavLink class="nav-link" href="InstallVersStats">
<NavMenuItem IconClass="fa-solid fa-chart-pie" Text="Install Ver Stats" />
</NavLink>
</li>
<li class="nav-item px-2">
<NavLink class="nav-link" href="Applicazioni">
<NavMenuItem IconClass="fa-regular fa-rectangle-list" Text="App & Releases" />