懒得勤快 3 lat temu
rodzic
commit
a4ea2d1409

+ 153 - 150
src/Masuit.MyBlogs.Core/Common/PerfCounter.cs

@@ -5,202 +5,205 @@ using Masuit.Tools;
 using Masuit.Tools.DateTimeExt;
 using Masuit.Tools.Hardware;
 using Masuit.Tools.Systems;
+using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection.Extensions;
 
-namespace Masuit.MyBlogs.Core.Common
+namespace Masuit.MyBlogs.Core.Common;
+
+public interface IPerfCounter
 {
-    public interface IPerfCounter
-    {
-        public static ConcurrentLimitedQueue<PerformanceCounter> List { get; } = new(50000);
+    public static ConcurrentLimitedQueue<PerformanceCounter> List { get; } = new(50000);
 
-        public static readonly DateTime StartTime = DateTime.Now;
+    public static readonly DateTime StartTime = DateTime.Now;
 
-        public static void Init()
+    public static void Init()
+    {
+        Task.Run(() =>
         {
-            Task.Run(() =>
+            int errorCount = 0;
+            while (true)
             {
-                int errorCount = 0;
-                while (true)
+                try
                 {
-                    try
-                    {
-                        List.Enqueue(GetCurrentPerformanceCounter());
-                    }
-                    catch (Exception e)
+                    List.Enqueue(GetCurrentPerformanceCounter());
+                }
+                catch (Exception e)
+                {
+                    if (errorCount > 20)
                     {
-                        if (errorCount > 20)
-                        {
-                            break;
-                        }
-                        Console.ForegroundColor = ConsoleColor.Red;
-                        Console.WriteLine(e.Message);
-                        Console.ForegroundColor = ConsoleColor.White;
-                        errorCount++;
+                        break;
                     }
-                    Thread.Sleep(5000);
+                    Console.ForegroundColor = ConsoleColor.Red;
+                    Console.WriteLine(e.Message);
+                    Console.ForegroundColor = ConsoleColor.White;
+                    errorCount++;
                 }
-            });
-        }
+                Thread.Sleep(5000);
+            }
+        });
+    }
 
-        public static PerformanceCounter GetCurrentPerformanceCounter()
+    public static PerformanceCounter GetCurrentPerformanceCounter()
+    {
+        var time = DateTime.Now.GetTotalMilliseconds();
+        var load = SystemInfo.CpuLoad;
+        var mem = (1 - SystemInfo.MemoryAvailable.ConvertTo<float>() / SystemInfo.PhysicalMemory.ConvertTo<float>()) * 100;
+
+        var read = SystemInfo.GetDiskData(DiskData.Read) / 1024f;
+        var write = SystemInfo.GetDiskData(DiskData.Write) / 1024;
+
+        var up = SystemInfo.GetNetData(NetData.Received) / 1024;
+        var down = SystemInfo.GetNetData(NetData.Sent) / 1024;
+        return new PerformanceCounter()
         {
-            var time = DateTime.Now.GetTotalMilliseconds();
-            var load = SystemInfo.CpuLoad;
-            var mem = (1 - SystemInfo.MemoryAvailable.ConvertTo<float>() / SystemInfo.PhysicalMemory.ConvertTo<float>()) * 100;
+            Time = time,
+            CpuLoad = load,
+            MemoryUsage = mem,
+            DiskRead = read,
+            DiskWrite = write,
+            Download = down,
+            Upload = up
+        };
+    }
 
-            var read = SystemInfo.GetDiskData(DiskData.Read) / 1024f;
-            var write = SystemInfo.GetDiskData(DiskData.Write) / 1024;
+    IQueryable<PerformanceCounter> CreateDataSource();
 
-            var up = SystemInfo.GetNetData(NetData.Received) / 1024;
-            var down = SystemInfo.GetNetData(NetData.Sent) / 1024;
-            return new PerformanceCounter()
-            {
-                Time = time,
-                CpuLoad = load,
-                MemoryUsage = mem,
-                DiskRead = read,
-                DiskWrite = write,
-                Download = down,
-                Upload = up
-            };
-        }
+    void Process();
+}
 
