Skip to content

Conversation

matouskozak
Copy link
Member

@matouskozak matouskozak commented Aug 31, 2025

Description

Adding simple mobile telemetry triggered by Build target for android, ios, maccatalyst, and tvos. Collecting: TargetPlatformIdentifier, RuntimeIdentifier, UseMonoRuntime, PublishAot, PublishReadyToRun, PublishReadyToRunComposite properties.

Sample Output Telemetry

{
    "EventName": "MobileProperties",
    "Properties": {
        "Invocation": "build",
        "TargetPlatformIdentifier": "android",
        "RuntimeIdentifier": "android-arm64",
        "UseMonoRuntime": "true",
        "PublishAot": "false",
        "PublishReadyToRun": "false",
        "PublishReadyToRunComposite": "false"
    },
    "Timestamp": "2025-08-31T14:07:24.070952+01:00",
    "ThreadId": 9,
    "Message": null,
    "HelpKeyword": null,
    "SenderName": null,
    "BuildEventContext": {
        "EvaluationId": -1,
        "NodeId": 1,
        "TargetId": 381,
        "ProjectContextId": 99,
        "TaskId": 333,
        "ProjectInstanceId": 4,
        "SubmissionId": 1,
        "BuildRequestId": -2053145140
    }
}

Testing

Tested locally by installing android workload to .dotnet/dotnet and running the following tests:

Publish:

[CoreMSBuildOnlyTheory]
[InlineData(ToolsetInfo.CurrentTargetFramework)]
public void It_collects_Mobile_properties_for_publish(string targetFramework)
{
    Type loggerType = typeof(LogTelemetryToStdOutForTest);
    var TelemetryTestLogger = new[]
        {
            "--property:TargetPlatformIdentifier=android",
            "--property:RuntimeIdentifier=android-arm64",
            "--property:UseMonoRuntime=true",
            "--property:PublishAot=false",
            "--property:PublishReadyToRun=false",
            "--property:PublishReadyToRunComposite=false",
            $"/Logger:{loggerType.FullName},{loggerType.GetTypeInfo().Assembly.Location}"
        };

    var testProject = CreateTestProject(targetFramework, "MobileTelemetryPublishTest");
    var testProjectInstance = _testAssetsManager.CreateTestProject(testProject);
    var publishCommand = new PublishCommand(testProjectInstance);
    publishCommand.Execute(TelemetryTestLogger).StdOut.Should.Contain(...)

Build:

[CoreMSBuildOnlyFact]
public void It_collects_Mobile_properties_for_build()
{
    string targetFramework = ToolsetInfo.CurrentTargetFramework;
    var testProject = new TestProject()
    {
        Name = "MobileTelemetryBuildTest",
        TargetFrameworks = targetFramework,
    };
    Type loggerType = typeof(LogTelemetryToStdOutForTest);
    var telemetryArgs = new[]
        {
            "--property:TargetPlatformIdentifier=android",
            "--property:RuntimeIdentifier=android-arm64",
            "--property:UseMonoRuntime=false",
            "--property:PublishAot=false",
            "--property:PublishReadyToRun=true",
            "--property:PublishReadyToRunComposite=true",
            $"/Logger:{loggerType.FullName},{loggerType.GetTypeInfo().Assembly.Location}"
        };
    var testAsset = _testAssetsManager.CreateTestProject(testProject);

    var buildCommand = new BuildCommand(testAsset);

    buildCommand
        .Execute(telemetryArgs)
        .StdOut.Should()
        .Contain(...)

Another testing was done by locally modified version of SDK, where I modified the .target files and verified that the mobile telemetry targets get executed for dotnet new android app.

Open Questions

  1. How to setup tests using mobile workloads as part of the regular dotnet/sdk tests? (Instead of manually installing workload to .dotnet/dotnet)
  2. Currently, the telemetry collects data for all commands that invoke Build target. How could we distinguish in the telemetry if the invocation came from dotnet build or dotnet publish?
  3. How will this new telemetry data get propagated to Kusto?

I noticed that without "--property:TargetPlatformIdentifier=android", the TargetPlatformIdentifier in BeforeCommon.targets was left empty and the telemetry wasn't included. My concerns is if TargetPlatformIdentifier is populated soon enough so that the check in BeforeCommon.targets succeeds when building for mobile targets.

  • After overwriting the modified target files in a local SDK copy, I can see the MobileTelemetry targets getting triggered, so I suppose the check is working.

@matouskozak matouskozak added this to the 10.0.1xx milestone Aug 31, 2025
@matouskozak matouskozak self-assigned this Aug 31, 2025
Copy link
Contributor

This PR is targeting main, which is now for .NET 11-facing work. If you intended to target .NET 10, either retarget this PR to release/10.0.1xx or make sure you backport the change to release/10.0.1xx after merging. See #50394 for more details.

@matouskozak matouskozak marked this pull request as ready for review September 1, 2025 10:15
@Copilot Copilot AI review requested due to automatic review settings September 1, 2025 10:15
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds mobile telemetry hooks to collect build-time information for mobile platforms (Android, iOS, macOS Catalyst, and tvOS). The telemetry captures key properties like target platform, runtime identifier, and publishing configuration settings when the Build target is executed.

  • Creates a new mobile telemetry target file that collects platform-specific properties
  • Conditionally imports mobile telemetry only for mobile platforms in the build pipeline
  • Registers the new "MobileProperties" telemetry event in the MSBuild logger

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
Microsoft.NET.Sdk.BeforeCommon.targets Conditionally imports mobile telemetry targets for mobile platforms
Microsoft.NET.MobileTelemetry.targets New file defining build telemetry collection for mobile properties
MSBuildLogger.cs Adds MobileProperties event name to the telemetry logger

Comment on lines +147 to +150
Condition="'$(TargetPlatformIdentifier)' == 'android' or
'$(TargetPlatformIdentifier)' == 'ios' or
'$(TargetPlatformIdentifier)' == 'maccatalyst' or
'$(TargetPlatformIdentifier)' == 'tvos'" />
Copy link
Preview

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The condition uses string equality comparisons with 'or' operators spanning multiple lines. Consider using an ItemGroup with an 'in' operator for better readability and maintainability: Condition="$(TargetPlatformIdentifier) != '' and '$(TargetPlatformIdentifier)' in 'android;ios;maccatalyst;tvos'"

Suggested change
Condition="'$(TargetPlatformIdentifier)' == 'android' or
'$(TargetPlatformIdentifier)' == 'ios' or
'$(TargetPlatformIdentifier)' == 'maccatalyst' or
'$(TargetPlatformIdentifier)' == 'tvos'" />
Condition="'$(TargetPlatformIdentifier)' != '' and '$(TargetPlatformIdentifier)' in 'android;ios;maccatalyst;tvos'" />

Copilot uses AI. Check for mistakes.

Comment on lines +10 to +11
<ItemGroup>
<MobileTelemetry Remove="@(MobileTelemetry)" />
Copy link
Preview

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The ItemGroup removes all MobileTelemetry items and then recreates them. This pattern could be simplified by using a condition on the target or by ensuring the ItemGroup is only populated once, which would be more efficient and clearer in intent.

Suggested change
<ItemGroup>
<MobileTelemetry Remove="@(MobileTelemetry)" />

Copilot uses AI. Check for mistakes.

@baronfel
Copy link
Member

baronfel commented Sep 2, 2025

Triage/proposal:

  • We should instead unify the current Publish properties and targetframeworkeval events into one combined data set
  • We need to add a new SessionId value because the existing telemetry-context one isn't being forwarded for some reason
  • We need clarity from @matouskozak's team about how you'd like to reason about multi-project and/or multi-TFM builds
    • We may be able to filter out transitive builds triggered by a top-level project if so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants