@@ -642,6 +642,10 @@ usePerf=1
642642# Use LTTng
643643useLTTng=1
644644
645+ # Use EventPipe to collect CLR events
646+ useEventPipe=0
647+ sdkAndToolDir=" /tmp/dotnet_sdk_tool"
648+
645649# LTTng Installed
646650lttngInstalled=0
647651
@@ -1332,6 +1336,7 @@ ProcessArguments()
13321336 if [ " -events" != " $arg " ]
13331337 then
13341338 # Convert the value to lower case.
1339+ rawvalue=$value
13351340 value=` echo $value | tr ' [:upper:]' ' [:lower:]' `
13361341 fi
13371342 fi
@@ -1377,6 +1382,18 @@ ProcessArguments()
13771382 elif [ " -nolttng" == " $arg " ]
13781383 then
13791384 useLTTng=0
1385+ elif [ " -eventpipe" == " $arg " ]
1386+ then
1387+ useEventPipe=1
1388+ useLTTng=0
1389+ elif [ " -providers" == " $arg " ]
1390+ then
1391+ providers=$rawvalue
1392+ i=$i +1
1393+ elif [ " -sdk-path" == " $arg " ]
1394+ then
1395+ sdkAndToolDir=$value
1396+ i=$i +1
13801397 elif [ " -noperf" == " $arg " ]
13811398 then
13821399 usePerf=0
@@ -1556,6 +1573,13 @@ ProcessCollectedData()
15561573 fi
15571574 fi
15581575
1576+ if [ " $useEventPipe " == " 1" ]
1577+ then
1578+ LogAppend " Saving EventPipe trace file."
1579+ cp $eventPipeOutputFile .
1580+ cp $eventPipeLogFile .
1581+ fi
1582+
15591583 if [ " $usePerf " == 1 ]
15601584 then
15611585 # Get any perf-$pid.map files that were used by the
@@ -1829,6 +1853,11 @@ EndCollect()
18291853 StopLTTngCollection
18301854 fi
18311855
1856+ if [ " $useEventPipe " == " 1" ]
1857+ then
1858+ StopEventPipeCollection
1859+ fi
1860+
18321861 # Update the user.
18331862 WriteStatus
18341863 WriteStatus " ...STOPPED."
@@ -1951,10 +1980,89 @@ BuildPerfRecordArgs()
19511980 durationString=" sleep ${duration} "
19521981 fi
19531982
1954- # Add the events onto the collection command line args.
1983+ # Add the events onto the collection command line args.
19551984 collectionArgs=" $collectionArgs -e $eventString $durationString "
19561985}
19571986
1987+ BuildEventPipeArgs ()
1988+ {
1989+ if [ " $collectionPid " == " " ]
1990+ then
1991+ FatalError " You must specify a .Net process id (-pid) to collect CLR events through EventPipe"
1992+ fi
1993+ eventPipeCollectionArgs=" collect -p $collectionPid "
1994+
1995+ activated_providers=()
1996+ if [ " $gcCollectOnly " == " 1" ]
1997+ then
1998+ # # GC & Exception
1999+ activated_providers+=(" Microsoft-Windows-DotNETRuntime:0x0000000000008001:4" )
2000+ # # Private GC
2001+ activated_providers+=(" Microsoft-Windows-DotNETRuntimePrivate:0x0000000000000001:4" )
2002+ elif [ " $gcOnly " == " 1" ]
2003+ then
2004+ # # GC & Jit & Loader & Exception
2005+ activated_providers+=(" Microsoft-Windows-DotNETRuntime:0x0000000000080019:5" )
2006+ # # Private GC
2007+ activated_providers+=(" Microsoft-Windows-DotNETRuntimePrivate:0x0000000000000001:5" )
2008+ elif [ " $gcWithHeap " == " 1" ]
2009+ then
2010+ # # GC & GCHeapSurvivalAndMovement
2011+ activated_providers+=(" Microsoft-Windows-DotNETRuntime:0x0000000000400001:5" )
2012+ else
2013+ if [ " $providers " == " " ]
2014+ then
2015+ # Enable the default set of events.
2016+
2017+ # DotNETRuntime with keywords: Exception, Contention, Jit/NGen, Loader, GC, Compilation
2018+ # Threading, ThreadTransfer & Jit
2019+ activated_providers+=(" Microsoft-Windows-DotNETRuntime:0x000000108001C039:5" )
2020+
2021+ # DotNETRuntimeRundown with keyword(s): Compilation
2022+ activated_providers+=(" Microsoft-Windows-DotNETRuntimeRundown:0x0000001000000000:4" )
2023+
2024+ # DotNETRuntimePrivate with keywords: GC, Binding, MulticoreJitPrivate
2025+ activated_providers+=(" Microsoft-Windows-DotNETRuntimePrivate:0x0000000000020003:4" )
2026+
2027+ elif [ " $providers " == " threading" ]
2028+ then
2029+ activated_providers+=(" Microsoft-Windows-DotNETRuntime:0x0000000000010000:5" )
2030+ else
2031+ # Enable other keywords
2032+ providers=(${providers// " ," / " " } )
2033+ for provider in ${providers[@]}
2034+ do
2035+ activated_providers+=($provider )
2036+ done
2037+ fi
2038+ fi
2039+ if (( ${# activated_providers[@]} ))
2040+ then
2041+ joined_providers=$( IFS=" ," ; echo " ${activated_providers[*]} " )
2042+ eventPipeCollectionArgs=" $eventPipeCollectionArgs --providers $joined_providers "
2043+ fi
2044+ eventPipeOutputFile=" $sdkAndToolDir /trace.nettrace"
2045+ eventPipeLogFile=" $sdkAndToolDir /eventpipe.log"
2046+ eventPipeCollectionArgs=" $eventPipeCollectionArgs -o $eventPipeOutputFile "
2047+ }
2048+
2049+ StartEventPipeCollection ()
2050+ {
2051+ pushd $sdkAndToolDir > /dev/null
2052+ eval " ./dotnet trace $eventPipeCollectionArgs < /dev/null > $eventPipeLogFile 2>&1 &"
2053+ eventPipeCollectionPid=$!
2054+ popd > /dev/null
2055+ }
2056+
2057+ StopEventPipeCollection ()
2058+ {
2059+ RunSilent " kill -15 $eventPipeCollectionPid "
2060+ while [ " $eventPipeCollectionPid " != " " ] && [ -e /proc/$eventPipeCollectionPid ]
2061+ do
2062+ sleep .6
2063+ done
2064+ }
2065+
19582066DoCollect ()
19592067{
19602068 # Ensure the script is run as root.
@@ -1980,6 +2088,12 @@ DoCollect()
19802088 StartLTTngCollection
19812089 fi
19822090
2091+ if [ " $useEventPipe " == " 1" ]
2092+ then
2093+ BuildEventPipeArgs
2094+ StartEventPipeCollection
2095+ fi
2096+
19832097 # Tell the user that collection has started and how to exit.
19842098 if [ " $duration " != " " ]
19852099 then
@@ -1998,7 +2112,7 @@ DoCollect()
19982112 # Pass trace directory and session name to the stop process.
19992113 popd > /dev/null
20002114 usePerf=0
2001- declare -p | grep -e lttngTraceDir -e lttngSessionName -e tempDir -e usePerf -e useLttng -e logFile > $collectInfoFile
2115+ declare -p | grep -e lttngTraceDir -e lttngSessionName -e tempDir -e usePerf -e useLttng -e logFile -e eventPipeCollectionPid -e eventPipeOutputFile -e eventPipeLogFile > $collectInfoFile
20022116 else
20032117 if [ " $usePerf " == " 1" ]
20042118 then
@@ -2112,6 +2226,51 @@ DoView()
21122226 rm -rf $tempDir
21132227}
21142228
2229+ IsTraceToolInstalled ()
2230+ {
2231+ # check global
2232+ local installed=0
2233+
2234+ if $( $sdkAndToolDir /dotnet tool list -g | grep -q " dotnet-trace" )
2235+ then
2236+ installed=1
2237+ elif $( $sdkAndToolDir /dotnet tool list --local | grep -q " dotnet-trace" )
2238+ then
2239+ installed=1
2240+ fi
2241+
2242+ echo $installed
2243+ }
2244+
2245+ EnsureDotNetTraceToolIsInstalled ()
2246+ {
2247+ if [ ! -d " $sdkAndToolDir " ]
2248+ then
2249+ WriteStatus " Installing dotnet sdk in $sdkAndToolDir "
2250+ ResetText
2251+ RunSilent " mkdir $sdkAndToolDir "
2252+ RunSilent " curl -OL https://dot.net/v1/dotnet-install.sh"
2253+ RunSilent " bash ./dotnet-install.sh --install-dir $sdkAndToolDir "
2254+ fi
2255+
2256+ pushd $sdkAndToolDir > /dev/null
2257+ if [ " $( IsTraceToolInstalled) " != " 1" ]
2258+ then
2259+ # create a tool-manifest. If there is one, it won't be overwritten.
2260+ WriteStatus " Installing dotnet trace"
2261+ RunSilent " ./dotnet new tool-manifest"
2262+ RunSilent " ./dotnet tool install dotnet-trace --local"
2263+ fi
2264+
2265+ ./dotnet trace --version > /dev/null 2>&1
2266+ if [ " $? " != 0 ]
2267+ then
2268+ FatalError " dotnet-trace tool was installed correctly."
2269+ fi
2270+ LogAppend ' dotnet-trace version:' ` $sdkAndToolDir /dotnet trace --version`
2271+ popd > /dev/null
2272+ }
2273+
21152274# ####################################
21162275# # Main Script Start
21172276# ####################################
@@ -2150,6 +2309,11 @@ ProcessArguments $@
21502309# Ensure prerequisites are installed.
21512310EnsurePrereqsInstalled
21522311
2312+ if [ " $useEventPipe " == " 1" ] && [ " $1 " != " stop" ]
2313+ then
2314+ EnsureDotNetTraceToolIsInstalled
2315+ fi
2316+
21532317# Take the appropriate action.
21542318if [ " $action " == " collect" ] || [ " $action " == " start" ]
21552319then
0 commit comments