-        IQueryable<PerformanceCounter> CreateDataSource();
+public class DefaultPerfCounter : IPerfCounter
+{
+    static DefaultPerfCounter()
+    {
+    }
 
-        void Process();
+    public IQueryable<PerformanceCounter> CreateDataSource()
+    {
+        return IPerfCounter.List.AsQueryable();
     }
 
-    public class DefaultPerfCounter : IPerfCounter
+    public void Process()
     {
-        static DefaultPerfCounter()
-        {
-        }
+    }
+}
 
-        public IQueryable<PerformanceCounter> CreateDataSource()
-        {
-            return IPerfCounter.List.AsQueryable();
-        }
+public class PerfCounterInDatabase : IPerfCounter
+{
+    public static ConcurrentLimitedQueue<PerformanceCounter> List { get; } = new(50000);
 
-        public void Process()
-        {
-        }
-    }
+    private readonly LoggerDbContext _dbContext;
 
-    public class PerfCounterInDatabase : IPerfCounter
+    public PerfCounterInDatabase(LoggerDbContext dbContext)
     {
-        public static ConcurrentLimitedQueue<PerformanceCounter> List { get; } = new(50000);
+        _dbContext = dbContext;
+    }
 
-        private readonly LoggerDbContext _dbContext;
+    public IQueryable<PerformanceCounter> CreateDataSource()
+    {
+        return _dbContext.Set<PerformanceCounter>();
+    }
 
-        public PerfCounterInDatabase(LoggerDbContext dbContext)
+    public void Process()
+    {
+        if (Debugger.IsAttached)
         {
-            _dbContext = dbContext;
+            return;
         }
 
-        public IQueryable<PerformanceCounter> CreateDataSource()
+        while (IPerfCounter.List.TryDequeue(out var result))
         {
-            return _dbContext.Set<PerformanceCounter>();
+            _dbContext.Add(result);
         }
 
-        public void Process()
+        if (_dbContext.SaveChanges() > 0)
         {
-            if (Debugger.IsAttached)
-            {
-                return;
-            }
-
-            while (IPerfCounter.List.TryDequeue(out var result))
-            {
-                _dbContext.Add(result);
-            }
-
-            _dbContext.SaveChanges();
             var start = DateTime.Now.AddMonths(-6).GetTotalMilliseconds();
-            _dbContext.Set<PerformanceCounter>().Where(e => e.Time < start).DeleteFromQuery();
+            var tableName = _dbContext.Model.FindEntityType(typeof(PerformanceCounter)).GetTableName();
+            _dbContext.Database.ExecuteSqlRaw($"DELETE FROM \"{tableName}\" WHERE \"{nameof(PerformanceCounter.Time)}\" <{start}");
         }
     }
+}
 
