Skip to content

Commit

Permalink
Build properties of telemetry on fly (#9552)
Browse files Browse the repository at this point in the history
* Combine GetProperties with UpdateProperties functionality. Remove public UpdateProperties from TelemetryBase
  • Loading branch information
f-alizada authored Dec 19, 2023
1 parent 82d381e commit 40f51a5
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 91 deletions.
42 changes: 19 additions & 23 deletions src/Build.UnitTests/BackEnd/KnownTelemetry_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ public void BuildTelemetryConstructedHasNoProperties()
buildTelemetry.Target.ShouldBeNull();
buildTelemetry.Version.ShouldBeNull();

buildTelemetry.UpdateEventProperties();
buildTelemetry.Properties.ShouldBeEmpty();
buildTelemetry.GetProperties().ShouldBeEmpty();
}

[Fact]
Expand All @@ -75,22 +74,23 @@ public void BuildTelemetryCreateProperProperties()
buildTelemetry.Target = "clean";
buildTelemetry.Version = new Version(1, 2, 3, 4);

buildTelemetry.UpdateEventProperties();
buildTelemetry.Properties.Count.ShouldBe(11);
var properties = buildTelemetry.GetProperties();

buildTelemetry.Properties["BuildEngineDisplayVersion"].ShouldBe("Some Display Version");
buildTelemetry.Properties["BuildEngineFrameworkName"].ShouldBe("new .NET");
buildTelemetry.Properties["BuildEngineHost"].ShouldBe("Host description");
buildTelemetry.Properties["InitialMSBuildServerState"].ShouldBe("hot");
buildTelemetry.Properties["ProjectPath"].ShouldBe(@"C:\\dev\\theProject");
buildTelemetry.Properties["ServerFallbackReason"].ShouldBe("busy");
buildTelemetry.Properties["BuildSuccess"].ShouldBe("True");
buildTelemetry.Properties["BuildTarget"].ShouldBe("clean");
buildTelemetry.Properties["BuildEngineVersion"].ShouldBe("1.2.3.4");
properties.Count.ShouldBe(11);

properties["BuildEngineDisplayVersion"].ShouldBe("Some Display Version");
properties["BuildEngineFrameworkName"].ShouldBe("new .NET");
properties["BuildEngineHost"].ShouldBe("Host description");
properties["InitialMSBuildServerState"].ShouldBe("hot");
properties["ProjectPath"].ShouldBe(@"C:\\dev\\theProject");
properties["ServerFallbackReason"].ShouldBe("busy");
properties["BuildSuccess"].ShouldBe("True");
properties["BuildTarget"].ShouldBe("clean");
properties["BuildEngineVersion"].ShouldBe("1.2.3.4");

// verify computed
buildTelemetry.Properties["BuildDurationInMilliseconds"] = (finishedAt - startAt).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
buildTelemetry.Properties["InnerBuildDurationInMilliseconds"] = (finishedAt - innerStartAt).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
properties["BuildDurationInMilliseconds"] = (finishedAt - startAt).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
properties["InnerBuildDurationInMilliseconds"] = (finishedAt - innerStartAt).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
}

[Fact]
Expand All @@ -100,22 +100,18 @@ public void BuildTelemetryHandleNullsInRecordedTimes()

buildTelemetry.StartAt = DateTime.MinValue;
buildTelemetry.FinishedAt = null;
buildTelemetry.UpdateEventProperties();
buildTelemetry.Properties.ShouldBeEmpty();
buildTelemetry.GetProperties().ShouldBeEmpty();

buildTelemetry.StartAt = null;
buildTelemetry.FinishedAt = DateTime.MaxValue;
buildTelemetry.UpdateEventProperties();
buildTelemetry.Properties.ShouldBeEmpty();
buildTelemetry.GetProperties().ShouldBeEmpty();

buildTelemetry.InnerStartAt = DateTime.MinValue;
buildTelemetry.FinishedAt = null;
buildTelemetry.UpdateEventProperties();
buildTelemetry.Properties.ShouldBeEmpty();
buildTelemetry.GetProperties().ShouldBeEmpty();

buildTelemetry.InnerStartAt = null;
buildTelemetry.FinishedAt = DateTime.MaxValue;
buildTelemetry.UpdateEventProperties();
buildTelemetry.Properties.ShouldBeEmpty();
buildTelemetry.GetProperties().ShouldBeEmpty();
}
}
34 changes: 16 additions & 18 deletions src/Build.UnitTests/BackEnd/LoggingConfigurationTelemetry_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ public void BuildTelemetryConstructedHasNoProperties()
telemetry.BinaryLogger.ShouldBe(false);
telemetry.BinaryLoggerUsedDefaultName.ShouldBe(false);

