diff --git a/.gitignore b/.gitignore index 42436d015..60e3cbb85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +# Rider +.idea + # Private files OSExtentions.cs diff --git a/src/LinuxEvent.Tests/Properties/AssemblyInfo.cs b/src/LinuxEvent.Tests/Properties/AssemblyInfo.cs index b2dcb2535..064fc9bf8 100644 --- a/src/LinuxEvent.Tests/Properties/AssemblyInfo.cs +++ b/src/LinuxEvent.Tests/Properties/AssemblyInfo.cs @@ -1,9 +1,12 @@ using System.Runtime.InteropServices; +using Xunit; -// 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 +// 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("c42873f2-d4a5-4ac7-9adb-9cd8e1856a9b")] + +[assembly: CollectionBehavior(DisableTestParallelization = true)] diff --git a/src/PerfView/PerfViewData.cs b/src/PerfView/PerfViewData.cs index 5fe45b56e..37d16d61b 100644 --- a/src/PerfView/PerfViewData.cs +++ b/src/PerfView/PerfViewData.cs @@ -8788,19 +8788,45 @@ public TraceLog GetTraceLog(TextWriter log) log.WriteLine("Creating ETLX file {0} from {1}", etlxFile, dataFileName); try { - TraceLog.CreateFromLttngTextDataFile(dataFileName, etlxFile, options); - } - catch (Exception e) // Throws this if there is no CTF Information - { - if (e is EndOfStreamException) - { - log.WriteLine("Warning: Trying to open CTF stream failed, no CTF (lttng) information"); - } - else + // linux files could contain CLR events collected either via LTTng or dotnet-trace + using (var zip = ZipFile.Open(dataFileName, ZipArchiveMode.Read)) { - log.WriteLine("Error: Exception CTF conversion: {0}", e.ToString()); - log.WriteLine("[Error: exception while opening CTF (lttng) data.]"); + var nettraceFile = zip.Entries.FirstOrDefault(e => e.Name.EndsWith(".nettrace")); + if (nettraceFile != null) + { + // look for dotnet-trace recording + var nettraceFilePath = etlxFile + ".nettrace"; + nettraceFile.ExtractToFile(nettraceFilePath); + TraceLog.CreateFromEventPipeDataFile(nettraceFilePath, etlxFile, options); + File.Delete(nettraceFilePath); + } + else + { + // look for LTTng recording + try + { + TraceLog.CreateFromLttngTextDataFile(dataFileName, etlxFile, options); + } + catch (Exception e) // Throws this if there is no CTF Information + { + if (e is EndOfStreamException) + { + log.WriteLine("Warning: Trying to open CTF stream failed, no CTF (lttng) information"); + } + else + { + log.WriteLine("Error: Exception CTF conversion: {0}", e.ToString()); + log.WriteLine("[Error: exception while opening CTF (lttng) data.]"); + } + + throw; + } + } } + } + catch (Exception e) + { + log.WriteLine("Error: Exception while opening linux file '{0}'\r\n {1}", e.ToString(), dataFileName); Debug.Assert(m_traceLog == null); m_noTraceLogInfo = true; diff --git a/src/TraceEvent/Ctf/CtfTracing.Tests/Properties/AssemblyInfo.cs b/src/TraceEvent/Ctf/CtfTracing.Tests/Properties/AssemblyInfo.cs index c4e1929c0..c958fb342 100644 --- a/src/TraceEvent/Ctf/CtfTracing.Tests/Properties/AssemblyInfo.cs +++ b/src/TraceEvent/Ctf/CtfTracing.Tests/Properties/AssemblyInfo.cs @@ -1,9 +1,12 @@ using System.Runtime.InteropServices; +using Xunit; -// 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 +// 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("e89fd36b-c900-4281-b549-3ce0bd580c78")] + +[assembly: CollectionBehavior(DisableTestParallelization = true)] diff --git a/src/TraceEvent/TraceEvent.Tests/Platform/EtlTestBase.cs b/src/TraceEvent/TraceEvent.Tests/Platform/EtlTestBase.cs index 2a42b59de..ae62f30b5 100644 --- a/src/TraceEvent/TraceEvent.Tests/Platform/EtlTestBase.cs +++ b/src/TraceEvent/TraceEvent.Tests/Platform/EtlTestBase.cs @@ -70,6 +70,11 @@ private static void UnzipDataFiles() var dir = Path.Combine(UnZippedDataDir, Path.GetFileNameWithoutExtension(folderZip)); if (!Directory.Exists(dir) || Directory.GetLastWriteTimeUtc(dir) < File.GetLastWriteTimeUtc(folderZip)) { + if (Directory.Exists(dir)) + { + Directory.Delete(dir, true); + } + zipFile.ExtractToDirectory(UnZippedDataDir); } else @@ -90,7 +95,7 @@ protected void PrepareTestData() Assert.True(Directory.Exists(OriginalBaselineDir)); OriginalBaselineDir = Path.GetFullPath(OriginalBaselineDir); - // This is all atomic because this method is synchronized. + // This is all atomic because this method is synchronized. Assert.True(Directory.Exists(TestDataDir)); UnzipDataFiles(); if (Directory.Exists(OutputDir)) diff --git a/src/TraceEvent/TraceEvent.Tests/Properties/AssemblyInfo.cs b/src/TraceEvent/TraceEvent.Tests/Properties/AssemblyInfo.cs index 722133d72..d9923a726 100644 --- a/src/TraceEvent/TraceEvent.Tests/Properties/AssemblyInfo.cs +++ b/src/TraceEvent/TraceEvent.Tests/Properties/AssemblyInfo.cs @@ -1,9 +1,12 @@ using System.Runtime.InteropServices; +using Xunit; -// 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 +// 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("19281902-fbc4-48c0-962b-9fdadaf5c783")] + +[assembly: CollectionBehavior(DisableTestParallelization = true)] diff --git a/src/perfcollect/perfcollect b/src/perfcollect/perfcollect index dfd614b6e..5aed454bb 100755 --- a/src/perfcollect/perfcollect +++ b/src/perfcollect/perfcollect @@ -643,6 +643,10 @@ usePerf=1 # Use LTTng useLTTng=1 +# Use dotnet-trace tool to collect CLR events +useDotnetTrace=0 +sdkAndToolDir="/tmp/perfcollect-dotnet-sdk" + # LTTng Installed lttngInstalled=0 @@ -738,6 +742,11 @@ InitializeLog() then LogAppend 'LTTng version: ' `$lttngcmd --version` fi + + if [ "$dotnettracecmd" != "" ] + then + LogAppend 'dotnet-trace version:' $(eval $dotnettracecmd --version) + fi LogAppend } @@ -928,6 +937,19 @@ DiscoverCommands() fi fi + if [ "$(IsSdkInstalledGlobally)" == 0 ] + then + dotnettracecmd="dotnet trace" + else + dotnettracecmd="DOTNET_ROOT=\"$sdkAndToolDir\" $sdkAndToolDir/dotnet-trace" + fi + + eval "$dotnettracecmd --version" > /dev/null 2>&1 + if [ "$?" != "0" ] + then + FatalError "Unable to find dotnet-trace tool. Try re-installing via ./perfcollect install." + fi + lttngcmd=`GetCommandFullPath "lttng"` zipcmd=`GetCommandFullPath "zip"` unzipcmd=`GetCommandFullPath "unzip"` @@ -962,8 +984,8 @@ InstallPerf_Alpine() # Install perf apk add perf --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community - # Install zip and unzip - apk add zip unzip + # Install zip, unzip and curl + apk add zip unzip curl } IsRHEL() @@ -982,8 +1004,8 @@ InstallPerf_RHEL() # Disallow non-root users. EnsureRoot - # Install perf - yum install perf zip unzip + # Install perf, zip, unzip and curl + yum install perf zip unzip curl } IsDebian() @@ -1019,8 +1041,8 @@ InstallPerf_Debian() fi fi - # Install zip and perf. - apt-get install -y zip binutils $pkgName + # Install zip, curl and perf. + apt-get install -y zip curl binutils $pkgName } IsSUSE() @@ -1039,8 +1061,8 @@ InstallPerf_SUSE() # Disallow non-root users. EnsureRoot - # Install perf. - zypper install perf zip unzip + # Install perf, zip unzip and curl + zypper install perf zip unzip curl } IsUbuntu() @@ -1072,9 +1094,9 @@ InstallPerf_Ubuntu() release=`uname -r` if [[ "$release" == *"-azure" ]] then - apt-get install -y linux-tools-azure zip software-properties-common + apt-get install -y linux-tools-azure zip curl software-properties-common else - apt-get install -y linux-tools-common linux-tools-`uname -r` linux-cloud-tools-`uname -r` zip software-properties-common + apt-get install -y linux-tools-common linux-tools-generic zip curl software-properties-common fi } @@ -1238,6 +1260,57 @@ InstallLTTng() fi } +IsSdkInstalledGlobally() +{ + installed=1 + dotnet tool list > /dev/null 2>&1 + if [ "$?" == "0" ] + then + installed=0 + fi + echo $installed +} + +InstallSdkAndDotNetTraceLocally() +{ + # install SDK, if needed + if [ ! -d "$sdkAndToolDir" ] || [ ! -f "$sdkAndToolDir/dotnet" ] + then + WriteStatus "Installing dotnet sdk in $sdkAndToolDir" + ResetText + RunSilent "mkdir $sdkAndToolDir" + RunSilent "cd $sdkAndToolDir" + RunSilent "curl -OL https://dot.net/v1/dotnet-install.sh" + RunSilent "bash ./dotnet-install.sh --install-dir ." + fi + + # install dotnet-trace, if needed + if [ ! -f "$sdkAndToolDir/dotnet-trace" ] + then + WriteStatus "Installing dotnet trace" + RunSilent "$sdkAndToolDir/dotnet tool install dotnet-trace --tool-path $sdkAndToolDir" + fi + + # Check if it works + DOTNET_ROOT="$sdkAndToolDir" $sdkAndToolDir/dotnet-trace --version > /dev/null 2>&1 + if [ "$?" != "0" ] + then + FatalError "dotnet-trace tool was not installed correctly. Delete $sdkAndToolDir and re-install via ./perfcollect install." + fi +} + +InstallDotNetTraceTool() +{ + if [ "$(IsSdkInstalledGlobally)" == 0 ] + then + WriteStatus "Installing dotnet trace using the existing SDK" + RunSilent "dotnet tool install dotnet-trace" + else + WriteStatus "Installing .NET SDK and dotnet-trace in $sdkAndToolDir" + InstallSdkAndDotNetTraceLocally + fi +} + SupportsAutoInstall() { local supportsAutoInstall=0 @@ -1290,6 +1363,22 @@ EnsurePrereqsInstalled() fi + # if dotnet-trace is installed consider using it. + if [ "$dotnettracecmd" == "" ] && [ "$useDotnetTrace" == "1" ] + then + RedText + echo "dotnet-trace not installed." + if [ "$(SupportsAutoInstall)" == "1" ] + then + echo "Run ./perfcollect install" + echo "or install dotnet-trace manually" + else + echo "Install dotnet-trace to proceed." + fi + ResetText + exit 1 + fi + # If zip or unzip are not installing, then bail. if [ "$zipcmd" == "" ] || [ "$unzipcmd" == "" ] then @@ -1373,6 +1462,7 @@ ProcessArguments() if [ "-events" != "$arg" ] then # Convert the value to lower case. + rawvalue=$value value=`echo $value | tr '[:upper:]' '[:lower:]'` fi fi @@ -1421,18 +1511,29 @@ ProcessArguments() elif [ "-nolttng" == "$arg" ] then useLTTng=0 - elif [ "-noperf" == "$arg" ] + elif [ "-dotnet-trace" == "$arg" ] + then + useDotnetTrace=1 + useLTTng=0 + elif [ "-providers" == "$arg" ] + then + providers=$rawvalue + i=$i+1 + elif [ "-noperf" == "$arg" ] then usePerf=0 elif [ "-gccollectonly" == "$arg" ] then gcCollectOnly=1 + usePerf=0 elif [ "-gconly" == "$arg" ] then gcOnly=1 + usePerf=0 elif [ "-gcwithheap" == "$arg" ] then gcWithHeap=1 + usePerf=0 elif [ "-events" == "$arg" ] then events=$value @@ -1448,7 +1549,18 @@ ProcessArguments() } - +ValidateOptions() +{ + if [ "$collectionPid" == "" ] && [ "$useDotnetTrace" == "1" ] + then + FatalError "You must specify a .Net process id (-pid) to collect CLR events with dotnet-trace tool." + fi + + if [ "$providers" != "" ] && [ "$useDotnetTrace" == "1" ] + then + FatalError "You must specify -dotnet-trace when passing '-providers $providers'." + fi +} ## # LTTng collection @@ -1482,13 +1594,11 @@ SetupLTTngSession() RunSilent "$lttngcmd enable-event --userspace --tracepoint DotNETRuntime:EventSource" elif [ "$gcCollectOnly" == "1" ] then - usePerf=0 EnableLTTngEvents ${DotNETRuntime_GCKeyword_GCCollectOnly[@]} EnableLTTngEvents ${DotNETRuntimePrivate_GCPrivateKeyword_GCCollectOnly[@]} EnableLTTngEvents ${DotNETRuntime_ExceptionKeyword[@]} elif [ "$gcOnly" == "1" ] then - usePerf=0 EnableLTTngEvents ${DotNETRuntime_GCKeyword[@]} EnableLTTngEvents ${DotNETRuntimePrivate_GCPrivateKeyword[@]} EnableLTTngEvents ${DotNETRuntime_JitKeyword[@]} @@ -1496,7 +1606,6 @@ SetupLTTngSession() EnableLTTngEvents ${DotNETRuntime_ExceptionKeyword[@]} elif [ "$gcWithHeap" == "1" ] then - usePerf=0 EnableLTTngEvents ${DotNETRuntime_GCKeyword[@]} EnableLTTngEvents ${DotNETRuntime_GCHeapSurvivalAndMovementKeyword[@]} else @@ -1603,6 +1712,13 @@ ProcessCollectedData() fi fi + if [ "$useDotnetTrace" == "1" ] + then + LogAppend "Saving dotnet-trace trace file." + cp $dotnetTraceOutputFile . + cp $dotnetTraceLogFile . + fi + if [ "$usePerf" == 1 ] then # Get any perf-$pid.map files that were used by the @@ -1873,6 +1989,11 @@ EndCollect() StopLTTngCollection fi + if [ "$useDotnetTrace" == "1" ] + then + StopDotnetTraceCollection + fi + # Update the user. WriteStatus WriteStatus "...STOPPED." @@ -1902,6 +2023,9 @@ PrintUsage() echo " -threadtime : Collect events for thread time analysis (on and off cpu)." echo " -offcpu : Collect events for off-cpu analysis." echo " -hwevents : Collect (some) hardware counters." + echo " -dotnet-trace : Collect CLR events using dotnet-trace tool." + echo " -providers : Comma-separated-list of provider/keywords/verbosity (used only with -dotnet-trace option)." + echo " Example: Microsoft-Windows-DotNETRuntime:0x000000108001C039:5,Microsoft-Windows-DotNETRuntime:0x000000108001C039:4" echo "" echo "start:" echo " Start collection, but with Lttng trace ONLY. It needs to be used with 'stop' action." @@ -2000,10 +2124,84 @@ BuildPerfRecordArgs() durationString="sleep ${duration}" fi - # Add the events onto the collection command line args. + # Add the events onto the collection command line args. collectionArgs="$collectionArgs -e $eventString $durationString" } +BuildDotnetTraceArgs() +{ + dotnetTraceCollectionArgs="collect -p $collectionPid " + + activated_providers=() + if [ "$gcCollectOnly" == "1" ] + then + ## GC & Exception + activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000008001:4") + ## Private GC + activated_providers+=("Microsoft-Windows-DotNETRuntimePrivate:0x0000000000000001:4") + elif [ "$gcOnly" == "1" ] + then + ## GC & Jit & Loader & Exception + activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000080019:5") + ## Private GC + activated_providers+=("Microsoft-Windows-DotNETRuntimePrivate:0x0000000000000001:5") + elif [ "$gcWithHeap" == "1" ] + then + ## GC & GCHeapSurvivalAndMovement + activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000400001:5") + else + if [ "$providers" == "" ] + then + # Enable the default set of events. + + # DotNETRuntime with keywords: Exception, Contention, Jit/NGen, Loader, GC, Compilation + # Threading, ThreadTransfer & Jit + activated_providers+=("Microsoft-Windows-DotNETRuntime:0x000000108001C039:5") + + # DotNETRuntimeRundown with keyword(s): Compilation + activated_providers+=("Microsoft-Windows-DotNETRuntimeRundown:0x0000001000000000:4") + + # DotNETRuntimePrivate with keywords: GC, Binding, MulticoreJitPrivate + activated_providers+=("Microsoft-Windows-DotNETRuntimePrivate:0x0000000000020003:4") + + elif [ "$providers" == "threading" ] + then + activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000010000:5") + else + # Enable other keywords + providers=(${providers//","/" "}) + for provider in ${providers[@]} + do + activated_providers+=($provider) + done + fi + fi + if (( ${#activated_providers[@]} )) + then + joined_providers=$( IFS=","; echo "${activated_providers[*]}" ) + dotnetTraceCollectionArgs="$dotnetTraceCollectionArgs --providers $joined_providers" + fi + dotnetTraceOutputFile="$sdkAndToolDir/trace.nettrace" + dotnetTraceLogFile="$sdkAndToolDir/dotnet-trace.log" + dotnetTraceCollectionArgs="$dotnetTraceCollectionArgs -o $dotnetTraceOutputFile" +} + +StartDotnetTraceCollection() +{ + eval "$dotnettracecmd $dotnetTraceCollectionArgs < /dev/null > $dotnetTraceLogFile 2>&1 &" + dotnetTraceCollectionPid=$! +} + +StopDotnetTraceCollection() +{ + + RunSilent "kill -15 $dotnetTraceCollectionPid" + while [ "$dotnetTraceCollectionPid" != "" ] && [ -e /proc/$dotnetTraceCollectionPid ] + do + sleep .6 + done +} + DoCollect() { # Ensure the script is run as root. @@ -2029,6 +2227,12 @@ DoCollect() StartLTTngCollection fi + if [ "$useDotnetTrace" == "1" ] + then + BuildDotnetTraceArgs + StartDotnetTraceCollection + fi + # Tell the user that collection has started and how to exit. if [ "$duration" != "" ] then @@ -2047,7 +2251,7 @@ DoCollect() # Pass trace directory and session name to the stop process. popd > /dev/null usePerf=0 - declare -p | grep -e lttngTraceDir -e lttngSessionName -e tempDir -e usePerf -e useLttng -e logFile > $collectInfoFile + declare -p | grep -e lttngTraceDir -e lttngSessionName -e tempDir -e usePerf -e useLttng -e logFile -e dotnetTraceCollectionPid -e dotnetTraceOutputFile -e dotnetTraceLogFile > $collectInfoFile else if [ "$usePerf" == "1" ] then @@ -2194,6 +2398,7 @@ then fi InstallPerf InstallLTTng + InstallDotNetTraceTool exit 0 fi @@ -2209,6 +2414,8 @@ fi # Process arguments. ProcessArguments $@ +ValidateOptions + # Ensure prerequisites are installed. EnsurePrereqsInstalled diff --git a/src/perfcollect/tests/ConsoleApp1/ConsoleApp1.csproj b/src/perfcollect/tests/ConsoleApp1/ConsoleApp1.csproj new file mode 100644 index 000000000..41f1d5ad4 --- /dev/null +++ b/src/perfcollect/tests/ConsoleApp1/ConsoleApp1.csproj @@ -0,0 +1,8 @@ + + + + Exe + net6.0 + + + diff --git a/src/perfcollect/tests/ConsoleApp1/Program.cs b/src/perfcollect/tests/ConsoleApp1/Program.cs new file mode 100644 index 000000000..2f9cc51f9 --- /dev/null +++ b/src/perfcollect/tests/ConsoleApp1/Program.cs @@ -0,0 +1,57 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace ConsoleApp1 +{ + class Program + { + static void StartException(object ignored) + { + try + { + Thread.Sleep(TimeSpan.FromMilliseconds(100)); + throw new Exception(); + } + catch + { + } + } + static void RunException() + { + while (true) + { + for (int i = 0; i < 10; i++) + { + var thread = new Thread(StartException); + thread.IsBackground = true; + thread.Start(); + } + Thread.Sleep(TimeSpan.FromMilliseconds(100)); + } + } + + static void RunGC() + { + + while (true) + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + GC.Collect(); + } + } + + + static void Main(string[] args) + { + Console.WriteLine("PID: " + Process.GetCurrentProcess().Id); + + Task.Run(RunGC); + Task.Run(RunException); + while (true) + { + } + } + } +} diff --git a/src/perfcollect/tests/ConsoleApp1/Properties/launchSettings.json b/src/perfcollect/tests/ConsoleApp1/Properties/launchSettings.json new file mode 100644 index 000000000..928725764 --- /dev/null +++ b/src/perfcollect/tests/ConsoleApp1/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "ConsoleApp1": { + "commandName": "Executable", + "executablePath": "D:\\criteo_repos\\criteoforks\\runtime\\artifacts\\bin\\coreclr\\Windows_NT.x64.Debug\\corerun.exe", + "commandLineArgs": "C:\\Users\\spy\\Source\\Repos\\ConsoleApplication1\\ConsoleApp1\\bin\\Debug\\netcoreapp3.1\\win-x64\\publish\\ConsolApp1.dll", + "environmentVariables": { + "CORE_ROOT": "D:\\criteo_repos\\criteoforks\\runtime\\artifacts\\bin\\coreclr\\Windows_NT.x64.Debug", + "CORE_LIBRARIES": "D:\\criteo_repos\\criteoforks\\runtime\\artifacts\\dotnet-runtime-5.0.0-dev-win-x64\\shared\\Microsoft.NETCore.App\\5.0.0-dev" + } + } + } +} \ No newline at end of file diff --git a/src/perfcollect/tests/container-entrypoint.sh b/src/perfcollect/tests/container-entrypoint.sh index 1e5e0c6c4..e6f634a51 100755 --- a/src/perfcollect/tests/container-entrypoint.sh +++ b/src/perfcollect/tests/container-entrypoint.sh @@ -27,3 +27,35 @@ if [ "$perf_data_txt_size" == "0" ] then exit -1 fi + +### Test capturing CLR events + +# install sdk +mkdir sdk +cd sdk +curl -OL https://dot.net/v1/dotnet-install.sh +bash ./dotnet-install.sh --install-dir . + +# run ConsoleApp1 in background +cd /src/tests/ConsoleApp1 +/src/sdk/dotnet run & +appPid=$! + +echo "Dotnet-trace hangs if attached too early, waiting..." +sleep 15 +echo "Finsihed sleeping" + +# Capture a short trace with dotnet-trace activated. +$perfcollect collect test-dotnettrace -pid $appPid -dotnet-trace -collectsec 5 + +# kill ConsoleApp1 +kill -9 $appPid + +# Open the trace +unzip test-dotnettrace.trace.zip + +# Test the size of the trace.nettrace file +if [[ ! -s test-dotnettrace.trace/trace.nettrace ]] +then + exit -1 +fi