-    public class PerfCounterBackService : BackgroundService
-    {
-        private readonly IPerfCounter _manager;
+public class PerfCounterBackService : ScheduledService
+{
+    private readonly IServiceScopeFactory _serviceScopeFactory;
 
-        public PerfCounterBackService(IPerfCounter manager)
-        {
-            _manager = manager;
-        }
+    public PerfCounterBackService(IServiceScopeFactory serviceScopeFactory) : base(TimeSpan.FromSeconds(5))
+    {
+        _serviceScopeFactory = serviceScopeFactory;
+    }
 
-        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
-        {
-            while (true)
-            {
-                _manager.Process();
-                await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
-            }
-        }
+    protected override Task ExecuteAsync()
+    {
+        using var scope = _serviceScopeFactory.CreateAsyncScope();
+        var counter = scope.ServiceProvider.GetRequiredService<IPerfCounter>();
+        counter.Process();
+        return Task.CompletedTask;
     }
+}
 
-    public static class PerfCounterServiceExtension
+public static class PerfCounterServiceExtension
+{
+    public static IServiceCollection AddPerfCounterManager(this IServiceCollection services, IConfiguration configuration)
     {
-        public static IServiceCollection AddPerfCounterManager(this IServiceCollection services, IConfiguration configuration)
+        IPerfCounter.Init();
+        switch (configuration["PerfCounterStorage"])
         {
-            IPerfCounter.Init();
-            switch (configuration["PerfCounterStorage"])
-            {
-                case "database":
-                    services.AddScoped<IPerfCounter, PerfCounterInDatabase>();
-                    services.TryAddScoped<PerfCounterInDatabase>();
-                    break;
-
-                default:
-                    services.AddSingleton<IPerfCounter, DefaultPerfCounter>();
-                    break;
-            }
-
-            services.AddHostedService<PerfCounterBackService>();
-            return services;
+            case "database":
+                services.AddScoped<IPerfCounter, PerfCounterInDatabase>();
+                services.TryAddScoped<PerfCounterInDatabase>();
+                break;
+
+            default:
+                services.AddSingleton<IPerfCounter, DefaultPerfCounter>();
+                break;
         }
+
+        services.Configure<HostOptions>(options => options.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore);
+        services.AddHostedService<PerfCounterBackService>();
+        return services;
     }
+}
 
+/// <summary>
+/// 性能计数器
+/// </summary>
+[Table(nameof(PerformanceCounter))]
+public class PerformanceCounter
+{
     /// <summary>
-    /// 性能计数器
+    /// 当前时间戳
     /// </summary>
-    [Table(nameof(PerformanceCounter))]
-    public class PerformanceCounter
-    {
-        /// <summary>
-        /// 当前时间戳
-        /// </summary>
-        [HypertableColumn]
-        public long Time { get; set; }
-
-        /// <summary>
-        /// CPU当前负载
-        /// </summary>
-        public float CpuLoad { get; set; }
-
-        /// <summary>
-        /// 内存使用率
-        /// </summary>
-        public float MemoryUsage { get; set; }
-
-        /// <summary>
-        /// 磁盘读
-        /// </summary>
-        public float DiskRead { get; set; }
-
-        /// <summary>
-        /// 磁盘写
-        /// </summary>
-        public float DiskWrite { get; set; }
-
-        /// <summary>
-        /// 网络上行
-        /// </summary>
-        public float Upload { get; set; }
-
-        /// <summary>
-        /// 网络下行
-        /// </summary>
-        public float Download { get; set; }
-    }
+    [HypertableColumn]
+    public long Time { get; set; }
+
+    /// <summary>
+    /// CPU当前负载
+    /// </summary>
+    public float CpuLoad { get; set; }
+
+    /// <summary>
+    /// 内存使用率
+    /// </summary>
+    public float MemoryUsage { get; set; }
+
+    /// <summary>
+    /// 磁盘读
+    /// </summary>
+    public float DiskRead { get; set; }
+
+    /// <summary>
+    /// 磁盘写
+    /// </summary>
+    public float DiskWrite { get; set; }
+
+    /// <summary>
+    /// 网络上行
+    /// </summary>
+    public float Upload { get; set; }
+
+    /// <summary>
+    /// 网络下行
+    /// </summary>
+    public float Download { get; set; }
 }

+ 46 - 0
src/Masuit.MyBlogs.Core/Common/ScheduledService.cs

@@ -0,0 +1,46 @@
+using Masuit.Tools.Logging;
+
+namespace Masuit.MyBlogs.Core.Common;
+
+public abstract class ScheduledService : IHostedService, IDisposable
+{
+    private readonly Timer _timer;
+    private readonly TimeSpan _period;
+
+    protected ScheduledService(TimeSpan period)
+    {
+        _period = period;
+        _timer = new Timer(Execute, null, Timeout.Infinite, 0);
+    }
+
+    public void Execute(object state = null)
+    {
+        try
+        {
+            ExecuteAsync().Wait();
+        }
+        catch (Exception ex)
+        {
+            LogManager.Error(ex);
+        }
+    }
+
+    protected abstract Task ExecuteAsync();
+
+    public virtual void Dispose()
+    {
+        _timer?.Dispose();
+    }
+
+    public Task StartAsync(CancellationToken cancellationToken)
+    {
+        _timer.Change(TimeSpan.FromSeconds(Random.Shared.Next(10)), _period);
+        return Task.CompletedTask;
+    }
+
+    public Task StopAsync(CancellationToken cancellationToken)
+    {
+        _timer?.Change(Timeout.Infinite, 0);
+        return Task.CompletedTask;
+    }
+}

+ 17 - 18
src/Masuit.MyBlogs.Core/Extensions/Firewall/IRequestLogger.cs

@@ -1,14 +1,10 @@
 using System.Collections.Concurrent;
 using System.Diagnostics;
-using Hangfire;
 using Masuit.MyBlogs.Core.Common;
-using Masuit.MyBlogs.Core.Extensions.Hangfire;
 using Masuit.MyBlogs.Core.Infrastructure;
 using Masuit.MyBlogs.Core.Models.Entity;
-using Masuit.Tools.Systems;
-using MaxMind.Db;
+using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection.Extensions;
-using Microsoft.Graph.CallRecords;
 
 namespace Masuit.MyBlogs.Core.Extensions.Firewall;
 
@@ -88,28 +84,31 @@ public class RequestDatabaseLogger : IRequestLogger
             result.Network = network;
             _dataContext.Add(result);
         }
-        _dataContext.SaveChanges();
-        var start = DateTime.Now.AddMonths(-6);
-        _dataContext.Set<RequestLogDetail>().Where(e => e.Time < start).DeleteFromQuery();
+
+        if (_dataContext.SaveChanges() > 0)
+        {
+            var start = DateTime.Now.AddMonths(-6);
+            var tableName = _dataContext.Model.FindEntityType(typeof(RequestLogDetail)).GetTableName();
+            _dataContext.Database.ExecuteSqlRaw($"DELETE FROM \"{tableName}\" WHERE \"{nameof(RequestLogDetail.Time)}\" <'{start:yyyy-MM-dd HH:mm:ss}'");
+        }
     }
 }
 
-public class RequestLoggerBackService : BackgroundService
+public class RequestLoggerBackService : ScheduledService
 {
-    private readonly IRequestLogger _logger;
+    private readonly IServiceScopeFactory _scopeFactory;
 
-    public RequestLoggerBackService(IRequestLogger logger)
+    public RequestLoggerBackService(IServiceScopeFactory scopeFactory) : base(TimeSpan.FromMinutes(5))
     {
-        _logger = logger;
+        _scopeFactory = scopeFactory;
     }
 
-    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+    protected override Task ExecuteAsync()
     {
-        while (true)
-        {
-            _logger.Process();
-            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
-        }
+        using var scope = _scopeFactory.CreateAsyncScope();
+        var logger = scope.ServiceProvider.GetRequiredService<IRequestLogger>();
+        logger.Process();
+        return Task.CompletedTask;
     }
 }
 

+ 9 - 0
src/Masuit.MyBlogs.Core/Infrastructure/LoggerDbContext.cs

@@ -21,6 +21,15 @@ public class LoggerDbContext : DbContext
     {
         modelBuilder.Entity<RequestLogDetail>().HasKey(e => new { e.Id, e.Time });
         modelBuilder.Entity<PerformanceCounter>().HasKey(e => e.Time);
+
+        if (Database.IsNpgsql() || Database.IsSqlite())
+        {
+            modelBuilder.HasDbFunction(typeof(Guid).GetMethod(nameof(Guid.NewGuid))).HasName("random");
+        }
+        else
+        {
+            modelBuilder.HasDbFunction(typeof(Guid).GetMethod(nameof(Guid.NewGuid))).HasName("RAND");
+        }
     }
 }
 

+ 9 - 7
src/Masuit.MyBlogs.Core/Views/Dashboard/Counter.razor

@@ -5,7 +5,9 @@
 @using Masuit.Tools
 @using System.IO
 @using Collections.Pooled
+@using Masuit.MyBlogs.Core.Infrastructure
 @using Masuit.Tools.Logging
+@using Microsoft.EntityFrameworkCore
 @using PerformanceCounter = Masuit.MyBlogs.Core.Common.PerformanceCounter
 @inject IPerfCounter PerfCounter;
 @inject IJSRuntime JS;