telemetry.UpdateEventProperties();
telemetry.Properties.Where(kv => kv.Value != bool.FalseString).ShouldBeEmpty();
telemetry.GetProperties().Where(kv => kv.Value != bool.FalseString).ShouldBeEmpty();
}

[Fact]
Expand All @@ -65,21 +64,20 @@ public void BuildTelemetryCreateProperProperties()
BinaryLoggerUsedDefaultName = true
};

telemetry.UpdateEventProperties();

telemetry.Properties["TerminalLogger"].ShouldBe(bool.TrueString);
telemetry.Properties["TerminalLoggerUserIntent"].ShouldBe("on");
telemetry.Properties["TerminalLoggerUserIntentSource"].ShouldBe("arg");
telemetry.Properties["TerminalLoggerDefault"].ShouldBe("auto");
telemetry.Properties["TerminalLoggerDefaultSource"].ShouldBe("sdk");
telemetry.Properties["ConsoleLogger"].ShouldBe(bool.TrueString);
telemetry.Properties["ConsoleLoggerType"].ShouldBe("serial");
telemetry.Properties["ConsoleLoggerVerbosity"].ShouldBe("minimal");
telemetry.Properties["FileLogger"].ShouldBe(bool.TrueString);
telemetry.Properties["FileLoggerType"].ShouldBe("serial");
telemetry.Properties["FileLoggersCount"].ShouldBe("2");
telemetry.Properties["FileLoggerVerbosity"].ShouldBe("normal");
telemetry.Properties["BinaryLogger"].ShouldBe(bool.TrueString);
telemetry.Properties["BinaryLoggerUsedDefaultName"].ShouldBe(bool.TrueString);
var properties = telemetry.GetProperties();
properties["TerminalLogger"].ShouldBe(bool.TrueString);
properties["TerminalLoggerUserIntent"].ShouldBe("on");
properties["TerminalLoggerUserIntentSource"].ShouldBe("arg");
properties["TerminalLoggerDefault"].ShouldBe("auto");
properties["TerminalLoggerDefaultSource"].ShouldBe("sdk");
properties["ConsoleLogger"].ShouldBe(bool.TrueString);
properties["ConsoleLoggerType"].ShouldBe("serial");
properties["ConsoleLoggerVerbosity"].ShouldBe("minimal");
properties["FileLogger"].ShouldBe(bool.TrueString);
properties["FileLoggerType"].ShouldBe("serial");
properties["FileLoggersCount"].ShouldBe("2");
properties["FileLoggerVerbosity"].ShouldBe("normal");
properties["BinaryLogger"].ShouldBe(bool.TrueString);
properties["BinaryLoggerUsedDefaultName"].ShouldBe(bool.TrueString);
}
}
18 changes: 6 additions & 12 deletions src/Build.UnitTests/TerminalLoggerConfiguration_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ public void TerminalLoggerOn(string tlValue)
FileLogger = false,
};

expectedTelemetry.UpdateEventProperties();
foreach (KeyValuePair<string, string> pair in expectedTelemetry.Properties)
foreach (KeyValuePair<string, string> pair in expectedTelemetry.GetProperties())
{
output.ShouldContain($"{expectedTelemetry.EventName}:{pair.Key}={pair.Value}");
}
Expand Down Expand Up @@ -101,8 +100,7 @@ public void TerminalLoggerWithTlAutoIsOff(string tlValue)
FileLogger = false,
};

expectedTelemetry.UpdateEventProperties();
foreach (KeyValuePair<string, string> pair in expectedTelemetry.Properties)
foreach (KeyValuePair<string, string> pair in expectedTelemetry.GetProperties())
{
output.ShouldContain($"{expectedTelemetry.EventName}:{pair.Key}={pair.Value}");
}
Expand All @@ -129,8 +127,7 @@ public void TerminalLoggerDefaultByEnv()
FileLogger = false,
};

expectedTelemetry.UpdateEventProperties();
foreach (KeyValuePair<string, string> pair in expectedTelemetry.Properties)
foreach (KeyValuePair<string, string> pair in expectedTelemetry.GetProperties())
{
output.ShouldContain($"{expectedTelemetry.EventName}:{pair.Key}={pair.Value}");
}
Expand Down Expand Up @@ -159,8 +156,7 @@ public void TerminalLoggerOnByEnv(string envVarSource)
FileLogger = false,
};

expectedTelemetry.UpdateEventProperties();
foreach (KeyValuePair<string, string> pair in expectedTelemetry.Properties)
foreach (KeyValuePair<string, string> pair in expectedTelemetry.GetProperties())
{
output.ShouldContain($"{expectedTelemetry.EventName}:{pair.Key}={pair.Value}");
}
Expand Down Expand Up @@ -188,8 +184,7 @@ public void TerminalLoggerDefaultOn(string defaultValue)
FileLogger = false,
};

