diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-02 21:38:19 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2025-08-02 21:38:19 +0300 |
| commit | 0df9f37075dd697ac34f4ed2a2749f62aa27a654 (patch) | |
| tree | 5d95103b41d4954eff9f266317c5a525e9a0e3e9 /Software/Visual_Studio/Utilities | |
| parent | 4222eddece906d6f0877022c06b853deb5068472 (diff) | |
| download | Tango-0df9f37075dd697ac34f4ed2a2749f62aa27a654.tar.gz Tango-0df9f37075dd697ac34f4ed2a2749f62aa27a654.zip | |
Telemetry Testing.
Diffstat (limited to 'Software/Visual_Studio/Utilities')
18 files changed, 1093 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config new file mode 100644 index 000000000..959eb4686 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/App.config @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> + </startup> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration>
\ No newline at end of file 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 new file mode 100644 index 000000000..cb8a79288 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Program.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Enumerations; +using Tango.Telemetry.Destinations; +using Tango.Telemetry.Sources; + +namespace Tango.Telemetry.Tester.IOT.CLI +{ + class Program + { + static void Main(string[] args) + { + TelemetryPublisher publisher = new TelemetryPublisher(new TelemetryPublisherConfiguration() + { + Environment = "DEV", + SerialNumber = "dev-machine", + MachineType = MachineTypes.TS1800, + HistorySourcesRequestInterval = TimeSpan.FromSeconds(1), + EnableBackoff = false, + + }, null); + + (publisher.StorageManager as TelemetryLiteDBStorageManager).EnableCheckPointsRecovery = false; + + publisher.RegisterSource(new JobRunsTestSource()); + 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.Start().GetAwaiter().GetResult(); + + Console.Clear(); + Console.WriteLine("=== Telemetry IoT Hub Test Utility ==="); + Console.WriteLine($"Publisher started. Streaming every {publisher.Config.HistorySourcesRequestInterval.TotalSeconds} seconds."); + Console.WriteLine("Press any key to stop streaming data..."); + + Console.ReadKey(); + + Console.WriteLine("Disposing publisher..."); + publisher.Dispose(); + } + + private static void Publisher_PublishResultAvailable(object sender, TelemetryPublishResultAvailableEventArgs e) + { + Console.ForegroundColor = ConsoleColor.DarkGray; + Console.WriteLine($"Package publish result available:\n{e.PublishResult.ToString()}"); + + if (e.PublishResult.DestinationsResults.Any(d => d.Status == TelemetryPublishResult.DestinationStatus.Failed)) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("One or more destinations failed to receive the package."); + } + else + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("Package successfully published."); + } + Console.ResetColor(); + + Console.WriteLine("Press any key to stop streaming data..."); + } + } + + [TelemetryName("JobRun")] + public class JobRunTestTelemetry : TelemetryBase + { + public String JobName { get; set; } + public String Thread { get; set; } + public double Length { get; set; } + } + + public class JobRunsTestSource : ITelemetryHistorySource + { + private int counter = 1; + + public string Name { get; } = "Persons Source"; + public bool RequiresTelemetryDuplicationTracking { get; } = false; + + public Task<bool> CanRequestHistory(DateTime from) + { + return Task.FromResult(true); + } + + public void Dispose() + { + + } + + public Task<IEnumerable<ITelemetry>> RequestHistory(DateTime from) + { + return Task. + FromResult<IEnumerable<ITelemetry>>(new List<JobRunTestTelemetry>() + { + new JobRunTestTelemetry() + { + Time = DateTime.UtcNow, + JobName = $"Job For Materialized {counter++}", + Length = 1000 + counter, + Thread = $"Coats Thread {counter}" + } + }); + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..dc1b052d1 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tango.Telemetry.Tester.IOT.CLI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.Telemetry.Tester.IOT.CLI")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c891b2f7-e63a-40e2-b6ce-a22a69b4d86a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj new file mode 100644 index 000000000..0449a67fe --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/Tango.Telemetry.Tester.IOT.CLI.csproj @@ -0,0 +1,202 @@ +<?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>{C891B2F7-E63A-40E2-B6CE-A22A69B4D86A}</ProjectGuid> + <OutputType>Exe</OutputType> + <RootNamespace>Tango.Telemetry.Tester.IOT.CLI</RootNamespace> + <AssemblyName>Tango.Telemetry.Tester.IOT.CLI</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <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' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="DotNetty.Buffers, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Buffers.0.4.6\lib\net45\DotNetty.Buffers.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Codecs, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Codecs.0.4.6\lib\net45\DotNetty.Codecs.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Codecs.Mqtt, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Codecs.Mqtt.0.4.6\lib\net45\DotNetty.Codecs.Mqtt.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Common, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Common.0.4.6\lib\net45\DotNetty.Common.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Handlers, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Handlers.0.4.6\lib\net45\DotNetty.Handlers.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Transport, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Transport.0.4.6\lib\net45\DotNetty.Transport.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.Amqp, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.Amqp.2.0.6\lib\net45\Microsoft.Azure.Amqp.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.Devices.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.Devices.Client.1.6.0\lib\net45\Microsoft.Azure.Devices.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.Devices.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.Devices.Shared.1.3.0\lib\net45\Microsoft.Azure.Devices.Shared.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.KeyVault.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Data.Edm, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.Edm.5.6.4\lib\net40\Microsoft.Data.Edm.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Data.OData, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.OData.5.6.4\lib\net40\Microsoft.Data.OData.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Data.Services.Client, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.Services.Client.5.6.4\lib\net40\Microsoft.Data.Services.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Extensions.Logging, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Extensions.Logging.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath> + </Reference> + <Reference Include="Microsoft.WindowsAzure.Storage, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PCLCrypto.2.0.147\lib\net45\PCLCrypto.dll</HintPath> + </Reference> + <Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.BCrypt.0.3.2\lib\net40\PInvoke.BCrypt.dll</HintPath> + </Reference> + <Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.Kernel32.0.3.2\lib\net40\PInvoke.Kernel32.dll</HintPath> + </Reference> + <Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.NCrypt.0.3.2\lib\net40\PInvoke.NCrypt.dll</HintPath> + </Reference> + <Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath> + </Reference> + <Reference Include="System.ComponentModel.Composition" /> + <Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> + </Reference> + <Reference Include="System.Core" /> + <Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath> + </Reference> + <Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath> + </Reference> + <Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath> + </Reference> + <Reference Include="System.IO.Compression.FileSystem" /> + <Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath> + </Reference> + <Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath> + </Reference> + <Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath> + </Reference> + <Reference Include="System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll</HintPath> + </Reference> + <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath> + </Reference> + <Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath> + </Reference> + <Reference Include="System.Numerics" /> + <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> + </Reference> + <Reference Include="System.Spatial, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Spatial.5.6.4\lib\net40\System.Spatial.dll</HintPath> + </Reference> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath> + </Reference> + <Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Tango.BL\Tango.BL.csproj"> + <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> + <Name>Tango.BL</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Telemetry\Tango.Telemetry.csproj"> + <Project>{af593663-d4e9-4a14-a3f2-fea57f30e9e6}</Project> + <Name>Tango.Telemetry</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config new file mode 100644 index 000000000..8dabdb1c2 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.Telemetry.Tester.IOT.CLI/packages.config @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="DotNetty.Buffers" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Codecs" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Codecs.Mqtt" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Common" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Handlers" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Transport" version="0.4.6" targetFramework="net461" /> + <package id="EnterpriseLibrary.TransientFaultHandling" version="6.0.1304.0" targetFramework="net461" /> + <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" /> + <package id="Microsoft.Azure.Amqp" version="2.0.6" targetFramework="net461" /> + <package id="Microsoft.Azure.Devices.Client" version="1.6.0" targetFramework="net461" /> + <package id="Microsoft.Azure.Devices.Shared" version="1.3.0" targetFramework="net461" /> + <package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net461" /> + <package id="Microsoft.Data.Edm" version="5.6.4" targetFramework="net461" /> + <package id="Microsoft.Data.OData" version="5.6.4" targetFramework="net461" /> + <package id="Microsoft.Data.Services.Client" version="5.6.4" targetFramework="net461" /> + <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.0" targetFramework="net461" /> + <package id="Microsoft.Extensions.Logging" version="1.1.1" targetFramework="net461" /> + <package id="Microsoft.Extensions.Logging.Abstractions" version="1.1.1" targetFramework="net461" /> + <package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net461" /> + <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="NETStandard.Library" version="1.6.1" targetFramework="net461" /> + <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" /> + <package id="PCLCrypto" version="2.0.147" targetFramework="net461" /> + <package id="PInvoke.BCrypt" version="0.3.2" targetFramework="net461" /> + <package id="PInvoke.Kernel32" version="0.3.2" targetFramework="net461" /> + <package id="PInvoke.NCrypt" version="0.3.2" targetFramework="net461" /> + <package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="net461" /> + <package id="System.AppContext" version="4.3.0" targetFramework="net461" /> + <package id="System.Collections" version="4.3.0" targetFramework="net461" /> + <package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net461" /> + <package id="System.ComponentModel" version="4.3.0" targetFramework="net461" /> + <package id="System.Console" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.DiagnosticSource" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net461" /> + <package id="System.Globalization" version="4.3.0" targetFramework="net461" /> + <package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net461" /> + <package id="System.IO" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.Compression" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Linq" version="4.3.0" targetFramework="net461" /> + <package id="System.Linq.Expressions" version="4.3.0" targetFramework="net461" /> + <package id="System.Net.Http" version="4.3.0" targetFramework="net461" /> + <package id="System.Net.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Net.Sockets" version="4.3.0" targetFramework="net461" /> + <package id="System.ObjectModel" version="4.3.0" targetFramework="net461" /> + <package id="System.Reflection" version="4.3.0" targetFramework="net461" /> + <package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net461" /> + <package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.Handles" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net461" /> + <package id="System.Spatial" version="5.6.4" targetFramework="net461" /> + <package id="System.Text.Encoding" version="4.3.0" targetFramework="net461" /> + <package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net461" /> + <package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net461" /> + <package id="System.Threading" version="4.3.0" targetFramework="net461" /> + <package id="System.Threading.Tasks" version="4.3.0" targetFramework="net461" /> + <package id="System.Threading.Timer" version="4.3.0" targetFramework="net461" /> + <package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net461" /> + <package id="System.Xml.XDocument" version="4.3.0" targetFramework="net461" /> + <package id="Validation" version="2.2.8" targetFramework="net461" /> + <package id="WindowsAzure.Storage" version="7.0.0" targetFramework="net461" /> +</packages>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/App.config b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/App.config new file mode 100644 index 000000000..c248eaa70 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/App.config @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> + </startup> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Azure.Amqp" publicKeyToken="31bf3856ad364e35" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.WindowsAzure.Storage" publicKeyToken="31bf3856ad364e35" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-8.7.0.0" newVersion="8.7.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="DotNetty.Transport" publicKeyToken="bc13ca065fa06c29" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="DotNetty.Buffers" publicKeyToken="bc13ca065fa06c29" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="DotNetty.Codecs.Mqtt" publicKeyToken="bc13ca065fa06c29" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="DotNetty.Common" publicKeyToken="bc13ca065fa06c29" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="DotNetty.Handlers" publicKeyToken="bc13ca065fa06c29" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-0.6.0.0" newVersion="0.6.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/DatabaseHelper.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/DatabaseHelper.cs new file mode 100644 index 000000000..60791a5d8 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/DatabaseHelper.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TelemetryTester.CLI +{ + public class DatabaseHelper + { + public static void ClearTelemetryDatabase() + { + string appName = AppDomain.CurrentDomain.FriendlyName.Replace(".exe", ""); + string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Telemetry"); + string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Telemetry", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName) + ".telemetry"); + string logFile = Path.Combine(path, appName + "-log.telemetry"); + string backup = file + ".bak"; + + try + { + if (File.Exists(file)) File.Delete(file); + if (File.Exists(backup)) File.Delete(backup); + if (File.Exists(logFile)) File.Delete(logFile); + Logger.LogWarning("Cleaned telemetry database for fresh test run."); + } + catch (Exception ex) + { + Logger.LogError($"Failed to clear telemetry database: {ex.Message}"); + } + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Logger.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Logger.cs new file mode 100644 index 000000000..8490ccfc6 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Logger.cs @@ -0,0 +1,49 @@ +using System; + +namespace Tango.TelemetryTester.CLI +{ + public static class Logger + { + public static void LogInfo(String message) + { + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(message); + } + + public static void LogWarning(String message) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(message); + } + + public static void LogError(String message) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(message); + } + + public static void LogSuccess(String message) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(message); + } + + public static void LogVerbose(String message) + { + Console.ForegroundColor = ConsoleColor.Gray; + Console.WriteLine(message); + } + + public static void LogVerboseByLogManager(String message) + { + Console.ForegroundColor = ConsoleColor.DarkGray; + Console.WriteLine(message); + } + + public static void LogTitle(string title) + { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine($"\n===== {title} ====="); + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockCheckpointsRecoveryClient.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockCheckpointsRecoveryClient.cs new file mode 100644 index 000000000..82b7d739f --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockCheckpointsRecoveryClient.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Tango.Telemetry; + +namespace Tango.TelemetryTester.CLI +{ + public class MockCheckpointsRecoveryClient : ITelemetryCheckpointsRecoveryClient + { + public Task<List<TelemetryHistorySourceCheckPoint>> GetCheckpointsBackup() => Task.FromResult(new List<TelemetryHistorySourceCheckPoint>()); + public Task SaveCheckpointsBackup(List<TelemetryHistorySourceCheckPoint> checkPoints) => Task.CompletedTask; + public void Dispose() { } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockDestinationWithFailure.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockDestinationWithFailure.cs new file mode 100644 index 000000000..400dbf3ef --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockDestinationWithFailure.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Tango.Telemetry; + +namespace Tango.TelemetryTester.CLI +{ + public class MockDestinationWithFailure : ITelemetryDestination + { + public string Name { get; set; } + public List<string> ReceivedPayloads { get; } = new List<string>(); + public int FailCountRemaining { get; private set; } + public int TotalAttempts { get; private set; } = 0; + + public MockDestinationWithFailure(string name, int failCount) + { + Name = name; + FailCountRemaining = failCount; + } + + public IReadOnlyList<TelemetrySourceTypes> SupportedSourceTypes => new[] + { + TelemetrySourceTypes.Streaming, + TelemetrySourceTypes.ExternalStorage, + TelemetrySourceTypes.PendingStorage + }; + + public Task<bool> IsAvailable() => Task.FromResult(true); + + public Task Publish(TelemetryPublishPackage package, List<KeyValuePair<string, string>> properties) + { + TotalAttempts++; + if (FailCountRemaining-- > 0) + { + throw new Exception("Simulated publish failure"); + } + + var payload = package.ToPayload(); + ReceivedPayloads.Add(payload); + Logger.LogInfo($"Destination '{Name}' received payload: {payload}"); + return Task.CompletedTask; + } + + public void Dispose() { } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockHistorySource.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockHistorySource.cs new file mode 100644 index 000000000..6ecd7e637 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockHistorySource.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Tango.Telemetry; + +namespace Tango.TelemetryTester.CLI +{ + public class MockHistorySource : ITelemetryHistorySource + { + public string Name { get; } + + public int ProvidedCount { get; set; } + + public MockHistorySource(string name) + { + Name = name; + } + + public Task<bool> CanRequestHistory(DateTime from) => Task.FromResult(true); + + public Task<IEnumerable<ITelemetry>> RequestHistory(DateTime from) + { + Logger.LogInfo($"[HistorySource] Providing historical telemetry at {DateTime.UtcNow}"); + + ProvidedCount++; + + return Task.FromResult<IEnumerable<ITelemetry>>(new[] + { + new MockTelemetry { Time = DateTime.UtcNow.AddSeconds(-30) } + }); + } + + public void Dispose() { } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockStreamingSource.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockStreamingSource.cs new file mode 100644 index 000000000..0ca058ec9 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockStreamingSource.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading; +using Tango.Telemetry; + +namespace Tango.TelemetryTester.CLI +{ + public class MockStreamingSource : ITelemetryStreamingSource + { + public string Name { get; } + public event EventHandler<TelemetryAvailableEventArgs> TelemetryAvailable; + private Timer _timer; + public int EmittedCount { get; private set; } + private bool _isStarted = false; + + public MockStreamingSource(string name) + { + Name = name; + } + + public void Start() + { + if (_isStarted) return; + _isStarted = true; + _timer = new Timer(SendTelemetry, null, 500, 1000); + } + + public void Stop() + { + if (!_isStarted) return; + _timer?.Dispose(); + _timer = null; + _isStarted = false; + } + + private void SendTelemetry(object state) + { + var telemetry = new MockTelemetry { Time = DateTime.UtcNow }; + EmittedCount++; + Logger.LogVerbose($"Emitting telemetry #{EmittedCount} from {Name}"); + TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs(telemetry, TelemetrySourceTypes.Streaming)); + } + + public void Dispose() => Stop(); + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockTelemetry.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockTelemetry.cs new file mode 100644 index 000000000..fb96e5819 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/MockTelemetry.cs @@ -0,0 +1,21 @@ +using System; +using System.Text; +using Tango.Telemetry; + +namespace Tango.TelemetryTester.CLI +{ + public class MockTelemetry : ITelemetry + { + public DateTime Time { get; set; } + + public string ToJson(Newtonsoft.Json.Formatting format = Newtonsoft.Json.Formatting.None, bool flatten = true) + { + return $"{{\"time\": \"{Time:o}\"}}"; + } + + public byte[] ToBytes(Newtonsoft.Json.Formatting format = Newtonsoft.Json.Formatting.None, bool flatten = true) + { + return Encoding.UTF8.GetBytes(ToJson(format, flatten)); + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Program.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Program.cs new file mode 100644 index 000000000..1b985e35b --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Program.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Tango.BL.Enumerations; +using Tango.Logging; +using Tango.Telemetry; + +namespace Tango.TelemetryTester.CLI +{ + class Program + { + static void Main(string[] args) + { + Run().GetAwaiter().GetResult(); + } + + static async Task Run() + { + Logger.LogTitle("Telemetry Pipeline Test Starting..."); + DatabaseHelper.ClearTelemetryDatabase(); + + LogManager.Default.NewLog += (x, log) => + { + switch (log.Category) + { + case LogCategory.Info: + case LogCategory.Debug: + Logger.LogVerboseByLogManager(log.Message); + break; + case LogCategory.Warning: + Logger.LogWarning(log.Message); + break; + case LogCategory.Error: + case LogCategory.Critical: + Logger.LogError(log.Message); + break; + } + }; + + var config = new TelemetryPublisherConfiguration + { + SerialNumber = "TEST-MACHINE", + MachineType = MachineTypes.TS1800, + Environment = "DEV", + PendingStorageCheckInterval = TimeSpan.FromSeconds(5), + HistorySourcesRequestInterval = TimeSpan.FromSeconds(5) + }; + + var recoveryClient = new MockCheckpointsRecoveryClient(); + var publisher = new TelemetryPublisher(config, recoveryClient); + + var mockStreamingSource = new MockStreamingSource("MockStreamingSource1"); + var mockHistorySource = new MockHistorySource("MockHistorySource1"); + var destination1 = new MockDestinationWithFailure("MockDestination", failCount: 2); + var destination2 = new MockDestinationWithFailure("FastDestination", failCount: 0); + var destination3 = new MockDestinationWithFailure("HistoryOnlyDestination", failCount: 0); + + publisher.RegisterSource(mockStreamingSource); + publisher.RegisterSource(mockHistorySource); + publisher.RegisterDestination(destination1); + publisher.RegisterDestination(destination2); + publisher.RegisterDestination(destination3); + + var results = new List<string>(); + var publishCount = 0; + var failureCount = 0; + + publisher.PackagePublished += (s, e) => + { + publishCount++; + var msg = $"SUCCESS: published telemetry to {e.Destination.Name}"; + results.Add(msg); + Logger.LogSuccess(msg); + }; + + publisher.PublishPackageFailed += (s, e) => + { + failureCount++; + var msg = $"FAILURE: failed to publish telemetry to {e.Destination.Name} - {e.Exception.Message}"; + results.Add(msg); + Logger.LogError(msg); + }; + + await publisher.Start(); + await Task.Delay(7000); + await publisher.Stop(); + + int pendingCount = publisher.StorageManager.GetPendingTelemetriesCount(); + + Logger.LogTitle("TEST REPORT"); + Logger.LogInfo($"Total telemetry generated by streaming source: {mockStreamingSource.EmittedCount}"); + Logger.LogInfo($"Total telemetry generated by history source: {mockHistorySource.ProvidedCount}"); + Logger.LogInfo($"Total failures (intentional): {failureCount}"); + Logger.LogInfo($"Total payloads received by MockDestination: {destination1.ReceivedPayloads.Count}"); + Logger.LogInfo($"Total payloads received by FastDestination: {destination2.ReceivedPayloads.Count}"); + Logger.LogInfo($"Total payloads received by HistoryOnlyDestination: {destination3.ReceivedPayloads.Count}"); + Logger.LogInfo($"Total telemetries published: {publishCount}"); + + int totalExpectedPublishes = (mockStreamingSource.EmittedCount + mockHistorySource.ProvidedCount) * 3; + bool allEmittedPublished = publishCount == totalExpectedPublishes; + bool allPublishedReceived = publishCount == destination1.ReceivedPayloads.Count + destination2.ReceivedPayloads.Count + destination3.ReceivedPayloads.Count; + bool retriesOccurred = destination1.TotalAttempts > destination1.ReceivedPayloads.Count; + bool noPendingLeft = pendingCount == 0; + + Logger.LogTitle("TEST VERDICT"); + Logger.LogInfo(allEmittedPublished ? "PASS: Emitted telemetry all published" : "FAIL: Emitted telemetry not fully published"); + Logger.LogInfo(allPublishedReceived ? "PASS: All published telemetry received by destinations" : "FAIL: Some published telemetry was not received"); + Logger.LogInfo(retriesOccurred ? "PASS: Retry logic triggered and succeeded" : "FAIL: Retry logic did not activate as expected"); + Logger.LogInfo(noPendingLeft ? "PASS: Pending storage clean after test" : $"FAIL: {pendingCount} telemetry still pending in storage"); + + Logger.LogTitle("DETAILED EVENTS"); + foreach (var line in results) + Logger.LogInfo(line); + + Logger.LogSuccess("\nTest complete."); + Console.ReadKey(); + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e4666e75a --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tango.TelemetryTester.CLI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.TelemetryTester.CLI")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("db3a1470-994b-46df-9be8-f905cdb97a3a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Tango.TelemetryTester.CLI.csproj b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Tango.TelemetryTester.CLI.csproj new file mode 100644 index 000000000..cc4ba9298 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Tango.TelemetryTester.CLI.csproj @@ -0,0 +1,83 @@ +<?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>{DB3A1470-994B-46DF-9BE8-F905CDB97A3A}</ProjectGuid> + <OutputType>Exe</OutputType> + <RootNamespace>Tango.TelemetryTester.CLI</RootNamespace> + <AssemblyName>Tango.TelemetryTester.CLI</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <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' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <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="DatabaseHelper.cs" /> + <Compile Include="Logger.cs" /> + <Compile Include="MockCheckpointsRecoveryClient.cs" /> + <Compile Include="MockDestinationWithFailure.cs" /> + <Compile Include="MockHistorySource.cs" /> + <Compile Include="MockStreamingSource.cs" /> + <Compile Include="MockTelemetry.cs" /> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + <None Include="packages.config" /> + <None Include="Verifications List.md" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Tango.BL\Tango.BL.csproj"> + <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> + <Name>Tango.BL</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Logging\Tango.Logging.csproj"> + <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project> + <Name>Tango.Logging</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Telemetry\Tango.Telemetry.csproj"> + <Project>{af593663-d4e9-4a14-a3f2-fea57f30e9e6}</Project> + <Name>Tango.Telemetry</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Verifications List.md b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Verifications List.md new file mode 100644 index 000000000..90362d659 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/Verifications List.md @@ -0,0 +1,90 @@ +### ✅ **Basic Functional Verifications** + +1. **Source Trigger Verification** + + * Log a message every time `MockStreamingSource` generates a telemetry. + * Count how many times `TelemetryAvailable` was raised vs. published. + +2. **Destination Receipt Check** + + * Confirm each destination receives telemetry that matches the `ToPayload()` value. + * Add internal counters per destination to confirm delivery. + +3. **Package Identity Tracking** + + * Assign a unique ID to each telemetry object and verify that: + + * It travels all the way to the destination. + * It is not duplicated or lost. + +--- + +### 🔁 **Retry and Backoff Testing** + +4. **Destination Retry Logic** + + * Simulate a failure in `MockDestination.Publish()` every Nth call. + * Verify that retries are scheduled with exponential backoff. + +5. **Pending Storage Write/Read** + + * Cause all destinations to fail. + * Confirm that telemetry is persisted to `TelemetryLiteDBStorageManager`. + * Manually inspect `PendingTelemetries.Count` after the run. + +--- + +### 🕒 **Time & Latency Metrics** + +6. **Elapsed Time Per Publish** + + * Log how long it takes from package creation to successful publish. + +7. **Latency Bucketing** + + * Track telemetry latency buckets (e.g., `<1s`, `1–5s`, `>5s`) and print histogram. + +--- + +### 📦 **Historical and Pending Telemetry** + +8. **History Source Verification** + + * Confirm `MockHistorySource.RequestHistory()` is triggered periodically. + * Verify telemetry from it is published and updated in checkpoints. + +9. **Checkpoint Verification** + + * Track when and how often checkpoints are updated. + * Ensure they persist across runs using `TelemetryLiteDBStorageManager`. + +--- + +### 🛠️ **Fault Injection and Resilience** + +10. **Out-of-Order Timestamps** + + * Send telemetry with past/future timestamps and check ordering in publish results. + +11. **Multiple Concurrent Sources** + + * Add 2–3 `MockStreamingSource` instances and confirm the system handles interleaved input. + +12. **Slow Publisher Simulation** + + * Simulate slow or blocking destination publish methods. + * Confirm queue doesn’t overflow and telemetry is not lost. + +--- + +### 🧪 **Extended Diagnostic Reporting** + +13. **Final Report Enhancements** + + * Total telemetry generated, published, failed, retried, and persisted. + * Telemetry per source/destination. + * Count of `TelemetryAvailable` vs `Publish()`. + +--- + +Would you like to start with a few of these now? I can help you implement fault injection, persistence inspection, or anything else you choose. diff --git a/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/packages.config b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/packages.config new file mode 100644 index 000000000..7ee8c1052 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.TelemetryTester.CLI/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" /> +</packages>
\ No newline at end of file |
