Inizio pagina stats licenze
This commit is contained in:
@@ -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,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 @@
|
||||
2.1.2501.1112
|
||||
2.1.2501.1309
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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 @@
|
||||
2.1.2501.1111
|
||||
2.1.2501.1309
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@page "/InstallVersStats"
|
||||
@attribute [Authorize]
|
||||
|
||||
|
||||
<div class="px-0">
|
||||
<InstallInfoStats></InstallInfoStats>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace LiMan.UI.Pages
|
||||
{
|
||||
public partial class InstallVersStats
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 @@
|
||||
2.1.2501.1112
|
||||
2.1.2501.1309
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user