-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from CriggerMarg/feature/web-socket
implement web socket data refresh
- Loading branch information
Showing
32 changed files
with
808 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
| ||
using Microsoft.Extensions.Configuration; | ||
|
||
namespace Tasklist.Background.Extensions | ||
{ | ||
public static class ConfigurationExtensions | ||
{ | ||
public static int ReadIntConfigValue(this IConfiguration configuration, string key, int defaultValue) | ||
{ | ||
var value = configuration[key]; | ||
if (value == null) | ||
{ | ||
return defaultValue; | ||
} | ||
int number; | ||
if(int.TryParse(value, out number)) | ||
{ | ||
return number; | ||
} | ||
return defaultValue; | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,15 @@ | ||
using System.Collections.Generic; | ||
using System.Net.WebSockets; | ||
using System.Threading.Tasks; | ||
|
||
namespace Tasklist.Background | ||
{ | ||
public interface IProcessRepository | ||
{ | ||
IReadOnlyCollection<ProcessInformation> ProcessInformation { get; set; } | ||
IReadOnlyCollection<ProcessInformation> ProcessInformation { get; } | ||
Task SetProcessInfo(IReadOnlyCollection<ProcessInformation> info); | ||
bool IsCpuHigh { get; set; } | ||
bool IsMemoryLow { get; set; } | ||
void AddSocket(WebSocket socket, TaskCompletionSource<object> tcs); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System; | ||
|
||
namespace Tasklist.Background | ||
{ | ||
public struct SysInfo : IEquatable<SysInfo> | ||
{ | ||
public bool HighCpu { get; set; } | ||
public bool LowMemory { get; set; } | ||
|
||
public bool Equals(SysInfo other) | ||
{ | ||
return HighCpu == other.HighCpu && LowMemory == other.LowMemory; | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
return obj is SysInfo other && Equals(other); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return HashCode.Combine(HighCpu, LowMemory); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
|
||
using Tasklist.Background.Extensions; | ||
|
||
namespace Tasklist.Background | ||
{ | ||
public class SysInfoHostedService : BackgroundService | ||
{ | ||
private readonly ILogger<SysInfoHostedService> _logger; | ||
private readonly IProcessRepository _processRepository; | ||
private readonly int _refreshRateInMs; | ||
private readonly int _cpuHighValue; | ||
private readonly int _memoryLowValue; | ||
public SysInfoHostedService(ILogger<SysInfoHostedService> logger, IProcessRepository processRepository, IConfiguration configuration) | ||
{ | ||
_logger = logger; | ||
_processRepository = processRepository; | ||
_refreshRateInMs = configuration.ReadIntConfigValue("TasklistRefreshRateMS", 50); | ||
_cpuHighValue = configuration.ReadIntConfigValue("cpuHighValue", 90); | ||
_memoryLowValue = configuration.ReadIntConfigValue("memoryLowValue", 1024); | ||
} | ||
|
||
public override async Task StopAsync(CancellationToken stoppingToken) | ||
{ | ||
_logger.LogInformation($"{GetType().Name} is stopping."); | ||
|
||
await base.StopAsync(stoppingToken); | ||
} | ||
|
||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | ||
{ | ||
await BackgroundProcessing(stoppingToken); | ||
} | ||
|
||
private async Task BackgroundProcessing(CancellationToken stoppingToken) | ||
{ | ||
while (!stoppingToken.IsCancellationRequested) | ||
{ | ||
try | ||
{ | ||
var info = ReadSysInfo(); | ||
_processRepository.IsMemoryLow = info.LowMemory; | ||
_processRepository.IsCpuHigh = info.HighCpu; | ||
|
||
await Task.Delay(TimeSpan.FromMilliseconds(_refreshRateInMs), stoppingToken); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_logger.LogError(ex, $"Error occurred executing {GetType().Name}"); | ||
} | ||
} | ||
} | ||
|
||
private SysInfo ReadSysInfo() | ||
{ | ||
var query = "(Get-Counter -Counter '\\Memory\\Available MBytes','\\Processor(_Total)\\% Processor Time').CounterSamples.CookedValue"; | ||
// powershell may not work on machine where it would be ran. So consider yo use WMI too | ||
var stringData = string.Empty; | ||
var errorData = string.Empty; | ||
using (var process = new Process()) | ||
{ | ||
process.StartInfo.FileName = "powershell.exe"; | ||
process.StartInfo.Arguments = $"-NoProfile -ExecutionPolicy unrestricted \"{query }\""; | ||
process.StartInfo.CreateNoWindow = true; | ||
process.StartInfo.UseShellExecute = false; | ||
process.StartInfo.RedirectStandardOutput = true; | ||
process.StartInfo.RedirectStandardError = true; | ||
|
||
process.OutputDataReceived += (sender, data) => | ||
{ | ||
if (!string.IsNullOrEmpty(data.Data)) | ||
{ | ||
stringData += data.Data + Environment.NewLine; | ||
} | ||
}; | ||
process.ErrorDataReceived += (sender, data) => errorData += data.Data; | ||
process.Start(); | ||
process.BeginOutputReadLine(); | ||
process.BeginErrorReadLine(); | ||
process.WaitForExit(1000 * 10); | ||
} | ||
if (!string.IsNullOrEmpty(errorData)) | ||
{ | ||
_logger.LogError(errorData); | ||
} | ||
try | ||
{ | ||
if (!string.IsNullOrEmpty(stringData)) | ||
{ | ||
var data = stringData.Split(Environment.NewLine); | ||
float memory; | ||
float.TryParse(data[0], out memory); | ||
|
||
float cpu; | ||
float.TryParse(data[1], out cpu); | ||
|
||
return new SysInfo | ||
{ | ||
HighCpu = cpu > _cpuHighValue, | ||
LowMemory = memory < _memoryLowValue | ||
}; | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "oops"); | ||
} | ||
|
||
return new SysInfo(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.4" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
using System.Reflection; | ||
|
||
namespace Tasklist.Middleware.Websocket | ||
{ | ||
public static class WebSocketExtensions | ||
{ | ||
public static IServiceCollection AddWebSocketManager(this IServiceCollection services) | ||
{ | ||
services.AddTransient<WebSocketConnectionManager>(); | ||
|
||
foreach (var type in Assembly.GetEntryAssembly().ExportedTypes) | ||
{ | ||
if (type.GetTypeInfo().BaseType == typeof(WebSocketHandler)) | ||
{ | ||
services.AddSingleton(type); | ||
} | ||
} | ||
|
||
return services; | ||
} | ||
|
||
public static IApplicationBuilder MapWebSocket(this IApplicationBuilder app, | ||
PathString path, | ||
WebSocketHandler handler) | ||
{ | ||
return app.Map(path, (_app) => _app.UseMiddleware<WebSocketMiddleware>(handler)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Idea taken from https://radu-matei.com/blog/aspnet-core-websockets-middleware/ |
Oops, something went wrong.