diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-08-16 17:05:56 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-08-16 17:05:56 +0300 |
| commit | e47e602cd61bcca8eb7fbef40dc4aa8798510ccc (patch) | |
| tree | aed51794566ba837dcfcfb673e5d67b4ab716884 /Software/Visual_Studio/Tango.Insights | |
| parent | f809df07060dc3a27167f68027eb03bdbc89221a (diff) | |
| download | Tango-e47e602cd61bcca8eb7fbef40dc4aa8798510ccc.tar.gz Tango-e47e602cd61bcca8eb7fbef40dc4aa8798510ccc.zip | |
Working on insights...
Diffstat (limited to 'Software/Visual_Studio/Tango.Insights')
6 files changed, 438 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsFrame.cs b/Software/Visual_Studio/Tango.Insights/InsightsFrame.cs new file mode 100644 index 000000000..4ea2a1c13 --- /dev/null +++ b/Software/Visual_Studio/Tango.Insights/InsightsFrame.cs @@ -0,0 +1,64 @@ +using LiteDB; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.PMR.Diagnostics; +using Tango.PMR.Insights; +using Tango.Transport.Compression; + +namespace Tango.Insights +{ + public class InsightsFrame + { + [BsonId(true)] + public int Id { get; set; } + public DateTime Time { get; set; } + public bool IsEmpty { get; set; } + public byte[] MonitorsData { get; set; } + + public static InsightsFrame CreateEmpty(DateTime timeUtc) + { + InsightsFrame frame = new InsightsFrame(); + frame.Time = timeUtc; + frame.IsEmpty = true; + frame.MonitorsData = null; + return frame; + } + + public static InsightsFrame FromDiagnosticsMonitors(DiagnosticsMonitors diagnosticsMonitors, DateTime timeUtc) + { + InsightsMonitors insightsMonitors = InsightsHelper.MapMonitors(diagnosticsMonitors); + return FromInsightsMonitors(insightsMonitors, timeUtc); + } + + public static InsightsFrame FromInsightsMonitors(InsightsMonitors insightsMonitors, DateTime timeUtc) + { + InsightsFrame frame = new InsightsFrame(); + frame.Time = timeUtc; + + byte[] data = insightsMonitors.ToBytes(); + byte[] compressedData = SevenZipHelper.Compress(data); + + frame.MonitorsData = compressedData; + + return frame; + } + + public InsightsMonitors ToInsightsMonitors() + { + if (IsEmpty) + { + return InsightsHelper.CreateEmptyGap(); + } + else + { + var uncompressed = SevenZipHelper.Decompress(MonitorsData); + var insightsMonitors = InsightsMonitors.Parser.ParseFrom(uncompressed); + return insightsMonitors; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.Insights/InsightsHelper.cs b/Software/Visual_Studio/Tango.Insights/InsightsHelper.cs new file mode 100644 index 000000000..202e2574d --- /dev/null +++ b/Software/Visual_Studio/Tango.Insights/InsightsHelper.cs @@ -0,0 +1,85 @@ +using Google.Protobuf.Collections; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Tango.PMR.Diagnostics; +using Tango.PMR.Insights; + +namespace Tango.Insights +{ + public static class InsightsHelper + { + private static List<PropertyInfo> _diagnosticsProperties; + private static List<PropertyInfo> _insightsProperties; + + static InsightsHelper() + { + _diagnosticsProperties = new List<PropertyInfo>(); + _insightsProperties = new List<PropertyInfo>(); + + foreach (var prop in typeof(DiagnosticsMonitors).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + _diagnosticsProperties.Add(prop); + } + + foreach (var prop in typeof(InsightsMonitors).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + { + _insightsProperties.Add(prop); + } + } + + public static InsightsMonitors MapMonitors(DiagnosticsMonitors diagnosticsMonitors) + { + InsightsMonitors insightsMonitors = new InsightsMonitors(); + + for (int i = 0; i < _diagnosticsProperties.Count; i++) + { + if (_diagnosticsProperties[i].PropertyType == typeof(RepeatedField<double>)) + { + var arr = _diagnosticsProperties[i].GetValue(diagnosticsMonitors) as RepeatedField<double>; + + if (arr.Count > 0) + { + _insightsProperties[i].SetValue(insightsMonitors, arr.Average()); + } + } + } + + return insightsMonitors; + } + + public static InsightsMonitors AverageMonitors(List<InsightsMonitors> insightsMonitorsCollection) + { + InsightsMonitors monitors = new InsightsMonitors(); + + foreach (var prop in _insightsProperties.Where(x => !typeof(IEnumerable).IsAssignableFrom(x.PropertyType)).ToList()) + { + prop.SetValue(monitors, insightsMonitorsCollection.Average(x => (double)prop.GetValue(x))); + } + + return monitors; + } + + public static InsightsMonitors AverageMonitors(List<DiagnosticsMonitors> diagnosticsMonitorsCollection) + { + List<InsightsMonitors> insightsMonitorsCollection = diagnosticsMonitorsCollection.ToList().Select(x => InsightsHelper.MapMonitors(x)).ToList(); + return AverageMonitors(insightsMonitorsCollection); + } + + public static InsightsMonitors CreateEmptyGap() + { + InsightsMonitors monitors = new InsightsMonitors(); + + foreach (var prop in _insightsProperties.Where(x => !typeof(IEnumerable).IsAssignableFrom(x.PropertyType)).ToList()) + { + prop.SetValue(monitors, double.NaN); + } + + return monitors; + } + } +} diff --git a/Software/Visual_Studio/Tango.Insights/InsightsListener.cs b/Software/Visual_Studio/Tango.Insights/InsightsListener.cs new file mode 100644 index 000000000..0df5b63a1 --- /dev/null +++ b/Software/Visual_Studio/Tango.Insights/InsightsListener.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; +using Tango.Integration.Operation; +using Tango.PMR.Diagnostics; +using Tango.PMR.Insights; + +namespace Tango.Insights +{ + public class InsightsListener + { + private InsightsManager _manager; + private IMachineOperator _operator; + private Timer _timer; + private List<DiagnosticsMonitors> _diagnosticsQueue; + private int _timerCount; + private int _deleteTicks; + private bool _writing; + + public bool IsStarted { get; private set; } + public TimeSpan WriteInterval { get; set; } + public TimeSpan DeleteInterval { get; set; } + public TimeSpan MaxFramesStorage { get; set; } + + public InsightsListener(InsightsManager manager, IMachineOperator machineOperator) + { + _diagnosticsQueue = new List<DiagnosticsMonitors>(); + + WriteInterval = TimeSpan.FromMinutes(0.1); + DeleteInterval = TimeSpan.FromMinutes(60); + MaxFramesStorage = TimeSpan.FromDays(30); + + _manager = manager; + _operator = machineOperator; + + _operator.DiagnosticsDataAvailable += _operator_DiagnosticsDataAvailable; + } + + public InsightsListener(IMachineOperator machineOperator) : this(InsightsManager.Default, machineOperator) + { + + } + + public void Start() + { + if (!IsStarted) + { + if (_timer == null) + { + _timer = new Timer(); + _timer.Interval = WriteInterval.TotalMilliseconds; + } + + _writing = false; + _timerCount = 0; + _deleteTicks = (int)(DeleteInterval.TotalMilliseconds / WriteInterval.TotalMilliseconds); + + _diagnosticsQueue.Clear(); + IsStarted = true; + _timer.Elapsed += _timer_Elapsed; + _timer.Start(); + } + } + + public void Stop() + { + if (IsStarted) + { + _timer.Stop(); + _diagnosticsQueue.Clear(); + } + } + + private void _operator_DiagnosticsDataAvailable(object sender, PMR.Diagnostics.StartDiagnosticsResponse e) + { + if (IsStarted && e.Monitors != null) + { + _diagnosticsQueue.Add(e.Monitors); + } + } + + private void _timer_Elapsed(object sender, ElapsedEventArgs e) + { + if (!IsStarted || _writing) return; + + _writing = true; + + InsightsFrame frame = null; + + if (_diagnosticsQueue.Count > 0) + { + var queue = _diagnosticsQueue.ToList(); + _diagnosticsQueue.Clear(); + + InsightsMonitors monitorsAvg = InsightsHelper.AverageMonitors(queue); + queue.Clear(); + + frame = InsightsFrame.FromInsightsMonitors(monitorsAvg, DateTime.UtcNow.Subtract(WriteInterval)); + } + else + { + frame = InsightsFrame.CreateEmpty(DateTime.UtcNow.Subtract(WriteInterval)); + } + + _manager.InsertFrame(frame); + + _timerCount++; + + if (_timerCount >= _deleteTicks) + { + _timerCount = 0; + _manager.DeleteFrames(DateTime.UtcNow.Subtract(MaxFramesStorage)); + } + + _writing = false; + } + } +} diff --git a/Software/Visual_Studio/Tango.Insights/InsightsManager.cs b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs new file mode 100644 index 000000000..7597aabf4 --- /dev/null +++ b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs @@ -0,0 +1,81 @@ +using LiteDB; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Insights +{ + public class InsightsManager : IDisposable + { + private const string INSIGHTS_COLLECTION = "Insights"; + + private static InsightsManager _instance; + public static InsightsManager Default + { + get + { + if (_instance == null) + { + _instance = new InsightsManager(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Insights", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName) + ".insights")); + } + + return _instance; + } + } + + private LiteDatabase _database; + + public String DatabasePath { get; private set; } + + private InsightsManager(String databasePath) + { + DatabasePath = databasePath; + Directory.CreateDirectory(Path.GetDirectoryName(DatabasePath)); + _database = new LiteDatabase($"Filename={DatabasePath}"); + } + + public virtual void Dispose() + { + if (_database != null) + { + try + { + _database.Dispose(); + _database = null; + } + catch { } + } + } + + ~InsightsManager() + { + Dispose(); + } + + private ILiteCollection<InsightsFrame> GetCollection() + { + return _database.GetCollection<InsightsFrame>(INSIGHTS_COLLECTION); + } + + public virtual void InsertFrame(InsightsFrame frame) + { + var collection = GetCollection(); + collection.Insert(frame); + } + + public virtual List<InsightsFrame> GetFrames(DateTime startUTC, DateTime endUTC) + { + var collection = GetCollection(); + return collection.Find(x => x.Time >= startUTC && x.Time <= endUTC).ToList(); + } + + public virtual int DeleteFrames(DateTime maxDateUTC) + { + var collection = GetCollection(); + return collection.DeleteMany(x => x.Time < maxDateUTC); + } + } +} diff --git a/Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2c2308493 --- /dev/null +++ b/Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Tango - Insights Library")] +[assembly: AssemblyVersion("2.0.12.1737")] +[assembly: ComVisible(false)]
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj b/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj new file mode 100644 index 000000000..0b9ecc641 --- /dev/null +++ b/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{4A55C185-3F8D-41B0-8815-C15F6213A14A}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Tango.Insights</RootNamespace> + <AssemblyName>Tango.Insights</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\Versioning\GlobalVersionInfo.cs"> + <Link>GlobalVersionInfo.cs</Link> + </Compile> + <Compile Include="InsightsHelper.cs" /> + <Compile Include="InsightsFrame.cs" /> + <Compile Include="InsightsListener.cs" /> + <Compile Include="InsightsManager.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Integration\Tango.Integration.csproj"> + <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project> + <Name>Tango.Integration</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.PMR\Tango.PMR.csproj"> + <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project> + <Name>Tango.PMR</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Transport\Tango.Transport.csproj"> + <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> + <Name>Tango.Transport</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Google.Protobuf"> + <Version>3.4.1</Version> + </PackageReference> + <PackageReference Include="LiteDB"> + <Version>5.0.4</Version> + </PackageReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file |
