Skip to content

Commit 4c4c6de

Browse files
author
Gregory LEOCADIE
committed
Add support for events collection through EventPipe
1 parent 9b5b7a6 commit 4c4c6de

File tree

1 file changed

+169
-5
lines changed

1 file changed

+169
-5
lines changed

src/perfcollect/perfcollect

Lines changed: 169 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,10 @@ usePerf=1
642642
# Use LTTng
643643
useLTTng=1
644644

645+
# Use EventPipe to collect CLR events
646+
useEventPipe=0
647+
sdkAndToolDir="/tmp/dotnet_sdk_tool"
648+
645649
# LTTng Installed
646650
lttngInstalled=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,18 +1382,33 @@ 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
13831400
elif [ "-gccollectonly" == "$arg" ]
13841401
then
13851402
gcCollectOnly=1
1403+
usePerf=0
13861404
elif [ "-gconly" == "$arg" ]
13871405
then
13881406
gcOnly=1
1407+
usePerf=0
13891408
elif [ "-gcwithheap" == "$arg" ]
13901409
then
13911410
gcWithHeap=1
1411+
usePerf=0
13921412
elif [ "-events" == "$arg" ]
13931413
then
13941414
events=$value
@@ -1438,21 +1458,18 @@ SetupLTTngSession()
14381458
RunSilent "$lttngcmd enable-event --userspace --tracepoint DotNETRuntime:EventSource"
14391459
elif [ "$gcCollectOnly" == "1" ]
14401460
then
1441-
usePerf=0
14421461
EnableLTTngEvents ${DotNETRuntime_GCKeyword_GCCollectOnly[@]}
14431462
EnableLTTngEvents ${DotNETRuntimePrivate_GCPrivateKeyword_GCCollectOnly[@]}
14441463
EnableLTTngEvents ${DotNETRuntime_ExceptionKeyword[@]}
14451464
elif [ "$gcOnly" == "1" ]
14461465
then
1447-
usePerf=0
14481466
EnableLTTngEvents ${DotNETRuntime_GCKeyword[@]}
14491467
EnableLTTngEvents ${DotNETRuntimePrivate_GCPrivateKeyword[@]}
14501468
EnableLTTngEvents ${DotNETRuntime_JitKeyword[@]}
14511469
EnableLTTngEvents ${DotNETRuntime_LoaderKeyword[@]}
14521470
EnableLTTngEvents ${DotNETRuntime_ExceptionKeyword[@]}
14531471
elif [ "$gcWithHeap" == "1" ]
14541472
then
1455-
usePerf=0
14561473
EnableLTTngEvents ${DotNETRuntime_GCKeyword[@]}
14571474
EnableLTTngEvents ${DotNETRuntime_GCHeapSurvivalAndMovementKeyword[@]}
14581475
else
@@ -1559,6 +1576,13 @@ ProcessCollectedData()
15591576
fi
15601577
fi
15611578

1579+
if [ "$useEventPipe" == "1" ]
1580+
then
1581+
LogAppend "Saving EventPipe trace file."
1582+
cp $eventPipeOutputFile .
1583+
cp $eventPipeLogFile .
1584+
fi
1585+
15621586
if [ "$usePerf" == 1 ]
15631587
then
15641588
# Get any perf-$pid.map files that were used by the
@@ -1832,6 +1856,11 @@ EndCollect()
18321856
StopLTTngCollection
18331857
fi
18341858

1859+
if [ "$useEventPipe" == "1" ]
1860+
then
1861+
StopEventPipeCollection
1862+
fi
1863+
18351864
# Update the user.
18361865
WriteStatus
18371866
WriteStatus "...STOPPED."
@@ -1954,10 +1983,89 @@ BuildPerfRecordArgs()
19541983
durationString="sleep ${duration}"
19551984
fi
19561985

1957-
# Add the events onto the collection command line args.
1986+
# Add the events onto the collection command line args.
19581987
collectionArgs="$collectionArgs -e $eventString $durationString"
19591988
}
19601989