expectedTelemetry.UpdateEventProperties();
foreach (KeyValuePair<string, string> pair in expectedTelemetry.Properties)
foreach (KeyValuePair<string, string> pair in expectedTelemetry.GetProperties())
{
output.ShouldContain($"{expectedTelemetry.EventName}:{pair.Key}={pair.Value}");
}
Expand Down Expand Up @@ -219,8 +214,7 @@ public void TerminalLoggerDefaultOff(string defaultValue)
FileLogger = false,
};

expectedTelemetry.UpdateEventProperties();
foreach (KeyValuePair<string, string> pair in expectedTelemetry.Properties)
foreach (KeyValuePair<string, string> pair in expectedTelemetry.GetProperties())
{
output.ShouldContain($"{expectedTelemetry.EventName}:{pair.Key}={pair.Value}");
}
Expand Down
6 changes: 2 additions & 4 deletions src/Build/BackEnd/BuildManager/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,7 @@ public void BeginBuild(BuildParameters parameters)
LogDeferredMessages(loggingService, _deferredBuildMessages);

// Log known deferred telemetry
KnownTelemetry.LoggingConfigurationTelemetry.UpdateEventProperties();
loggingService.LogTelemetry(buildEventContext: null, KnownTelemetry.LoggingConfigurationTelemetry.EventName, KnownTelemetry.LoggingConfigurationTelemetry.Properties);
loggingService.LogTelemetry(buildEventContext: null, KnownTelemetry.LoggingConfigurationTelemetry.EventName, KnownTelemetry.LoggingConfigurationTelemetry.GetProperties());

InitializeCaches();

Expand Down Expand Up @@ -1090,8 +1089,7 @@ public void EndBuild()
}
_buildTelemetry.Host = host;

_buildTelemetry.UpdateEventProperties();
loggingService.LogTelemetry(buildEventContext: null, _buildTelemetry.EventName, _buildTelemetry.Properties);
loggingService.LogTelemetry(buildEventContext: null, _buildTelemetry.EventName, _buildTelemetry.GetProperties());
// Clean telemetry to make it ready for next build submission.
_buildTelemetry = null;
}
Expand Down
30 changes: 18 additions & 12 deletions src/Framework/Telemetry/BuildTelemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Globalization;

namespace Microsoft.Build.Framework.Telemetry
Expand Down Expand Up @@ -84,62 +85,67 @@ internal class BuildTelemetry : TelemetryBase
/// </summary>
public string? FrameworkName { get; set; }

public override void UpdateEventProperties()
public override IDictionary<string, string> GetProperties()
{
var properties = new Dictionary<string, string>();

// populate property values
if (DisplayVersion != null)
{
Properties["BuildEngineDisplayVersion"] = DisplayVersion;
properties["BuildEngineDisplayVersion"] = DisplayVersion;
}

if (StartAt.HasValue && FinishedAt.HasValue)
{
Properties["BuildDurationInMilliseconds"] = (FinishedAt.Value - StartAt.Value).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
properties["BuildDurationInMilliseconds"] = (FinishedAt.Value - StartAt.Value).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
}

if (InnerStartAt.HasValue && FinishedAt.HasValue)
{
Properties["InnerBuildDurationInMilliseconds"] = (FinishedAt.Value - InnerStartAt.Value).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
properties["InnerBuildDurationInMilliseconds"] = (FinishedAt.Value - InnerStartAt.Value).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
}

if (FrameworkName != null)
{
Properties["BuildEngineFrameworkName"] = FrameworkName;
properties["BuildEngineFrameworkName"] = FrameworkName;
}

if (Host != null)
{
Properties["BuildEngineHost"] = Host;
properties["BuildEngineHost"] = Host;
}

if (InitialServerState != null)
{
Properties["InitialMSBuildServerState"] = InitialServerState;
properties["InitialMSBuildServerState"] = InitialServerState;
}

if (Project != null)
{
Properties["ProjectPath"] = Project;
properties["ProjectPath"] = Project;
}

if (ServerFallbackReason != null)
{
Properties["ServerFallbackReason"] = ServerFallbackReason;
properties["ServerFallbackReason"] = ServerFallbackReason;
}

if (Success.HasValue)
{
Properties["BuildSuccess"] = Success.HasValue.ToString(CultureInfo.InvariantCulture);
properties["BuildSuccess"] = Success.HasValue.ToString(CultureInfo.InvariantCulture);
}

if (Target != null)
{
Properties["BuildTarget"] = Target;
properties["BuildTarget"] = Target;
}

if (Version != null)
{
Properties["BuildEngineVersion"] = Version.ToString();
properties["BuildEngineVersion"] = Version.ToString();
}

return properties;
}
}
}
36 changes: 21 additions & 15 deletions src/Framework/Telemetry/LoggingConfigurationTelemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Globalization;

namespace Microsoft.Build.Framework.Telemetry;
Expand Down Expand Up @@ -97,54 +98,59 @@ internal class LoggingConfigurationTelemetry : TelemetryBase
/// </summary>
public bool BinaryLoggerUsedDefaultName { get; set; }

public override void UpdateEventProperties()
public override IDictionary<string, string> GetProperties()
{
Properties["TerminalLogger"] = TerminalLogger.ToString(CultureInfo.InvariantCulture);
var properties = new Dictionary<string, string>();

// populate property values
properties["TerminalLogger"] = TerminalLogger.ToString(CultureInfo.InvariantCulture);

if (TerminalLoggerUserIntent != null)
{
Properties["TerminalLoggerUserIntent"] = TerminalLoggerUserIntent;
properties["TerminalLoggerUserIntent"] = TerminalLoggerUserIntent;
}

if (TerminalLoggerUserIntentSource != null)
{
Properties["TerminalLoggerUserIntentSource"] = TerminalLoggerUserIntentSource;
properties["TerminalLoggerUserIntentSource"] = TerminalLoggerUserIntentSource;
}

if (TerminalLoggerDefault != null)
{
Properties["TerminalLoggerDefault"] = TerminalLoggerDefault;
properties["TerminalLoggerDefault"] = TerminalLoggerDefault;
}

if (TerminalLoggerDefaultSource != null)
{
Properties["TerminalLoggerDefaultSource"] = TerminalLoggerDefaultSource;
properties["TerminalLoggerDefaultSource"] = TerminalLoggerDefaultSource;
}

Properties["ConsoleLogger"] = ConsoleLogger.ToString(CultureInfo.InvariantCulture);
properties["ConsoleLogger"] = ConsoleLogger.ToString(CultureInfo.InvariantCulture);
if (ConsoleLoggerType != null)
{
Properties["ConsoleLoggerType"] = ConsoleLoggerType;
properties["ConsoleLoggerType"] = ConsoleLoggerType;
}

if (ConsoleLoggerVerbosity != null)
{
Properties["ConsoleLoggerVerbosity"] = ConsoleLoggerVerbosity;
properties["ConsoleLoggerVerbosity"] = ConsoleLoggerVerbosity;
}

Properties["FileLogger"] = FileLogger.ToString(CultureInfo.InvariantCulture);
properties["FileLogger"] = FileLogger.ToString(CultureInfo.InvariantCulture);
if (FileLoggerType != null)
{
Properties["FileLoggerType"] = FileLoggerType;
Properties["FileLoggersCount"] = FileLoggersCount.ToString(CultureInfo.InvariantCulture);
properties["FileLoggerType"] = FileLoggerType;
properties["FileLoggersCount"] = FileLoggersCount.ToString(CultureInfo.InvariantCulture);
}

if (FileLoggerVerbosity != null)
{
Properties["FileLoggerVerbosity"] = FileLoggerVerbosity;
properties["FileLoggerVerbosity"] = FileLoggerVerbosity;
}

Properties["BinaryLogger"] = BinaryLogger.ToString(CultureInfo.InvariantCulture);
Properties["BinaryLoggerUsedDefaultName"] = BinaryLoggerUsedDefaultName.ToString(CultureInfo.InvariantCulture);
properties["BinaryLogger"] = BinaryLogger.ToString(CultureInfo.InvariantCulture);
properties["BinaryLoggerUsedDefaultName"] = BinaryLoggerUsedDefaultName.ToString(CultureInfo.InvariantCulture);

return properties;
}
}
9 changes: 2 additions & 7 deletions src/Framework/Telemetry/TelemetryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@ internal abstract class TelemetryBase
public abstract string EventName { get; }

/// <summary>
/// Gets or sets a list of properties associated with the event.
/// Fetches all derived type members wrapped in Dictionary which will be used to build <see cref="TelemetryEventArgs"/>.
/// </summary>
public IDictionary<string, string> Properties { get; set; } = new Dictionary<string, string>();

/// <summary>
/// Translate all derived type members into properties which will be used to build <see cref="TelemetryEventArgs"/>.
/// </summary>
public abstract void UpdateEventProperties();
public abstract IDictionary<string, string> GetProperties();
}

0 comments on commit 40f51a5

Please sign in to comment.