diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-16 20:46:30 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-16 20:46:30 +0300 |
| commit | 5282624fc0f2ba7b5191219a0e941c9b53d1843b (patch) | |
| tree | f4dc6603a125727a59ef956cc05a8dd4b8e2779d /Software/Visual_Studio | |
| parent | e9f317178f6454836d488cf1e65d04b20b02d334 (diff) | |
| download | Tango-5282624fc0f2ba7b5191219a0e941c9b53d1843b.tar.gz Tango-5282624fc0f2ba7b5191219a0e941c9b53d1843b.zip | |
Telemetry Logs & Machine Updates.
Diffstat (limited to 'Software/Visual_Studio')
12 files changed, 286 insertions, 9 deletions
diff --git a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs index 867665f89..f3b0237d8 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs @@ -12,6 +12,8 @@ namespace Tango.BL.Entities { public class TangoUpdate : TangoUpdateBase { + public static event EventHandler<TangoUpdate> TangoUpdateSaved; + [NotMapped] [JsonIgnore] public TangoUpdateStatuses UpdateStatus @@ -166,5 +168,12 @@ namespace Tango.BL.Entities base.OnStatusChanged(status); RaisePropertyChanged(nameof(UpdateStatus)); } + + public override void OnBeforeSave() + { + base.OnBeforeSave(); + + TangoUpdateSaved?.Invoke(this, this); + } } } diff --git a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs index 3d330b797..6bacf610b 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs @@ -133,9 +133,13 @@ namespace Tango.BL { foreach (var entity in ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified).ToList()) { - if (entity is IObservableEntity && entity != null) + if (entity is IObservableEntity en) { - (entity as IObservableEntity).OnBeforeSave(); + en?.OnBeforeSave(); + } + else if (entity.Entity is IObservableEntity en2) + { + en2?.OnBeforeSave(); } } diff --git a/Software/Visual_Studio/Tango.Telemetry/Mappers/MachineUpdateMapper.cs b/Software/Visual_Studio/Tango.Telemetry/Mappers/MachineUpdateMapper.cs new file mode 100644 index 000000000..d02d8f64d --- /dev/null +++ b/Software/Visual_Studio/Tango.Telemetry/Mappers/MachineUpdateMapper.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.Telemetry.Telemetries; + +namespace Tango.Telemetry.Mappers +{ + public class MachineUpdateMapper + { + public static TelemetryMachineUpdate MapMachineUpdate(TangoUpdate update) + { + TelemetryMachineUpdate tUpdate = new TelemetryMachineUpdate(); + tUpdate.Time = update.LastUpdated; + tUpdate.ID = update.Guid; + tUpdate.StartTime = update.StartDate; + tUpdate.EndTime = update.EndDate; + tUpdate.ApplicationVersion = update.ApplicationVersion; + tUpdate.FirmwareVersion = update.FirmwareVersion; + tUpdate.VersionTag = update.ApplicationVersionTag; + tUpdate.Status = update.UpdateStatus.ToString(); + tUpdate.FailedReason = update.FailedReason; + tUpdate.FailedLog = update.FailedLog; + + return tUpdate; + } + } +} diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs index b13402831..f7aee1f4c 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobRunsHistorySource.cs @@ -26,9 +26,16 @@ namespace Tango.Telemetry.Sources } else { - using (ObservablesContext db = ObservablesContext.CreateDefault()) + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + return await db.JobRuns.CountAsync(x => x.LastUpdated < from) > 0; + } + } + catch { - return await db.JobRuns.CountAsync(x => x.LastUpdated < from) > 0; + return false; } } } diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryLogsStreamingSource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryLogsStreamingSource.cs index 8001caac8..9deb93132 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryLogsStreamingSource.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryLogsStreamingSource.cs @@ -28,12 +28,12 @@ namespace Tango.Telemetry.Sources _lastFirmwareMessage = new KeyValuePair<DateTime, string>(DateTime.MinValue, String.Empty); } - public TelemetryLogsStreamingSource(IMachineOperator machineOperator) + public TelemetryLogsStreamingSource(IMachineOperator machineOperator) : this() { MachineOperator = machineOperator; } - public void Start() + public virtual void Start() { if (!IsStarted) { @@ -47,13 +47,14 @@ namespace Tango.Telemetry.Sources { if (IsStarted) { - if (Config.Categories.Contains((LogCategory)log.Category)) return; + if (!Config.Categories.Contains((LogCategory)log.Category)) return; if (log.Message == _lastFirmwareMessage.Value && DateTime.UtcNow < _lastFirmwareMessage.Key.AddSeconds(1)) return; _lastFirmwareMessage = new KeyValuePair<DateTime, string>(DateTime.UtcNow, log.Message); TelemetryLog tLog = new TelemetryLog(); + tLog.Source = "Firmware"; tLog.Time = DateTime.UtcNow; tLog.Category = log.Category.ToString(); tLog.Class = log.FileName; @@ -68,9 +69,10 @@ namespace Tango.Telemetry.Sources { if (IsStarted) { - if (Config.Categories.Contains(log.Category)) return; + if (!Config.Categories.Contains(log.Category)) return; TelemetryLog tLog = new TelemetryLog(); + tLog.Source = "Application"; tLog.Time = log.TimeStamp.ToUniversalTime(); tLog.Category = log.Category.ToString(); tLog.Class = log.ClassName; diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryMachineUpdatesHistorySource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryMachineUpdatesHistorySource.cs new file mode 100644 index 000000000..0b78018e6 --- /dev/null +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryMachineUpdatesHistorySource.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.BL.Enumerations; +using Tango.Telemetry.Mappers; +using Tango.Telemetry.Telemetries; + +namespace Tango.Telemetry.Sources +{ + public class TelemetryMachineUpdatesHistorySource : ITelemetryHistorySource + { + private bool _isBusy; + + public TelemetryHistorySourceDirection Direction { get; } = TelemetryHistorySourceDirection.Descending; + + public string Name { get; } = "Machine Updates History"; + + public bool RequiresTelemetryDuplicationTracking { get; } = true; + + public async Task<bool> CanRequestHistory(DateTime from) + { + if (_isBusy) + { + return false; + } + else + { + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + return await db.TangoUpdates.CountAsync(x => x.LastUpdated < from) > 0; + } + } + catch + { + return false; + } + } + } + + public async Task<IEnumerable<ITelemetry>> RequestHistory(DateTime from) + { + try + { + _isBusy = true; + + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + int[] skipArr = { (int)TangoUpdateStatuses.SynchronizationCompleted, (int)TangoUpdateStatuses.SynchronizationFailed, (int)TangoUpdateStatuses.SynchronizationStarted }; + var updates = await db.TangoUpdates.Where(x => x.LastUpdated <= from && !skipArr.Contains(x.Status)).Take(10).ToListAsync(); + + List<TelemetryMachineUpdate> tUpdates = new List<TelemetryMachineUpdate>(); + + foreach (var update in updates) + { + TelemetryMachineUpdate tUpdate = MachineUpdateMapper.MapMachineUpdate(update); + tUpdates.Add(tUpdate); + } + + return tUpdates; + } + } + finally + { + _isBusy = false; + } + } + + public void Dispose() + { + + } + } +} diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryMachineUpdatesStreamingSource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryMachineUpdatesStreamingSource.cs new file mode 100644 index 000000000..85d5309a5 --- /dev/null +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryMachineUpdatesStreamingSource.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.BL.Enumerations; +using Tango.Telemetry.Mappers; +using Tango.Telemetry.Telemetries; + +namespace Tango.Telemetry.Sources +{ + public class TelemetryMachineUpdatesStreamingSource : ITelemetryStreamingSource + { + public string Name { get; } = "Machine Updates Streaming"; + + public bool RequiresTelemetryDuplicationTracking { get; } = true; + + public bool IsStarted { get; private set; } + + public event EventHandler<TelemetryAvailableEventArgs> TelemetryAvailable; + + public void Start() + { + if (!IsStarted) + { + IsStarted = true; + TangoUpdate.TangoUpdateSaved += TangoUpdate_UpdateSaved; + } + } + + public void Stop() + { + if (IsStarted) + { + IsStarted = false; + TangoUpdate.TangoUpdateSaved -= TangoUpdate_UpdateSaved; + } + } + + private void TangoUpdate_UpdateSaved(object sender, TangoUpdate update) + { + if (IsStarted) + { + if (!update.IsSynchronization) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + if (db.TangoUpdates.Any(x => x.Guid == update.Guid)) return; + + TelemetryMachineUpdate tUpdate = MachineUpdateMapper.MapMachineUpdate(update); + + TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs() { TelemetryObject = tUpdate }); + } + } + } + } + + public void Dispose() + { + Stop(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj b/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj index b04b0654d..35ddf9839 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj +++ b/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj @@ -251,6 +251,7 @@ <Compile Include="ITelemetryPublisher.cs" /> <Compile Include="ITelemetryStreamingSource.cs" /> <Compile Include="Mappers\JobRunMapper.cs" /> + <Compile Include="Mappers\MachineUpdateMapper.cs" /> <Compile Include="Reporting\DestinationStatusSummary.cs" /> <Compile Include="Reporting\SourceSummary.cs" /> <Compile Include="Reporting\SourceTypeSummary.cs" /> @@ -263,7 +264,10 @@ <Compile Include="Sources\TelemetryJobRunsStreamingSource.cs" /> <Compile Include="Sources\TelemetryLogsStreamingSource.cs" /> <Compile Include="Sources\TelemetryLogsStreamingSourceConfig.cs" /> + <Compile Include="Sources\TelemetryMachineUpdatesStreamingSource.cs" /> + <Compile Include="Sources\TelemetryMachineUpdatesHistorySource.cs" /> <Compile Include="Telemetries\TelemetryLog.cs" /> + <Compile Include="Telemetries\TelemetryMachineUpdate.cs" /> <Compile Include="TelemetryConfigurableSource.cs" /> <Compile Include="TelemetryHistorySourceCheckPoint.cs" /> <Compile Include="TelemetryHistorySourceDirection.cs" /> diff --git a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs index 358ce7e70..82fb53617 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryDiagnosticsFrame.cs @@ -14,5 +14,10 @@ namespace Tango.Telemetry.Telemetries public class TelemetryDiagnosticsFrame : TelemetryBase { public InsightsMonitors Monitors { get; set; } + + public TelemetryDiagnosticsFrame() : base() + { + ID = String.Empty; + } } } diff --git a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryLog.cs b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryLog.cs index c37f6fd29..e32243d54 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryLog.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryLog.cs @@ -6,8 +6,11 @@ using System.Threading.Tasks; namespace Tango.Telemetry.Telemetries { + [TelemetryName("Log", 1)] public class TelemetryLog : TelemetryBase { + public String Source { get; set; } + public String Category { get; set; } public String Class { get; set; } @@ -17,5 +20,10 @@ namespace Tango.Telemetry.Telemetries public int Line { get; set; } public String Message { get; set; } + + public TelemetryLog() : base() + { + ID = String.Empty; + } } } diff --git a/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryMachineUpdate.cs b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryMachineUpdate.cs new file mode 100644 index 000000000..bf2c391d6 --- /dev/null +++ b/Software/Visual_Studio/Tango.Telemetry/Telemetries/TelemetryMachineUpdate.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Telemetry.Telemetries +{ + [TelemetryName("MachineUpdate", 1)] + public class TelemetryMachineUpdate : TelemetryBase + { + public DateTime StartTime { get; set; } + public DateTime? EndTime { get; set; } + public String ApplicationVersion { get; set; } + public String FirmwareVersion { get; set; } + public String VersionTag { get; set; } + public String FailedReason { get; set; } + public String FailedLog { get; set; } + public String Status { get; set; } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs index 0b90f0de4..a75b63771 100644 --- a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs +++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs @@ -40,12 +40,31 @@ namespace Tango.Telemetry.Tester.IOT.CLI (publisher.StorageManager as TelemetryLiteDBStorageManager).EnableCheckPointsRecovery = false; //publisher.RegisterSource(new JobRunsTestSource()); - publisher.RegisterSource(new DiagnosticsTestSource()); + //publisher.RegisterSource(new DiagnosticsTestSource()); + publisher.RegisterSource(new TelemetryMachineUpdatesStreamingSource()); publisher.RegisterDestination(new TelemetryAzureHubDestination("HostName=iot-twine-dev-weu.azure-devices.net;DeviceId=telemetry-dev-01;SharedAccessKey=cZhCMhiVL+TF7p13fpX+lFmyxoy8ZqCkbxUwumWw18Q=")); publisher.PublishResultAvailable += Publisher_PublishResultAvailable; publisher.PublishingPackage += Publisher_PublishingPackage; + Task.Factory.StartNew(() => + { + Thread.Sleep(2000); + using (ObservablesContext db = new ObservablesContext()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = "1.0.0.0"; + update.FirmwareVersion = "1.2.3.4"; + update.UpdateStatus = TangoUpdateStatuses.DatabaseFailed; + update.FailedReason = "Fake Reason"; + update.FailedLog = "Failed log something..."; + update.StartDate = DateTime.UtcNow; + update.EndDate = DateTime.UtcNow.AddMinutes(1); + db.TangoUpdates.Add(update); + db.SaveChanges(); + } + }); + publisher.Start().GetAwaiter().GetResult(); Console.Clear(); @@ -208,4 +227,26 @@ namespace Tango.Telemetry.Tester.IOT.CLI IsStarted = false; } } + + public class LogsTestSource : TelemetryLogsStreamingSource + { + public LogsTestSource() + { + Config.Categories.Add(LogCategory.Info); + } + + public override void Start() + { + base.Start(); + + Task.Factory.StartNew(() => + { + for (int i = 0; i < 100; i++) + { + Thread.Sleep(100); + LogManager.Log($"This is a info test log {i + 1}.", LogCategory.Info); + } + }); + } + } } |