1990+
BuildEventPipeArgs()
1991+
{
1992+
if [ "$collectionPid" == "" ]
1993+
then
1994+
FatalError "You must specify a .Net process id (-pid) to collect CLR events through EventPipe"
1995+
fi
1996+
eventPipeCollectionArgs="collect -p $collectionPid "
1997+
1998+
activated_providers=()
1999+
if [ "$gcCollectOnly" == "1" ]
2000+
then
2001+
## GC & Exception
2002+
activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000008001:4")
2003+
## Private GC
2004+
activated_providers+=("Microsoft-Windows-DotNETRuntimePrivate:0x0000000000000001:4")
2005+
elif [ "$gcOnly" == "1" ]
2006+
then
2007+
## GC & Jit & Loader & Exception
2008+
activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000080019:5")
2009+
## Private GC
2010+
activated_providers+=("Microsoft-Windows-DotNETRuntimePrivate:0x0000000000000001:5")
2011+
elif [ "$gcWithHeap" == "1" ]
2012+
then
2013+
## GC & GCHeapSurvivalAndMovement
2014+
activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000400001:5")
2015+
else
2016+
if [ "$providers" == "" ]
2017+
then
2018+
# Enable the default set of events.
2019+
2020+
# DotNETRuntime with keywords: Exception, Contention, Jit/NGen, Loader, GC, Compilation
2021+
# Threading, ThreadTransfer & Jit
2022+
activated_providers+=("Microsoft-Windows-DotNETRuntime:0x000000108001C039:5")
2023+
2024+
# DotNETRuntimeRundown with keyword(s): Compilation
2025+
activated_providers+=("Microsoft-Windows-DotNETRuntimeRundown:0x0000001000000000:4")
2026+
2027+
# DotNETRuntimePrivate with keywords: GC, Binding, MulticoreJitPrivate
2028+
activated_providers+=("Microsoft-Windows-DotNETRuntimePrivate:0x0000000000020003:4")
2029+
2030+
elif [ "$providers" == "threading" ]
2031+
then
2032+
activated_providers+=("Microsoft-Windows-DotNETRuntime:0x0000000000010000:5")
2033+
else
2034+
# Enable other keywords
2035+
providers=(${providers//","/" "})
2036+
for provider in ${providers[@]}
2037+
do
2038+
activated_providers+=($provider)
2039+
done
2040+
fi
2041+
fi
2042+
if (( ${#activated_providers[@]} ))
2043+
then
2044+
joined_providers=$( IFS=","; echo "${activated_providers[*]}" )
2045+
eventPipeCollectionArgs="$eventPipeCollectionArgs --providers $joined_providers"
2046+
fi
2047+
eventPipeOutputFile="$sdkAndToolDir/trace.nettrace"
2048+
eventPipeLogFile="$sdkAndToolDir/eventpipe.log"
2049+
eventPipeCollectionArgs="$eventPipeCollectionArgs -o $eventPipeOutputFile"
2050+
}
2051+
2052+
StartEventPipeCollection()
2053+
{
2054+
pushd $sdkAndToolDir > /dev/null
2055+
eval "./dotnet trace $eventPipeCollectionArgs < /dev/null > $eventPipeLogFile 2>&1 &"
2056+
eventPipeCollectionPid=$!
2057+
popd > /dev/null
2058+
}
2059+
2060+
StopEventPipeCollection()
2061+
{
2062+
RunSilent "kill -15 $eventPipeCollectionPid"
2063+
while [ "$eventPipeCollectionPid" != "" ] && [ -e /proc/$eventPipeCollectionPid ]
2064+
do
2065+
sleep .6
2066+
done
2067+
}
2068+
19612069
DoCollect()
19622070
{
19632071
# Ensure the script is run as root.
@@ -1983,6 +2091,12 @@ DoCollect()
19832091
StartLTTngCollection
19842092
fi
19852093

2094+
if [ "$useEventPipe" == "1" ]
2095+
then
2096+
BuildEventPipeArgs
2097+
StartEventPipeCollection
2098+
fi
2099+
19862100
# Tell the user that collection has started and how to exit.
19872101
if [ "$duration" != "" ]
19882102
then
@@ -2001,7 +2115,7 @@ DoCollect()
20012115
# Pass trace directory and session name to the stop process.
20022116
popd > /dev/null
20032117
usePerf=0
2004-
declare -p | grep -e lttngTraceDir -e lttngSessionName -e tempDir -e usePerf -e useLttng -e logFile > $collectInfoFile
2118+
declare -p | grep -e lttngTraceDir -e lttngSessionName -e tempDir -e usePerf -e useLttng -e logFile -e eventPipeCollectionPid -e eventPipeOutputFile -e eventPipeLogFile > $collectInfoFile
20052119
else
20062120
if [ "$usePerf" == "1" ]
20072121
then
@@ -2115,6 +2229,51 @@ DoView()
21152229
rm -rf $tempDir
21162230
}
21172231

2232+
IsTraceToolInstalled()
2233+
{
2234+
# check global
2235+
local installed=0
2236+
2237+
if $($sdkAndToolDir/dotnet tool list -g | grep -q "dotnet-trace")
2238+
then
2239+
installed=1
2240+
elif $($sdkAndToolDir/dotnet tool list --local | grep -q "dotnet-trace")
2241+
then
2242+
installed=1
2243+
fi
2244+
2245+
echo $installed
2246+
}
2247+
2248+
EnsureDotNetTraceToolIsInstalled()
2249+
{
2250+
if [ ! -d "$sdkAndToolDir" ]
2251+
then
2252+
WriteStatus "Installing dotnet sdk in $sdkAndToolDir"
2253+
ResetText
2254+
RunSilent "mkdir $sdkAndToolDir"
2255+
RunSilent "curl -OL https://dot.net/v1/dotnet-install.sh"
2256+
RunSilent "bash ./dotnet-install.sh --install-dir $sdkAndToolDir"
2257+
fi
2258+
2259+
pushd $sdkAndToolDir > /dev/null
2260+
if [ "$(IsTraceToolInstalled)" != "1" ]
2261+
then
2262+
# create a tool-manifest. If there is one, it won't be overwritten.
2263+
WriteStatus "Installing dotnet trace"
2264+
RunSilent "./dotnet new tool-manifest"
2265+
RunSilent "./dotnet tool install dotnet-trace --local"
2266+
fi
2267+
2268+
./dotnet trace --version > /dev/null 2>&1
2269+
if [ "$?" != 0 ]
2270+
then
2271+
FatalError "dotnet-trace tool was installed correctly."
2272+
fi
2273+
LogAppend 'dotnet-trace version:' `$sdkAndToolDir/dotnet trace --version`
2274+
popd > /dev/null
2275+
}
2276+
21182277
#####################################
21192278
## Main Script Start
21202279
#####################################
@@ -2153,6 +2312,11 @@ ProcessArguments $@
21532312
# Ensure prerequisites are installed.
21542313
EnsurePrereqsInstalled
21552314

2315+
if [ "$useEventPipe" == "1" ] && [ "$1" != "stop" ]
2316+
then
2317+
EnsureDotNetTraceToolIsInstalled
2318+
fi
2319+
21562320
# Take the appropriate action.
21572321
if [ "$action" == "collect" ] || [ "$action" == "start" ]
21582322
then

0 commit comments

Comments
 (0)