Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Add RunWithLogging target (dotnet#8324)
Browse files Browse the repository at this point in the history
We are frequently faced with the need to look at some detailed
information optionally logged by our runtime (as well as by the
MonoVM runtime in dotnet/runtime), and in order to obtain the necessary
data, we ask our users to perform a series of steps on the command line.

This is a task we can easily wrap in a nice target, so that instead
of having to type 5 lines of commands the user instead invokes a
single command which will do the rest for them:

	dotnet build -t:RunWithLogging

The above command will:

 1. Set the `debug.mono.log` Android system property
 2. increase the `adb logcat` buffer size
 3. clear the `adb logcat` buffer,
 4. start the application waiting for it to be fully started
 5. pause for 1s
 6. dump the `adb logcat` buffer to a file.
 7. Print a message mentioning where the `adb logcat` output is.

The `$(RunLogVerbose)` MSBuild property can be used to increase
verbosity.  By default the `RunWithLogging` target will set
the `debug.mono.log` system property to:

	default,assembly,timing=bare

When `$(RunLogVerbose)`=true, `debug.mono.log` is instead set to:

	default,assembly,timing=bare,mono_log_level=debug,mono_log_mask=all

The `$(RunLogDelayInMS)` MSBuild property can be used to override the
pause in step (5).

The `$(_RunLogFilePath)` MSBuild property controls the output filename;
by default it is `$(IntermediateOutputPath)logcat.txt`.
  • Loading branch information
grendello authored Sep 21, 2023
1 parent 589b6e3 commit 791fedb
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 10 deletions.
12 changes: 12 additions & 0 deletions Documentation/guides/building-apps/build-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ MSBuild property controls which
[Visual Studio SDK Manager repository](~/android/get-started/installation/android-sdk.md?tabs=windows#repository-selection)
is used for package name and package version detection, and URLs to download.

## RunWithLogging

Runs the application with additional logging enabled. Helpful when reporting or investigating an issue with
either the application or the runtime. If successful, messages printed to the screen will show location
of the logcat file with the logged messages.

Properties which affect how the target works:

* `/p:RunLogVerbose=true` enables even more verbose logging from MonoVM
* `/p:RunLogDelayInMS=X` where `X` should be replaced with time in milliseconds to wait before writing the
log output to file. Defaults to `1000`.

## SignAndroidPackage

Creates and signs the Android package (`.apk`) file.
Expand Down
27 changes: 26 additions & 1 deletion Documentation/workflow/DevelopmentTips.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ A second (better) way is to add this MSBuild target to your Android
```xml
<Target Name="UpdateMonoRuntimePacks" BeforeTargets="ProcessFrameworkReferences">
<ItemGroup>
<KnownRuntimePack
<KnownRuntimePack
Update="Microsoft.NETCore.App"
Condition=" '%(KnownRuntimePack.TargetFramework)' == 'net6.0' "
LatestRuntimeFrameworkVersion="6.0.0-preview.7.21364.3"
Expand All @@ -477,6 +477,31 @@ automatically picked up by the .NET SDK.

## Enabling Mono Logging

### The easy way

A quick way to enable Mono logging is to use the `RunWithLogging`
target:

```bash
$ dotnet build -t:RunWithLogging
```

If successful, messages printed to the screen will show location
of the logcat file with the logged messages.

Verbosity of logging can be increased by setting the `$(RunLogVerbose)`
property to `true`, in which case the log output file will contain
(very) verbose log messages from the MonoVM runtime.

By default, the target will wait for a 1000ms before it dumps the
logcat buffer to file. This is to give the Android logging daemon
time to actually put all the messages logged by the application in
the logcat buffer. This value can be overridden by setting the
`$(RunLogDelayInMS)` MSBuild property to a number of milliseconds that
the target should wait before creating the log file.

### The manual way

Since [6e58ce4][6e58ce4], logging from Mono is no longer enabled by
default. You can set the `debug.mono.log` system property to answer
questions like: Is AOT working? Is the Mono Interpreter enabled?
Expand Down
8 changes: 4 additions & 4 deletions build-tools/scripts/TestApks.targets
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<UsingTask AssemblyFile="$(BootstrapTasksAssembly)" TaskName="Xamarin.Android.Tools.BootstrapTasks.StartAndroidEmulator" />
<UsingTask AssemblyFile="$(BootstrapTasksAssembly)" TaskName="Xamarin.Android.Tools.BootstrapTasks.KillProcess" />
<UsingTask AssemblyFile="$(BootstrapTasksAssembly)" TaskName="Xamarin.Android.Tools.BootstrapTasks.WaitForAndroidEmulator" />
<UsingTask AssemblyFile="$(PrepTasksAssembly)" TaskName="Xamarin.Android.BuildTools.PrepTasks.Sleep" />
<UsingTask AssemblyFile="$(PrepTasksAssembly)" TaskName="Xamarin.Android.BuildTools.PrepTasks.XASleepInternal" />
<UsingTask AssemblyFile="$(PrepTasksAssembly)" TaskName="Xamarin.Android.BuildTools.PrepTasks.ProcessLogcatTiming" />
<UsingTask AssemblyFile="$(PrepTasksAssembly)" TaskName="Xamarin.Android.BuildTools.PrepTasks.ProcessApkSizes" />

Expand Down Expand Up @@ -160,7 +160,7 @@
ContinueOnError="WarnAndContinue"
Command="kill -HUP $(_EmuPid)"
/>
<Sleep
<XASleepInternal
Condition=" '$(HostOS)' != 'Windows' And '$(_EmuTarget)' != '' "
Milliseconds="5000"
/>
Expand Down Expand Up @@ -375,7 +375,7 @@
ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="_SdkManagerExitCode" />
</Exec>
<Sleep
<XASleepInternal
Milliseconds="5000"
Condition=" '$(_SdkManagerExitCode)' != '0' "
/>
Expand All @@ -386,7 +386,7 @@
Condition=" '$(_SdkManagerExitCode)' != '0' ">
<Output TaskParameter="ExitCode" PropertyName="_SdkManagerExitCode" />
</Exec>
<Sleep
<XASleepInternal
Milliseconds="10000"
Condition=" '$(_SdkManagerExitCode)' != '0' "
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Android.Build.Tasks;

using TPLTask = System.Threading.Tasks.Task;

namespace Xamarin.Android.BuildTools.PrepTasks
{
public class Sleep : Task
public class XASleepInternal : AndroidAsyncTask
{
public override string TaskPrefix => "XASI";
public int Milliseconds { get; set; }

public override bool Execute ()
public override TPLTask RunTaskAsync ()
{
Log.LogMessage (MessageImportance.Normal, $"Going to sleep for {Milliseconds}ms");
Thread.Sleep (Milliseconds);

return true;
return TPLTask.Delay (Milliseconds, CancellationToken);
}
}
}
4 changes: 4 additions & 0 deletions build-tools/xa-prep-tasks/xa-prep-tasks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@
<Import Project="..\..\Configuration.props" />
<Import Project="..\..\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\MSBuildReferences.projitems" />

<ItemGroup>
<ProjectReference Include="..\..\external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\Microsoft.Android.Build.BaseTasks.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This file contains targets specific for Android application projects.
***********************************************************************************************
-->
<Project>
<UsingTask TaskName="Xamarin.Android.Tasks.GetAndroidActivityName" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />
<UsingTask TaskName="Xamarin.Android.BuildTools.PrepTasks.XASleepInternal" AssemblyFile="$(_XamarinAndroidBuildTasksAssembly)" />

<PropertyGroup>
<UseAppHost>false</UseAppHost>
Expand All @@ -28,4 +30,42 @@ This file contains targets specific for Android application projects.

<Target Name="Run" DependsOnTargets="$(_RunDependsOn)" />

<PropertyGroup>
<_RunWithLoggingDependsOn>
Install;
</_RunWithLoggingDependsOn>

<_RunLogFilePath Condition=" '$(_RunLogFilePath)' == '' ">$(IntermediateOutputPath)logcat.txt</_RunLogFilePath>
<RunLogVerbose Condition=" '$(RunLogVerbose)' == '' ">false</RunLogVerbose>
</PropertyGroup>

<Target Name="RunWithLogging"
DependsOnTargets="$(_RunWithLoggingDependsOn)">
<GetAndroidActivityName
Condition=" '$(AndroidLaunchActivity)' == '' "
ManifestFile="$(IntermediateOutputPath)android\AndroidManifest.xml">
<Output TaskParameter="ActivityName" PropertyName="AndroidLaunchActivity" />
</GetAndroidActivityName>

<PropertyGroup>
<_MonoLog>default,assembly,timing=bare</_MonoLog>
<_MonoLog Condition=" '$(RunLogVerbose)' != 'false' ">$(_MonoLog),mono_log_level=debug,mono_log_mask=all</_MonoLog>
<RunLogDelayInMS>1000</RunLogDelayInMS> <!-- milliseconds -->
</PropertyGroup>

<Message Text="Preparing application to log more information" Importance="High" />
<Message Text="Setting the debug.mono.log property to: $(_MonoLog)" Importance="High" />
<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) shell setprop debug.mono.log $(_MonoLog)" />
<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) logcat -G 16M" />
<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) logcat -c" />

<Message Text="Running the application and waiting for it to fully start" Importance="High" />
<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) shell am start -S -W -n &quot;$(_AndroidPackage)/$(AndroidLaunchActivity)&quot;" />

<Message Text="Sleeping for $(RunLogDelayInMS)ms to give logcat a chance to log all the messages" Importance="High" />
<XASleepInternal Milliseconds="$(RunLogDelayInMS)" />

<Exec Command="&quot;$(AdbToolPath)adb&quot; $(AdbTarget) logcat -d > &quot;$(_RunLogFilePath)&quot;" />
<Message Text="Logcat output is available in $(_RunLogFilePath)" Importance="High" />
</Target>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@
<Compile Include="..\Mono.Android\\Android\NativeLibraryReferenceAttribute.cs">
<Link>Mono.Android\NativeLibraryReferenceAttribute.cs</Link>
</Compile>
<Compile Include="..\..\build-tools\xa-prep-tasks\Xamarin.Android.BuildTools.PrepTasks\Sleep.cs">
<Link>Xamarin.Android.BuildTools.PrepTasks\Sleep.cs</Link>
</Compile>
<_MonoAndroidEnum Include="$(AndroidGeneratedClassDirectory)\Android.Content.PM.LaunchMode.cs" />
<_MonoAndroidEnum Include="$(AndroidGeneratedClassDirectory)\Android.Content.PM.ScreenOrientation.cs" />
<_MonoAndroidEnum Include="$(AndroidGeneratedClassDirectory)\Android.Content.PM.ConfigChanges.cs" />
Expand Down

0 comments on commit 791fedb

Please sign in to comment.