aboutsummaryrefslogtreecommitdiffstats
path: root/Software
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-08-23 08:44:31 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-08-23 08:44:31 +0300
commit02ae577faa0bd4938507061d603e4f9447e2b64f (patch)
tree7daf0e275338ec92e93bfca39f2d529d93858162 /Software
parent67770063ff1a1c5c522e3bc29f442c42eb6dc521 (diff)
downloadTango-02ae577faa0bd4938507061d603e4f9447e2b64f.tar.gz
Tango-02ae577faa0bd4938507061d603e4f9447e2b64f.zip
Fixed issue with insights file datetime utc.
added insights application exception/crash. added remote actions service. fixed issue with LiteDB hang on application start/exit. reduced insights listener empty frames.
Diffstat (limited to 'Software')
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_crash.pngbin0 -> 5249 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_exception.pngbin0 -> 2720 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/bug_report.pngbin0 -> 3831 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj7
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml146
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs49
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyApplicationException.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteActions/IRemoteActionsProvider.cs13
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs15
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteActions/DefaultRemoteActionsProvider.cs26
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj1
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs4
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs5
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteActions/IRemoteActionsService.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj3
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsRequest.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionRequest.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionResponse.cs12
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj5
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs33
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs3
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/RemoteActions/DefaultRemoteActionsService.cs54
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj6
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs4
-rw-r--r--Software/Visual_Studio/Tango.Core/Bson/BsonUtcSerializer.cs68
-rw-r--r--Software/Visual_Studio/Tango.Core/Tango.Core.csproj3
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsApplicationException.cs20
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsFile.cs17
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsListener.cs19
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsManager.cs42
-rw-r--r--Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj1
-rw-r--r--Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs13
-rw-r--r--Software/Visual_Studio/Tango.Transport/GenericMessageSerializer.cs52
35 files changed, 578 insertions, 89 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_crash.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_crash.png
new file mode 100644
index 000000000..303952d86
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_crash.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_exception.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_exception.png
new file mode 100644
index 000000000..d14bb84af
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/app_exception.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/bug_report.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/bug_report.png
new file mode 100644
index 000000000..05d00014d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Images/bug_report.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj
index ea6616985..617ca2d99 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Tango.FSE.Insights.csproj
@@ -312,6 +312,13 @@
<ItemGroup>
<Resource Include="Images\detection.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\app_crash.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\bug_report.png" />
+ <Resource Include="Images\app_exception.png" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml
index 5426ba4ea..b4b3fe746 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/Themes/Generic.xaml
@@ -11,7 +11,7 @@
<DataTemplate x:Key="InsightEventTemplate" DataType="{x:Type commonInsights:InsightsReadyEvent}">
- <Border Tag="{Binding DataContext,RelativeSource={RelativeSource AncestorType=views:InsightsView}}" Padding="10 5" Cursor="Hand" IsHitTestVisible="True" BorderThickness="1" CornerRadius="3" BorderBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}">
+ <Border Tag="{Binding DataContext,RelativeSource={RelativeSource AncestorType=views:InsightsView}}" Padding="10 5" IsHitTestVisible="True" BorderThickness="1" CornerRadius="3" BorderBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}">
<Border.ToolTip>
<StackPanel>
<TextBlock TextWrapping="Wrap">
@@ -139,7 +139,7 @@
</DataTemplate>
<DataTemplate x:Key="InsightBugTemplate" DataType="{x:Type commonInsights:InsightsReadyBug}">
- <Border MaxWidth="300" Tag="{Binding DataContext,RelativeSource={RelativeSource AncestorType=views:InsightsView}}" Padding="10 5" Cursor="Hand" IsHitTestVisible="True" BorderThickness="1" CornerRadius="15" BorderBrush="{StaticResource FSE_ErrorBrush}">
+ <Border MaxWidth="300" Tag="{Binding DataContext,RelativeSource={RelativeSource AncestorType=views:InsightsView}}">
<Border.ToolTip>
<StackPanel>
<TextBlock TextWrapping="Wrap">
@@ -167,7 +167,7 @@
</Border.ToolTip>
<Border.Style>
<Style TargetType="Border">
- <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundDarkBrush}"></Setter>
+ <Setter Property="Opacity" Value="1"></Setter>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
@@ -192,7 +192,7 @@
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
- <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundLightBrush}"></Setter>
+ <Setter Property="Opacity" Value="0.8"></Setter>
</Trigger>
<EventTrigger RoutedEvent="PreviewMouseRightButtonUp">
<EventTrigger.Actions>
@@ -208,10 +208,140 @@
</Style.Triggers>
</Style>
</Border.Style>
- <DockPanel>
- <material:PackIcon Height="16" Width="16" Kind="Ladybug" Foreground="{StaticResource FSE_ErrorBrush}" VerticalAlignment="Center"/>
- <TextBlock TextTrimming="CharacterEllipsis" VerticalAlignment="Center" Margin="5 0 0 0" Text="{Binding Bug.Title,Mode=OneWay}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"></TextBlock>
- </DockPanel>
+ <StackPanel>
+ <Image Source="../Images/bug_report.png" Stretch="Uniform" HorizontalAlignment="Center" RenderOptions.BitmapScalingMode="Fant" Width="48" />
+ <TextBlock Foreground="{StaticResource FSE_ErrorBrush}" FontWeight="SemiBold">Bug Report</TextBlock>
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+
+ <DataTemplate x:Key="InsightApplicationExceptionTemplate" DataType="{x:Type commonInsights:InsightsReadyApplicationException}">
+ <Border Tag="{Binding DataContext,RelativeSource={RelativeSource AncestorType=views:InsightsView}}" IsHitTestVisible="True" Canvas.ZIndex="200">
+ <Border.ToolTip>
+ <StackPanel>
+ <TextBlock>Unhandled Application Exception</TextBlock>
+ <TextBlock>
+ <Run>Time:</Run>
+ <Run Text="{Binding Time,Converter={StaticResource DateTimeUtcToLocalDateTime},StringFormat='MM/dd/yyyy hh:mm:ss'}"></Run>
+ </TextBlock>
+ <StackPanel Margin="0 5 0 0">
+ <TextBlock Foreground="{StaticResource FSE_ErrorBrush}">Exception</TextBlock>
+ <Rectangle Margin="0 2 0 0" HorizontalAlignment="Stretch" VerticalAlignment="Top" StrokeThickness="1" Stroke="{StaticResource FSE_PrimaryForegroundBrush}" StrokeDashArray="5" />
+ <TextBlock Text="{Binding Exception,Mode=OneWay}" MaxHeight="200" TextWrapping="Wrap" MaxWidth="400" Margin="0 5 0 0"></TextBlock>
+ </StackPanel>
+ </StackPanel>
+ </Border.ToolTip>
+ <Border.Style>
+ <Style TargetType="Border">
+ <Setter Property="Opacity" Value="1"></Setter>
+ <Setter Property="ContextMenu">
+ <Setter.Value>
+ <ContextMenu>
+ <MenuItem ToolTip="View extended details about this exception" Header="View Details" Command="{Binding PlacementTarget.Tag.ViewApplicationExceptionCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Chip" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <Separator/>
+ <MenuItem ToolTip="Locate related application logs using the Application module" Header="Peek Application Logs" Command="{Binding PlacementTarget.Tag.PeekApplicationLogsCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Application" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <MenuItem ToolTip="Locate related firmware logs using the Firmware module" Header="Peek Firmware Logs" Command="{Binding PlacementTarget.Tag.PeekFirmwareLogsCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Chip" />
+ </MenuItem.Icon>
+ </MenuItem>
+ </ContextMenu>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Opacity" Value="0.8"></Setter>
+ </Trigger>
+ <EventTrigger RoutedEvent="PreviewMouseRightButtonUp">
+ <EventTrigger.Actions>
+ <BeginStoryboard>
+ <Storyboard>
+ <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
+ <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
+ </BooleanAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger.Actions>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ <StackPanel>
+ <Image Source="../Images/app_exception.png" Stretch="Uniform" HorizontalAlignment="Center" RenderOptions.BitmapScalingMode="Fant" Width="48" />
+ <TextBlock Foreground="{StaticResource FSE_ErrorBrush}" FontWeight="SemiBold">Application Exception</TextBlock>
+ </StackPanel>
+ </Border>
+ </DataTemplate>
+
+ <DataTemplate x:Key="InsightApplicationCrashTemplate" DataType="{x:Type commonInsights:InsightsReadyApplicationException}">
+ <Border Tag="{Binding DataContext,RelativeSource={RelativeSource AncestorType=views:InsightsView}}" IsHitTestVisible="True" Margin="-80 0 0 0">
+ <Border.ToolTip>
+ <StackPanel>
+ <TextBlock>Application Crash!</TextBlock>
+ <TextBlock>
+ <Run>Time:</Run>
+ <Run Text="{Binding Time,Converter={StaticResource DateTimeUtcToLocalDateTime},StringFormat='MM/dd/yyyy hh:mm:ss'}"></Run>
+ </TextBlock>
+ <StackPanel Margin="0 5 0 0">
+ <TextBlock Text="{Binding Exception,Mode=OneWay}" TextWrapping="Wrap" MaxHeight="200" MaxWidth="400" Margin="0 5 0 0" TextTrimming="CharacterEllipsis"></TextBlock>
+ </StackPanel>
+ </StackPanel>
+ </Border.ToolTip>
+ <Border.Style>
+ <Style TargetType="Border">
+ <Setter Property="Opacity" Value="1"></Setter>
+ <Setter Property="ContextMenu">
+ <Setter.Value>
+ <ContextMenu>
+ <MenuItem ToolTip="View extended details about this exception" Header="View Details" Command="{Binding PlacementTarget.Tag.ViewApplicationExceptionCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Chip" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <Separator/>
+ <MenuItem ToolTip="Locate related application logs using the Application module" Header="Peek Application Logs" Command="{Binding PlacementTarget.Tag.PeekApplicationLogsCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Application" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <MenuItem ToolTip="Locate related firmware logs using the Firmware module" Header="Peek Firmware Logs" Command="{Binding PlacementTarget.Tag.PeekFirmwareLogsCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Chip" />
+ </MenuItem.Icon>
+ </MenuItem>
+ </ContextMenu>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Opacity" Value="0.8"></Setter>
+ </Trigger>
+ <EventTrigger RoutedEvent="PreviewMouseRightButtonUp">
+ <EventTrigger.Actions>
+ <BeginStoryboard>
+ <Storyboard>
+ <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
+ <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
+ </BooleanAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger.Actions>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ <Grid>
+ <Image Source="../Images/app_crash.png" Stretch="Fill" RenderOptions.BitmapScalingMode="Fant" Width="160" Height="40" />
+ <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Red" FontWeight="SemiBold" FontSize="{StaticResource FSE_SmallFontSize}">Application Crash!</TextBlock>
+ </Grid>
</Border>
</DataTemplate>
</ResourceDictionary> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs
index 6ef92e525..ccbb77cf1 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Insights/ViewModels/InsightsViewVM.cs
@@ -20,6 +20,7 @@ using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.FSE.Common;
+using Tango.FSE.Common.Dialogs;
using Tango.FSE.Common.Insights;
using Tango.FSE.Insights.Contracts;
using Tango.FSE.Insights.Dialogs;
@@ -189,6 +190,8 @@ namespace Tango.FSE.Insights.ViewModels
public RelayCommand<InsightsReadyBug> OpenBugReportCommand { get; set; }
+ public RelayCommand<InsightsReadyApplicationException> ViewApplicationExceptionCommand { get; set; }
+
public RelayCommand AnalyzeCommand { get; set; }
#endregion
@@ -210,6 +213,7 @@ namespace Tango.FSE.Insights.ViewModels
PeekApplicationLogsCommand = new RelayCommand<InsightReadyBase>(PeekAnnotationApplicationLogs);
PeekFirmwareLogsCommand = new RelayCommand<InsightReadyBase>(PeekAnnotationFirmwareLogs);
OpenBugReportCommand = new RelayCommand<InsightsReadyBug>(OpenAnnotationBugReport);
+ ViewApplicationExceptionCommand = new RelayCommand<InsightsReadyApplicationException>(ViewAnnotationApplicationException);
AnalyzeCommand = new RelayCommand(Analyze, () => InsightsPackage != null);
}
@@ -482,12 +486,12 @@ namespace Tango.FSE.Insights.ViewModels
line.Stroke = connected ? Brushes.Green : Brushes.DarkGray;
line.X1 = date;
line.X2 = date;
- line.ShowLabel = false;
- line.AnnotationLabels.Add(new AnnotationLabel()
- {
- LabelPlacement = connected ? LabelPlacement.TopRight : LabelPlacement.BottomLeft,
- Text = connected ? "machine connected" : "machine disconnected"
- });
+ //line.ShowLabel = false;
+ //line.AnnotationLabels.Add(new AnnotationLabel()
+ //{
+ // LabelPlacement = connected ? LabelPlacement.TopRight : LabelPlacement.BottomLeft,
+ // Text = connected ? "machine connected" : "machine disconnected"
+ //});
Annotations.Add(line);
}
@@ -495,7 +499,7 @@ namespace Tango.FSE.Insights.ViewModels
{
var y = 0.05;
- foreach (var insight in package.Events.Cast<InsightReadyBase>().Concat(package.Statuses).Concat(package.Bugs).OrderBy(x => x.Time))
+ foreach (var insight in package.Events.Cast<InsightReadyBase>().Concat(package.Statuses).Concat(package.Bugs).Concat(package.ApplicationExceptions).OrderBy(x => x.Time))
{
CustomAnnotation annotation = new CustomAnnotation();
annotation.X1 = insight.Time.ToLocalTime();
@@ -509,14 +513,30 @@ namespace Tango.FSE.Insights.ViewModels
}
else if (insight is InsightsReadyStatus status)
{
+ Panel.SetZIndex(annotation, 1);
annotation.Content = status;
annotation.ContentTemplate = Application.Current.Resources["InsightStatusTemplate"] as DataTemplate;
}
else if (insight is InsightsReadyBug bug)
{
+ Panel.SetZIndex(annotation, 2);
annotation.Content = bug;
annotation.ContentTemplate = Application.Current.Resources["InsightBugTemplate"] as DataTemplate;
}
+ else if (insight is InsightsReadyApplicationException appException)
+ {
+ annotation.Content = appException;
+ Panel.SetZIndex(annotation, 3);
+
+ if (appException.IsApplicationCrash)
+ {
+ annotation.ContentTemplate = Application.Current.Resources["InsightApplicationCrashTemplate"] as DataTemplate;
+ }
+ else
+ {
+ annotation.ContentTemplate = Application.Current.Resources["InsightApplicationExceptionTemplate"] as DataTemplate;
+ }
+ }
Annotations.Add(annotation);
@@ -531,7 +551,7 @@ namespace Tango.FSE.Insights.ViewModels
#endregion
- #region Logs Peeking
+ #region Menu Items Handling
private async void PeekAnnotationFirmwareLogs(InsightReadyBase ev)
{
@@ -551,15 +571,20 @@ namespace Tango.FSE.Insights.ViewModels
}
}
- #endregion
-
- #region Bug Report
-
private void OpenAnnotationBugReport(InsightsReadyBug bug)
{
Process.Start(bug.Bug.URL);
}
+ private async void ViewAnnotationApplicationException(InsightsReadyApplicationException appException)
+ {
+ MessageLogItem logItem = new MessageLogItem();
+ logItem.Category = LogCategory.Critical;
+ logItem.TimeStamp = appException.Time;
+ logItem.Message = appException.Exception;
+ await NotificationProvider.ShowDialog(new ApplicationLogItemViewVM() { LogItem = logItem });
+ }
+
#endregion
#region Event Handlers
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs
index 3f57a50d9..a823295a9 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsPackage.cs
@@ -14,6 +14,7 @@ namespace Tango.FSE.Common.Insights
public List<InsightsReadyFrame> Frames { get; set; }
public List<InsightsReadyEvent> Events { get; set; }
public List<InsightsReadyStatus> Statuses { get; set; }
+ public List<InsightsReadyApplicationException> ApplicationExceptions { get; set; }
public List<InsightsReadyBug> Bugs { get; set; }
public InsightsPackage()
@@ -22,6 +23,7 @@ namespace Tango.FSE.Common.Insights
Events = new List<InsightsReadyEvent>();
Statuses = new List<InsightsReadyStatus>();
Bugs = new List<InsightsReadyBug>();
+ ApplicationExceptions = new List<InsightsReadyApplicationException>();
}
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyApplicationException.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyApplicationException.cs
new file mode 100644
index 000000000..9f4524100
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Insights/InsightsReadyApplicationException.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Common.Insights
+{
+ public class InsightsReadyApplicationException : InsightReadyBase
+ {
+ public String Exception { get; set; }
+ public bool IsApplicationCrash { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteActions/IRemoteActionsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteActions/IRemoteActionsProvider.cs
new file mode 100644
index 000000000..024a8ac39
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/RemoteActions/IRemoteActionsProvider.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Common.RemoteActions
+{
+ public interface IRemoteActionsProvider
+ {
+ void SimulateApplicationException(bool causeCrash);
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
index b89d30f82..cbd70e665 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
@@ -228,6 +228,7 @@
<Compile Include="INotifyApplicationReady.cs" />
<Compile Include="Insights\InsightReadyBase.cs" />
<Compile Include="Insights\IInsightsProvider.cs" />
+ <Compile Include="Insights\InsightsReadyApplicationException.cs" />
<Compile Include="Insights\InsightsReadyBug.cs" />
<Compile Include="Insights\InsightsReadyEvent.cs" />
<Compile Include="Insights\InsightsHandler.cs" />
@@ -262,6 +263,7 @@
<Compile Include="Performance\PerformancePackageEventArgs.cs" />
<Compile Include="MachineUpdates\IMachineUpdatesProvider.cs" />
<Compile Include="MachineUpdates\MachineUpdatesResult.cs" />
+ <Compile Include="RemoteActions\IRemoteActionsProvider.cs" />
<Compile Include="RemoteDesktop\DesktopFrameReceivedEventArgs.cs" />
<Compile Include="RemoteDesktop\IRemoteDesktopProvider.cs" />
<Compile Include="RemoteDesktop\Mp4VideoEncoder.cs" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs
index 5b17bd5e0..08120c24f 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Insights/DefaultInsightsProvider.cs
@@ -55,7 +55,10 @@ namespace Tango.FSE.UI.Insights
var response = await MachineProvider.MachineOperator.SendGenericRequest<InsightsRequest, InsightsResponse>(new InsightsRequest()
{
StartDateUTC = startDateUTC,
- EndDateUTC = endTimeUTC
+ EndDateUTC = endTimeUTC,
+ IncludeStatuses = true,
+ IncludeEvents = true,
+ IncludeApplicationExceptions = true
}, new TransportRequestConfig()
{
Timeout = TimeSpan.FromMinutes(1),
@@ -142,6 +145,16 @@ namespace Tango.FSE.UI.Insights
});
}
+ foreach (var appException in insightsFile.ApplicationExceptions)
+ {
+ package.ApplicationExceptions.Add(new InsightsReadyApplicationException()
+ {
+ Time = appException.Time,
+ Exception = appException.Exception,
+ IsApplicationCrash = appException.IsApplicationCrash
+ });
+ }
+
if (AuthenticationProvider.CurrentUser.HasPermission(Permissions.FSE_ModifyBugReport))
{
try
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteActions/DefaultRemoteActionsProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteActions/DefaultRemoteActionsProvider.cs
new file mode 100644
index 000000000..98256fa3c
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/RemoteActions/DefaultRemoteActionsProvider.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.DI;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.RemoteActions;
+using Tango.PPC.Shared.RemoteActions;
+
+namespace Tango.FSE.UI.RemoteActions
+{
+ public class DefaultRemoteActionsProvider : IRemoteActionsProvider
+ {
+ [TangoInject]
+ private IMachineProvider MachineProvider { get; set; }
+
+ public void SimulateApplicationException(bool causeCrash)
+ {
+ var response = MachineProvider.MachineOperator.SendGenericRequest<SimulateApplicationExceptionRequest, SimulateApplicationExceptionResponse>(new SimulateApplicationExceptionRequest()
+ {
+ CrashApplication = causeCrash,
+ }).Result;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
index 8974407d4..17fa594fd 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
@@ -330,6 +330,7 @@
<Compile Include="Panes\MachineConnectionPaneVM.cs" />
<Compile Include="Performance\DefaultPerformanceProvider.cs" />
<Compile Include="MachineUpdates\DefaultMachineUpdatesProvider.cs" />
+ <Compile Include="RemoteActions\DefaultRemoteActionsProvider.cs" />
<Compile Include="RemoteDesktop\DefaultRemoteDesktopProvider.cs" />
<Compile Include="RemoteUpgrade\DefaultRemoteUpgradeManager.cs" />
<Compile Include="Resolution\DefaultResolutionService.cs" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
index 5da32809f..e70b25d09 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
@@ -68,6 +68,8 @@ using Tango.FSE.Common.FileAssociation;
using Tango.FSE.UI.FileAssociation;
using Tango.FSE.Common.Insights;
using Tango.FSE.UI.Insights;
+using Tango.FSE.Common.RemoteActions;
+using Tango.FSE.UI.RemoteActions;
namespace Tango.FSE.UI
{
@@ -107,6 +109,7 @@ namespace Tango.FSE.UI
TangoIOC.Default.Unregister<IRemoteSqlProvider>();
TangoIOC.Default.Unregister<IFileAssociationProvider>();
TangoIOC.Default.Unregister<IInsightsProvider>();
+ TangoIOC.Default.Unregister<IRemoteActionsProvider>();
//TangoIOC.Default.Unregister<ExternalBridgeScanner>();
//TangoIOC.Default.Unregister<IDiagnosticsFrameProvider>();
//TangoIOC.Default.Unregister<IEventLogger>();
@@ -146,6 +149,7 @@ namespace Tango.FSE.UI
TangoIOC.Default.Register<IRemoteSqlProvider, DefaultRemoteSqlProvider>();
TangoIOC.Default.Register<IFileAssociationProvider, DefaultFileAssociationProvider>();
TangoIOC.Default.Register<IInsightsProvider, DefaultInsightsProvider>();
+ TangoIOC.Default.Register<IRemoteActionsProvider, DefaultRemoteActionsProvider>();
TangoIOC.Default.Register<MainWindowVM>();
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs
index f015c3bad..75c5ae9cd 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs
@@ -89,6 +89,11 @@ namespace Tango.PPC.Common.Insights
insightsFile.Statuses = InsightsManager.Default.GetStatuses(request.StartDateUTC, request.EndDateUTC);
}
+ if (request.IncludeApplicationExceptions)
+ {
+ insightsFile.ApplicationExceptions = InsightsManager.Default.GetApplicationExceptions(request.StartDateUTC, request.EndDateUTC);
+ }
+
insightsFile.ToFile(filePath);
});
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteActions/IRemoteActionsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteActions/IRemoteActionsService.cs
new file mode 100644
index 000000000..477663342
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteActions/IRemoteActionsService.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.RemoteActions
+{
+ public interface IRemoteActionsService
+ {
+
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
index 08e49621c..ed0c30755 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
@@ -179,6 +179,7 @@
<Compile Include="RemoteDesktop\RemoteDesktopClient.cs" />
<Compile Include="RemoteJob\DefaultRemoteJobService.cs" />
<Compile Include="RemoteJob\IRemoteJobService.cs" />
+ <Compile Include="RemoteActions\IRemoteActionsService.cs" />
<Compile Include="SQL\DefaultRemoteSqlService.cs" />
<Compile Include="SQL\IRemoteSqlService.cs" />
<Compile Include="Synchronization\DefaultMachineDataSynchronizer.cs" />
@@ -483,7 +484,7 @@
</Target>
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsRequest.cs
index 6603a05b5..b34895e78 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsRequest.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Insights/InsightsRequest.cs
@@ -13,11 +13,13 @@ namespace Tango.PPC.Shared.Insights
public bool IncludeEvents { get; set; }
public bool IncludeStatuses { get; set; }
+ public bool IncludeApplicationExceptions { get; set; }
public InsightsRequest()
{
IncludeEvents = true;
IncludeStatuses = true;
+ IncludeApplicationExceptions = true;
}
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionRequest.cs
new file mode 100644
index 000000000..76216edad
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionRequest.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Shared.RemoteActions
+{
+ public class SimulateApplicationExceptionRequest
+ {
+ public bool CrashApplication { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionResponse.cs
new file mode 100644
index 000000000..e0b71ddf4
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/RemoteActions/SimulateApplicationExceptionResponse.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Shared.RemoteActions
+{
+ public class SimulateApplicationExceptionResponse
+ {
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj
index de1eb03b1..bfd4d587b 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj
@@ -95,6 +95,8 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
+ <Compile Include="RemoteActions\SimulateApplicationExceptionRequest.cs" />
+ <Compile Include="RemoteActions\SimulateApplicationExceptionResponse.cs" />
<Compile Include="RemoteUpgrade\StartRemoteFirmwareUpgradeRequest.cs" />
<Compile Include="RemoteUpgrade\StartRemoteFirmwareUpgradeResponse.cs" />
<Compile Include="RemoteUpgrade\StartRemoteApplicationUpgradeResponse.cs" />
@@ -137,5 +139,8 @@
<Name>Tango.SystemInfo</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Simulation\" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
index 16eb656a8..e478dba77 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
@@ -13,6 +13,7 @@ using Tango.BL;
using Tango.Core;
using Tango.Core.DI;
using Tango.Core.Helpers;
+using Tango.Insights;
using Tango.Integration.Operation;
using Tango.Logging;
using Tango.PPC.Common;
@@ -29,7 +30,7 @@ namespace Tango.PPC.UI
/// </summary>
public partial class App : Application
{
- private WpfGlobalExceptionTrapper exceptionTrapper;
+ public static WpfGlobalExceptionTrapper ExceptionTrapper;
public static String[] StartupArgs { get; private set; }
private LogManager LogManager = LogManager.Default;
@@ -80,9 +81,9 @@ namespace Tango.PPC.UI
base.OnStartup(e);
- exceptionTrapper = new WpfGlobalExceptionTrapper();
- exceptionTrapper.Initialize(this);
- exceptionTrapper.ApplicationCrashed += ExceptionTrapper_ApplicationCrashed;
+ ExceptionTrapper = new WpfGlobalExceptionTrapper();
+ ExceptionTrapper.Initialize(this);
+ ExceptionTrapper.ApplicationCrashed += ExceptionTrapper_ApplicationCrashed;
CoreSettings.DefaultDataSource = new DataSource()
{
@@ -100,10 +101,21 @@ namespace Tango.PPC.UI
private async void GetLastApplicationCrashFromWindows()
{
- var logItem = await exceptionTrapper.GetLastApplicationCrashEventLog();
+ var logItem = await ExceptionTrapper.GetLastApplicationCrashEventLog(60);
if (logItem != null)
{
LogManager.Log(logItem);
+
+ try
+ {
+ InsightsManager.Default.InsertApplicationException(new InsightsApplicationException()
+ {
+ Time = DateTime.UtcNow,
+ Exception = logItem.Message,
+ IsApplicationCrash = true
+ });
+ }
+ catch { }
}
}
@@ -135,6 +147,17 @@ namespace Tango.PPC.UI
try
{
+ InsightsManager.Default.InsertApplicationException(new InsightsApplicationException()
+ {
+ Time = DateTime.UtcNow,
+ Exception = e.Exception.ToString()
+ });
+ }
+ catch
+ { }
+
+ try
+ {
if (Application.Current == null)
{
new Application { ShutdownMode = ShutdownMode.OnExplicitShutdown };
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
index 54193a793..29f4e65be 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
@@ -476,6 +476,7 @@ namespace Tango.PPC.UI.PPCApplication
{
var frame = InsightsFrame.CreateEmpty(DateTime.UtcNow);
InsightsManager.Default.InsertFrame(frame);
+ InsightsManager.Default.Dispose();
}
catch {}
@@ -528,6 +529,7 @@ namespace Tango.PPC.UI.PPCApplication
{
var frame = InsightsFrame.CreateEmpty(DateTime.UtcNow);
InsightsManager.Default.InsertFrame(frame);
+ InsightsManager.Default.Dispose();
}
catch { }
@@ -566,6 +568,7 @@ namespace Tango.PPC.UI.PPCApplication
{
var frame = InsightsFrame.CreateEmpty(DateTime.UtcNow);
InsightsManager.Default.InsertFrame(frame);
+ InsightsManager.Default.Dispose();
}
catch { }
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/RemoteActions/DefaultRemoteActionsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/RemoteActions/DefaultRemoteActionsService.cs
new file mode 100644
index 000000000..1b8780f91
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/RemoteActions/DefaultRemoteActionsService.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core.DI;
+using Tango.Core.Threading;
+using Tango.Integration.ExternalBridge;
+using Tango.PPC.Common.ExternalBridge;
+using Tango.PPC.Common.RemoteActions;
+using Tango.PPC.Common.Threading;
+using Tango.PPC.Shared.RemoteActions;
+
+namespace Tango.PPC.UI.RemoteActions
+{
+ [TangoCreateWhenRegistered]
+ public class DefaultRemoteActionsService : IRemoteActionsService, IExternalBridgeRequestHandler
+ {
+ [TangoInject]
+ private IDispatcherProvider DispatcherProvider { get; set; }
+
+ public DefaultRemoteActionsService(IPPCExternalBridgeService externalBridge)
+ {
+ externalBridge.RegisterRequestHandler(this);
+ }
+
+ public void OnReceiverDisconnected(ExternalBridgeReceiver receiver)
+ {
+ //Do nothing.
+ }
+
+ [ExternalBridgeRequestHandlerMethod(typeof(SimulateApplicationExceptionRequest), RequestHandlerLoggingMode.LogRequestName)]
+ public async Task OnSimulateApplicationExceptionRequest(SimulateApplicationExceptionRequest request, String token, ExternalBridgeReceiver receiver)
+ {
+ await receiver.SendGenericResponse(new SimulateApplicationExceptionResponse(), token);
+
+ Thread.Sleep(500);
+
+ DispatcherProvider.Invoke(() =>
+ {
+ if (request.CrashApplication)
+ {
+ App.ExceptionTrapper.Disable();
+ throw new OutOfMemoryException("This is a simulated exception to cause the application to crash.");
+ }
+ else
+ {
+ throw new ApplicationException("This is a simulated exception to cause an unhandled application error.");
+ }
+ });
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
index 569621432..bfb16f10d 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
@@ -181,6 +181,7 @@
<Compile Include="Notifications\PendingNotification.cs" />
<Compile Include="PPCApplication\DefaultPPCApplicationManager.cs" />
<Compile Include="Printing\DefaultPrintingManager.cs" />
+ <Compile Include="RemoteActions\DefaultRemoteActionsService.cs" />
<Compile Include="Threading\DefaultDispatcherProvider.cs" />
<Compile Include="ViewModelLocator.cs" />
<Compile Include="ViewModels\EmergencyViewVM.cs" />
@@ -446,6 +447,9 @@
<Resource Include="Images\firmware.png" />
<Resource Include="Images\power_off_2.gif" />
<Resource Include="Images\loading_anim.gif" />
+ <Content Include="..\..\Build\ColorLib\Debug\Tango.ColorLib_v4.dll">
+ <Link>Tango.ColorLib_v4.dll</Link>
+ </Content>
<Content Include="Manifests\release.xml" />
<Content Include="Manifests\debug.xml" />
<None Include="firmware_package.tfp">
@@ -717,7 +721,7 @@ if $(ConfigurationName) == Debug copy /Y "$(TargetDir)Packages" "$(TargetDir)"</
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
index b5da9f066..7011cd3be 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
@@ -24,6 +24,7 @@ using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.OS;
using Tango.PPC.Common.Performance;
using Tango.PPC.Common.Printing;
+using Tango.PPC.Common.RemoteActions;
using Tango.PPC.Common.RemoteAssistance;
using Tango.PPC.Common.RemoteDesktop;
using Tango.PPC.Common.RemoteJob;
@@ -42,6 +43,7 @@ using Tango.PPC.UI.Navigation;
using Tango.PPC.UI.Notifications;
using Tango.PPC.UI.PPCApplication;
using Tango.PPC.UI.Printing;
+using Tango.PPC.UI.RemoteActions;
using Tango.PPC.UI.Threading;
using Tango.PPC.UI.ViewModels;
using Tango.PPC.UI.Views;
@@ -94,6 +96,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Unregister<IRemoteJobService>();
TangoIOC.Default.Unregister<IRemoteSqlService>();
TangoIOC.Default.Unregister<IInsightsService>();
+ TangoIOC.Default.Unregister<IRemoteActionsService>();
if (App.StartupArgs != null && App.StartupArgs.Contains("-webDebug"))
{
@@ -135,6 +138,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Register<IRemoteJobService, DefaultRemoteJobService>();
TangoIOC.Default.Register<IRemoteSqlService, DefaultRemoteSqlService>();
TangoIOC.Default.Register<IInsightsService, DefaultInsightsService>();
+ TangoIOC.Default.Register<IRemoteActionsService, DefaultRemoteActionsService>();
TangoIOC.Default.Register<LoadingViewVM>();
TangoIOC.Default.Register<MainViewVM>();
diff --git a/Software/Visual_Studio/Tango.Core/Bson/BsonUtcSerializer.cs b/Software/Visual_Studio/Tango.Core/Bson/BsonUtcSerializer.cs
new file mode 100644
index 000000000..6f5cb7700
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Core/Bson/BsonUtcSerializer.cs
@@ -0,0 +1,68 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Core.Bson
+{
+ public class BsonUtcSerializer : JsonSerializer
+ {
+ private class DateTimeConverter : JsonConverter
+ {
+ public override bool CanConvert(Type objectType)
+ {
+ return typeof(DateTime) == objectType
+ || typeof(DateTime?) == objectType;
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ var dateTimeOffset = (DateTime)value;
+ // Serialize DateTimeOffset as round-trip formatted string
+ serializer.Serialize(writer, dateTimeOffset.ToString("O"));
+ }
+
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Date)
+ return null;
+
+ DateTime dt;
+
+ var dateWithOffset = (String)reader.Value;
+
+ if (String.IsNullOrEmpty(dateWithOffset))
+ return null;
+
+ if (DateTime.TryParseExact(dateWithOffset, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt))
+ return dt;
+
+ return null;
+ }
+
+ }
+
+ private class DateTimeContractResolver : DefaultContractResolver
+ {
+ protected override JsonContract CreateContract(Type objectType)
+ {
+ var contract = base.CreateContract(objectType);
+
+ if (objectType == typeof(DateTime) || objectType == typeof(DateTime?))
+ contract.Converter = new DateTimeConverter();
+
+ return contract;
+ }
+ }
+
+ public BsonUtcSerializer()
+ {
+ ContractResolver = new DateTimeContractResolver();
+ DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj
index 2db9c8643..2ecd441f2 100644
--- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj
+++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj
@@ -95,6 +95,7 @@
<Compile Include="..\Versioning\GlobalVersionInfo.cs">
<Link>GlobalVersionInfo.cs</Link>
</Compile>
+ <Compile Include="Bson\BsonUtcSerializer.cs" />
<Compile Include="Components\CmdCommand.cs" />
<Compile Include="CustomAttributes\PropertyIndexAttribute.cs" />
<Compile Include="CustomAttributes\StringFormatAttribute.cs" />
@@ -216,7 +217,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
<Import Project="..\packages\System.Data.SQLite.Core.1.0.108.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.108.0\build\net46\System.Data.SQLite.Core.targets')" />
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsApplicationException.cs b/Software/Visual_Studio/Tango.Insights/InsightsApplicationException.cs
new file mode 100644
index 000000000..193412ae8
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/InsightsApplicationException.cs
@@ -0,0 +1,20 @@
+using LiteDB;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Insights
+{
+ public class InsightsApplicationException
+ {
+ [BsonId(true)]
+ [JsonIgnore]
+ public int Id { get; set; }
+ public DateTime Time { get; set; }
+ public String Exception { get; set; }
+ public bool IsApplicationCrash { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsFile.cs b/Software/Visual_Studio/Tango.Insights/InsightsFile.cs
index 4eba06035..2bcb2f761 100644
--- a/Software/Visual_Studio/Tango.Insights/InsightsFile.cs
+++ b/Software/Visual_Studio/Tango.Insights/InsightsFile.cs
@@ -6,22 +6,33 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.Core.Bson;
namespace Tango.Insights
{
public class InsightsFile
{
+ private static JsonSerializer _serializer;
+
+ static InsightsFile()
+ {
+ _serializer = new BsonUtcSerializer();
+ }
+
public List<InsightsFrame> Frames { get; set; }
public List<InsightsEvent> Events { get; set; }
public List<InsightsStatus> Statuses { get; set; }
+ public List<InsightsApplicationException> ApplicationExceptions { get; set; }
+
public InsightsFile()
{
Frames = new List<InsightsFrame>();
Events = new List<InsightsEvent>();
Statuses = new List<InsightsStatus>();
+ ApplicationExceptions = new List<InsightsApplicationException>();
}
public Stream ToStream()
@@ -35,8 +46,7 @@ namespace Tango.Insights
{
using (BsonWriter writer = new BsonWriter(ms))
{
- JsonSerializer serializer = new JsonSerializer();
- serializer.Serialize(writer, this);
+ _serializer.Serialize(writer, this);
ms.Position = 0;
return ms.ToArray();
}
@@ -52,8 +62,7 @@ namespace Tango.Insights
{
using (BsonReader reader = new BsonReader(stream))
{
- JsonSerializer serializer = new JsonSerializer();
- return serializer.Deserialize<InsightsFile>(reader);
+ return _serializer.Deserialize<InsightsFile>(reader);
}
}
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsListener.cs b/Software/Visual_Studio/Tango.Insights/InsightsListener.cs
index 6a9e7726b..f57753cfc 100644
--- a/Software/Visual_Studio/Tango.Insights/InsightsListener.cs
+++ b/Software/Visual_Studio/Tango.Insights/InsightsListener.cs
@@ -25,6 +25,7 @@ namespace Tango.Insights
private int _timerCount;
private int _deleteTicks;
private bool _writing;
+ private bool _emptyWritten;
public bool IsStarted { get; private set; }
public TimeSpan SamplingInterval { get; set; }
@@ -164,16 +165,21 @@ namespace Tango.Insights
queue.Clear();
frame = InsightsFrame.FromInsightsMonitors(monitorsAvg, DateTime.UtcNow.Subtract(SamplingInterval));
+ _emptyWritten = false;
+ _manager.InsertFrame(frame);
+ Debug.WriteLine("Insights frame inserted.");
}
else
{
- frame = InsightsFrame.CreateEmpty(DateTime.UtcNow.Subtract(SamplingInterval));
+ if (!_emptyWritten)
+ {
+ frame = InsightsFrame.CreateEmpty(DateTime.UtcNow.Subtract(SamplingInterval));
+ _emptyWritten = true;
+ _manager.InsertFrame(frame);
+ Debug.WriteLine("Insights empty frame inserted.");
+ }
}
- _manager.InsertFrame(frame);
-
- Debug.WriteLine("Insights frame inserted.");
-
_timerCount++;
if (_timerCount >= _deleteTicks)
@@ -185,6 +191,9 @@ namespace Tango.Insights
deleted = _manager.DeleteStatuses(maxDate);
Debug.WriteLine($"{deleted} insights machine statuses deleted.");
+
+ deleted = _manager.DeleteApplicationExceptions(maxDate);
+ Debug.WriteLine($"{deleted} insights application exceptions deleted.");
}
}
catch (Exception ex)
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsManager.cs b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs
index 73b74bff6..b187279b4 100644
--- a/Software/Visual_Studio/Tango.Insights/InsightsManager.cs
+++ b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs
@@ -15,6 +15,9 @@ namespace Tango.Insights
{
private const string INSIGHTS_COLLECTION = "Insights";
private const string STATUSES_COLLECTION = "Statuses";
+ private const string APPLICATION_EXCEPTIONS_COLLECTION = "ApplicationExceptions";
+
+ private bool _disposed;
private static InsightsManager _instance;
public static InsightsManager Default
@@ -39,6 +42,9 @@ namespace Tango.Insights
DatabasePath = databasePath;
Directory.CreateDirectory(Path.GetDirectoryName(DatabasePath));
_database = new LiteDatabase($"Filename={DatabasePath}");
+ _database.Pragma("TIMEOUT", 10); //Read Timeout
+ _database.Pragma("UTC_DATE", true); //Keep time as UTC when getting data
+ _database.Commit();
}
public virtual void Dispose()
@@ -47,6 +53,7 @@ namespace Tango.Insights
{
try
{
+ _disposed = true;
_database.Dispose();
_database = null;
}
@@ -69,18 +76,34 @@ namespace Tango.Insights
return _database.GetCollection<InsightsStatus>(STATUSES_COLLECTION);
}
+ private ILiteCollection<InsightsApplicationException> GetApplicationExceptionsCollection()
+ {
+ return _database.GetCollection<InsightsApplicationException>(APPLICATION_EXCEPTIONS_COLLECTION);
+ }
+
public virtual void InsertFrame(InsightsFrame frame)
{
+ if (_disposed) return;
+
var collection = GetInsightsCollection();
collection.Insert(frame);
}
public virtual void InsertStatus(InsightsStatus status)
{
+ if (_disposed) return;
var collection = GetStatusesCollection();
collection.Insert(status);
}
+ public virtual void InsertApplicationException(InsightsApplicationException appException)
+ {
+ if (_disposed) return;
+ var collection = GetApplicationExceptionsCollection();
+ appException.Time = appException.Time.Subtract(TimeSpan.FromSeconds(30));
+ collection.Insert(appException);
+ }
+
public virtual List<InsightsFrame> GetFrames(DateTime startUTC, DateTime endUTC)
{
var collection = GetInsightsCollection();
@@ -93,20 +116,36 @@ namespace Tango.Insights
return collection.Find(x => x.Time >= startUTC && x.Time <= endUTC).ToList().OrderBy(x => x.Time).ToList();
}
+ public virtual List<InsightsApplicationException> GetApplicationExceptions(DateTime startUTC, DateTime endUTC)
+ {
+ var collection = GetApplicationExceptionsCollection();
+ return collection.Find(x => x.Time >= startUTC && x.Time <= endUTC).ToList().OrderBy(x => x.Time).ToList();
+ }
+
public virtual int DeleteFrames(DateTime maxDateUTC)
{
+ if (_disposed) return 0;
var collection = GetInsightsCollection();
return collection.DeleteMany(x => x.Time < maxDateUTC);
}
public virtual int DeleteStatuses(DateTime maxDateUTC)
{
+ if (_disposed) return 0;
var collection = GetStatusesCollection();
return collection.DeleteMany(x => x.Time < maxDateUTC);
}
+ public virtual int DeleteApplicationExceptions(DateTime maxDateUTC)
+ {
+ if (_disposed) return 0;
+ var collection = GetApplicationExceptionsCollection();
+ return collection.DeleteMany(x => x.Time < maxDateUTC);
+ }
+
public DateTime? GetFramesMinDate()
{
+ if (_disposed) return null;
var collection = GetInsightsCollection();
if (collection.Count() > 0)
@@ -133,9 +172,10 @@ namespace Tango.Insights
Description = x.Description
})
.ToList()
+ .Where(x => (EventTypes)x.EventCode != EventTypes.APPLICATION_EXCEPTION)
.Select(x => new InsightsEvent()
{
- Time = new DateTime(x.Time.Ticks, DateTimeKind.Utc),
+ Time = x.Time,
EventCode = x.EventCode,
Description = ((EventTypes)x.EventCode == EventTypes.JOB_FAILED ? x.Description : null)
})
diff --git a/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj b/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj
index 1e440a62c..ed136a8c6 100644
--- a/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj
+++ b/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj
@@ -44,6 +44,7 @@
<Compile Include="..\Versioning\GlobalVersionInfo.cs">
<Link>GlobalVersionInfo.cs</Link>
</Compile>
+ <Compile Include="InsightsApplicationException.cs" />
<Compile Include="InsightsEvent.cs" />
<Compile Include="InsightsFile.cs" />
<Compile Include="InsightsHelper.cs" />
diff --git a/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs b/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs
index fc791ff4a..3409ffdc4 100644
--- a/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs
+++ b/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs
@@ -21,6 +21,7 @@ namespace Tango.Logging
public class WpfGlobalExceptionTrapper : IGlobalExceptionTrapper
{
private DateTime _lastGlobalExceptionTime = DateTime.Now.AddMinutes(-1);
+ private Application _app;
/// <summary>
/// Occurs when the global exception trapper has detected an unhandled exception.
@@ -33,6 +34,7 @@ namespace Tango.Logging
/// <param name="app">The application.</param>
public void Initialize(Application app)
{
+ _app = app;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
app.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
@@ -40,6 +42,17 @@ namespace Tango.Logging
}
/// <summary>
+ /// Use only when need to simulate application crash!
+ /// </summary>
+ public void Disable()
+ {
+ AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
+ _app.Dispatcher.UnhandledException -= Dispatcher_UnhandledException;
+ Application.Current.DispatcherUnhandledException -= Current_DispatcherUnhandledException;
+ TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException;
+ }
+
+ /// <summary>
/// Handles the UnobservedTaskException event of the TaskScheduler control.
/// </summary>
/// <param name="sender">The source of the event.</param>
diff --git a/Software/Visual_Studio/Tango.Transport/GenericMessageSerializer.cs b/Software/Visual_Studio/Tango.Transport/GenericMessageSerializer.cs
index bb483e19a..6368a7754 100644
--- a/Software/Visual_Studio/Tango.Transport/GenericMessageSerializer.cs
+++ b/Software/Visual_Studio/Tango.Transport/GenericMessageSerializer.cs
@@ -10,6 +10,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.Core.Bson;
using Tango.PMR;
using Tango.PMR.Common;
using Tango.PMR.Integration;
@@ -18,60 +19,11 @@ namespace Tango.Transport
{
public static class GenericMessageSerializer
{
- private class DateTimeConverter : JsonConverter
- {
- public override bool CanConvert(Type objectType)
- {
- return typeof(DateTime) == objectType
- || typeof(DateTime?) == objectType;
- }
-
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
- {
- var dateTimeOffset = (DateTime)value;
- // Serialize DateTimeOffset as round-trip formatted string
- serializer.Serialize(writer, dateTimeOffset.ToString("O"));
- }
-
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
- {
- if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Date)
- return null;
-
- DateTime dt;
-
- var dateWithOffset = (String)reader.Value;
-
- if (String.IsNullOrEmpty(dateWithOffset))
- return null;
-
- if (DateTime.TryParseExact(dateWithOffset, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt))
- return dt;
-
- return null;
- }
-
- }
-
- private class DateTimeContractResolver : DefaultContractResolver
- {
- protected override JsonContract CreateContract(Type objectType)
- {
- var contract = base.CreateContract(objectType);
-
- if (objectType == typeof(DateTime) || objectType == typeof(DateTime?))
- contract.Converter = new DateTimeConverter();
-
- return contract;
- }
- }
-
private static JsonSerializer _serializer;
static GenericMessageSerializer()
{
- _serializer = new JsonSerializer() { ContractResolver = new DateTimeContractResolver() };
- _serializer.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+ _serializer = new BsonUtcSerializer();
ProtoBuf.Meta.RuntimeTypeModel.Default.AutoAddMissingTypes = true;
ProtoBuf.Meta.RuntimeTypeModel.Default.AutoAddProtoContractTypesOnly = false;