Skip to content

Commit ca58f17

Browse files
committed
Add globalJson property for global.json state to toplevelparser/command event
1 parent 1010968 commit ca58f17

File tree

5 files changed

+55
-5
lines changed

5 files changed

+55
-5
lines changed

src/Cli/dotnet/Program.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,18 @@ internal static int ProcessArgs(string[] args, TimeSpan startupTime)
230230
}
231231
PerformanceLogEventSource.Log.TelemetrySaveIfEnabledStart();
232232
performanceData.Add("Startup Time", startupTime.TotalMilliseconds);
233-
TelemetryEventEntry.SendFiltered(Tuple.Create(parseResult, performanceData));
233+
234+
string globalJsonState = string.Empty;
235+
if (TelemetryClient.Enabled)
236+
{
237+
// Get the global.json state to report in telemetry along with this command invocation.
238+
// We don't care about the actual SDK resolution, just the global.json information,
239+
// so just pass empty string as executable directory for resolution.
240+
NativeWrapper.SdkResolutionResult result = NativeWrapper.NETCoreSdkResolverNativeWrapper.ResolveSdk(string.Empty, Environment.CurrentDirectory);
241+
globalJsonState = result.GlobalJsonState;
242+
}
243+
244+
TelemetryEventEntry.SendFiltered(Tuple.Create(parseResult, performanceData, globalJsonState));
234245
PerformanceLogEventSource.Log.TelemetrySaveIfEnabledStop();
235246

236247
int exitCode;

src/Cli/dotnet/Telemetry/TelemetryFilter.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,40 @@ public IEnumerable<ApplicationInsightsEntryFormat> Filter(object objectToFilter)
2626
{
2727
var result = new List<ApplicationInsightsEntryFormat>();
2828
Dictionary<string, double> measurements = null;
29+
string globalJsonState = string.Empty;
2930
if (objectToFilter is Tuple<ParseResult, Dictionary<string, double>> parseResultWithMeasurements)
3031
{
3132
objectToFilter = parseResultWithMeasurements.Item1;
3233
measurements = parseResultWithMeasurements.Item2;
3334
measurements = RemoveZeroTimes(measurements);
3435
}
36+
else if (objectToFilter is Tuple<ParseResult, Dictionary<string, double>, string> parseResultWithMeasurementsAndGlobalJsonState)
37+
{
38+
objectToFilter = parseResultWithMeasurementsAndGlobalJsonState.Item1;
39+
measurements = parseResultWithMeasurementsAndGlobalJsonState.Item2;
40+
measurements = RemoveZeroTimes(measurements);
41+
globalJsonState = parseResultWithMeasurementsAndGlobalJsonState.Item3;
42+
}
3543

3644
if (objectToFilter is ParseResult parseResult)
3745
{
3846
var topLevelCommandName = parseResult.RootSubCommandResult();
3947
if (topLevelCommandName != null)
4048
{
49+
Dictionary<string, string> properties = new()
50+
{
51+
["verb"] = topLevelCommandName
52+
};
53+
if (!string.IsNullOrEmpty(globalJsonState))
54+
{
55+
properties["globalJson"] = globalJsonState;
56+
}
57+
4158
result.Add(new ApplicationInsightsEntryFormat(
4259
"toplevelparser/command",
43-
new Dictionary<string, string>()
44-
{{ "verb", topLevelCommandName }}
45-
, measurements
46-
));
60+
properties,
61+
measurements
62+
));
4763

4864
LogVerbosityForAllTopLevelCommand(result, parseResult, topLevelCommandName, measurements);
4965

src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ internal enum hostfxr_resolve_sdk2_result_key_t : int
8080
resolved_sdk_dir = 0,
8181
global_json_path = 1,
8282
requested_version = 2,
83+
global_json_state = 3,
8384
}
8485

8586
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

src/Resolvers/Microsoft.DotNet.NativeWrapper/SdkResolutionResult.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ public class SdkResolutionResult
2020
/// </summary>
2121
public string? RequestedVersion;
2222

23+
/// <summary>
24+
/// Result of the global.json search
25+
/// </summary>
26+
public string? GlobalJsonState;
27+
2328
/// <summary>
2429
/// True if a global.json was found but there was no compatible SDK, so it was ignored.
2530
/// </summary>
@@ -38,6 +43,9 @@ internal void Initialize(Interop.hostfxr_resolve_sdk2_result_key_t key, string v
3843
case Interop.hostfxr_resolve_sdk2_result_key_t.requested_version:
3944
RequestedVersion = value;
4045
break;
46+
case Interop.hostfxr_resolve_sdk2_result_key_t.global_json_state:
47+
GlobalJsonState = value;
48+
break;
4149
}
4250
}
4351
}

test/dotnet.Tests/TelemetryFilterTest.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ public void TopLevelCommandNameShouldBeSentToTelemetryWithPerformanceData()
5050
e.Measurement["Startup Time"] == 12345);
5151
}
5252

53+
[Fact]
54+
public void TopLevelCommandNameShouldBeSentToTelemetryWithGlobalJsonState()
55+
{
56+
string globalJsonState = "invalid_data";
57+
var parseResult = Parser.Parse(["build"]);
58+
TelemetryEventEntry.SendFiltered(Tuple.Create(parseResult, new Dictionary<string, double>(), globalJsonState));
59+
_fakeTelemetry.LogEntries.Should().Contain(e => e.EventName == "toplevelparser/command" &&
60+
e.Properties.ContainsKey("verb") &&
61+
e.Properties["verb"] == Sha256Hasher.Hash("BUILD") &&
62+
e.Measurement == null &&
63+
e.Properties.ContainsKey("globalJson") &&
64+
e.Properties["globalJson"] == Sha256Hasher.HashWithNormalizedCasing(globalJsonState));
65+
}
66+
5367
[Fact]
5468
public void TopLevelCommandNameShouldBeSentToTelemetryWithZeroPerformanceData()
5569
{

0 commit comments

Comments
 (0)