@@ -161,7 +163,7 @@
 
     public Dictionary<string, dynamic> GetCounterPercent()
     {
-        var counters = PerfCounter.CreateDataSource();
+        var counters = PerfCounter.CreateDataSource().OrderBy(c => Guid.NewGuid()).Take(5000).ToList();
         var count = counters.Count();
         return new()
         {
@@ -173,7 +175,7 @@
                 p99 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 100).MinOrDefault(c => c.CpuLoad).ToString("N2"),
                 p999 = counters.OrderByDescending(c => c.CpuLoad).Take(count / 1000).MinOrDefault(c => c.CpuLoad).ToString("N2"),
                 average = counters.Average(c => c.CpuLoad).ToString("N2"),
-                stdev = counters.StandardDeviation(c => c.CpuLoad).ToString("N2"),
+                stdev = counters.Select(c => c.CpuLoad).StandardDeviation().ToString("N2"),
             },
             ["内存使用率(%)"] = new
             {
@@ -183,7 +185,7 @@
                 p99 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 100).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
                 p999 = counters.OrderByDescending(c => c.MemoryUsage).Take(count / 1000).MinOrDefault(c => c.MemoryUsage).ToString("N2"),
                 average = counters.Average(c => c.MemoryUsage).ToString("N2"),
-                stdev = counters.StandardDeviation(c => c.MemoryUsage).ToString("N2"),
+                stdev = counters.Select(c => c.MemoryUsage).StandardDeviation().ToString("N2"),
             },
             ["磁盘读(KBps)"] = new
             {
@@ -193,7 +195,7 @@
                 p99 = counters.OrderByDescending(c => c.DiskRead).Take(count / 100).MinOrDefault(c => c.DiskRead).ToString("N2"),
                 p999 = counters.OrderByDescending(c => c.DiskRead).Take(count / 1000).MinOrDefault(c => c.DiskRead).ToString("N2"),
                 average = counters.Average(c => c.DiskRead).ToString("N2"),
-                stdev = counters.StandardDeviation(c => c.DiskRead).ToString("N2"),
+                stdev = counters.Select(c => c.DiskRead).StandardDeviation().ToString("N2"),
             },
             ["磁盘写(KBps)"] = new
             {
@@ -203,7 +205,7 @@
                 p99 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 100).MinOrDefault(c => c.DiskWrite).ToString("N2"),
                 p999 = counters.OrderByDescending(c => c.DiskWrite).Take(count / 1000).MinOrDefault(c => c.DiskWrite).ToString("N2"),
                 average = counters.Average(c => c.DiskWrite).ToString("N2"),
-                stdev = counters.StandardDeviation(c => c.DiskWrite).ToString("N2")
+                stdev = counters.Select(c => c.DiskWrite).StandardDeviation().ToString("N2")
             },
             ["网络下载(KBps)"] = new
             {
@@ -213,7 +215,7 @@
                 p99 = counters.OrderByDescending(c => c.Download).Take(count / 100).MinOrDefault(c => c.Download).ToString("N2"),
                 p999 = counters.OrderByDescending(c => c.Download).Take(count / 1000).MinOrDefault(c => c.Download).ToString("N2"),
                 average = counters.Average(c => c.Download).ToString("N2"),
-                stdev = counters.StandardDeviation(c => c.Download).ToString("N2")
+                stdev = counters.Select(c => c.Download).StandardDeviation().ToString("N2")
             },
             ["网络上行(KBps)"] = new
             {
@@ -223,7 +225,7 @@
                 p99 = counters.OrderByDescending(c => c.Upload).Take(count / 100).MinOrDefault(c => c.Upload).ToString("N2"),
                 p999 = counters.OrderByDescending(c => c.Upload).Take(count / 1000).MinOrDefault(c => c.Upload).ToString("N2"),
                 average = counters.Average(c => c.Upload).ToString("N2"),
-                stdev = counters.StandardDeviation(c => c.Upload).ToString("N2")
+                stdev = counters.Select(c => c.Upload).StandardDeviation().ToString("N2")
             }
         };
     }