Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added telemetry data point for extensions loaded during test discovery/run #3511

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void HandleDiscoveryComplete(DiscoveryCompleteEventArgs discoveryComplete
// TODO(copoiena): Writing telemetry twice is less than ideal.
// We first write telemetry data in the _requestData variable in the ParallelRunEventsHandler
// and then we write again here. We should refactor this code and write only once.
discoveryCompleteEventArgs.DiscoveredExtensions = TestExtensions.MergeDictionaries(
discoveryCompleteEventArgs.DiscoveredExtensions = TestExtensions.CreateMergedDictionary(
discoveryCompleteEventArgs.DiscoveredExtensions,
TestPluginCache.Instance.TestExtensions.GetCachedExtensions());

Expand Down Expand Up @@ -435,7 +435,7 @@ private string UpdateRawMessageWithTelemetryInfo(DiscoveryCompletePayload discov
// this merge a level above in order to be consistent, but that means we'd have to
// deserialize all raw messages no matter if telemetry is opted in or not and that
// would probably mean a performance hit.
discoveryCompletePayload.DiscoveredExtensions = TestExtensions.MergeDictionaries(
discoveryCompletePayload.DiscoveredExtensions = TestExtensions.CreateMergedDictionary(
discoveryCompletePayload.DiscoveredExtensions,
TestPluginCache.Instance.TestExtensions.GetCachedExtensions());

Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.TestPlatform.Client/Execution/TestRunRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ public void HandleTestRunComplete(TestRunCompleteEventArgs runCompleteArgs!!, Te
// TODO(copoiena): Writing telemetry twice is less than ideal.
// We first write telemetry data in the _requestData variable in the ParallelRunEventsHandler
// and then we write again here. We should refactor this code and write only once.
runCompleteArgs.DiscoveredExtensions = TestExtensions.MergeDictionaries(
runCompleteArgs.DiscoveredExtensions = TestExtensions.CreateMergedDictionary(
runCompleteArgs.DiscoveredExtensions,
TestPluginCache.Instance.TestExtensions.GetCachedExtensions());

Expand Down Expand Up @@ -611,7 +611,7 @@ private string UpdateRawMessageWithTelemetryInfo(TestRunCompletePayload testRunC
// this merge a level above in order to be consistent, but that means we'd have to
// deserialize all raw messages no matter if telemetry is opted in or not and that
// would probably mean a performance hit.
testRunCompletePayload.TestRunCompleteArgs.DiscoveredExtensions = TestExtensions.MergeDictionaries(
testRunCompletePayload.TestRunCompleteArgs.DiscoveredExtensions = TestExtensions.CreateMergedDictionary(
testRunCompletePayload.TestRunCompleteArgs.DiscoveredExtensions,
TestPluginCache.Instance.TestExtensions.GetCachedExtensions());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ internal Dictionary<string, TPluginInfo> GetTestExtensions<TPluginInfo, TExtensi
TestExtensions.GetTestExtensionCache<TPluginInfo>(),
extensionAssembly);

if (extensions != null && extensions.Count > 0)
if (extensions?.Count > 0)
{
return extensions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public class TestExtensions
/// <returns>
/// A dictionary representing the merger between the two input dictionaries.
/// </returns>
internal static Dictionary<string, HashSet<string>> MergeDictionaries(
internal static Dictionary<string, HashSet<string>> CreateMergedDictionary(
Dictionary<string, HashSet<string>> first,
Dictionary<string, HashSet<string>> second)
{
Expand All @@ -123,7 +123,7 @@ internal static Dictionary<string, HashSet<string>> MergeDictionaries(
}

// Copy all the keys in the first dictionary into the resulting dictionary.
var resultMap = new Dictionary<string, HashSet<string>>(first);
var result = new Dictionary<string, HashSet<string>>(first);

foreach (var kvp in second)
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
{
Expand All @@ -135,34 +135,34 @@ internal static Dictionary<string, HashSet<string>> MergeDictionaries(

// If there's no key-value pair entry in the "destination" dictionary for the current
// key in the "source" dictionary, we copy the "source" set wholesale.
if (!resultMap.ContainsKey(kvp.Key))
if (!result.ContainsKey(kvp.Key))
{
resultMap.Add(kvp.Key, kvp.Value);
result.Add(kvp.Key, kvp.Value);
continue;
}

// Getting here means there's already an entry for the "source" key in the "destination"
// dictionary which means we need to copy individual set elements from the "source" set
// to the "destination" set.
resultMap[kvp.Key] = MergeSets(resultMap[kvp.Key], kvp.Value);
result[kvp.Key] = MergeSets(result[kvp.Key], kvp.Value);
}

return resultMap;
return result;
}

/// <summary>
/// Add extension-related telemetry.
/// </summary>
///
/// <param name="metrics">A collection representing the telemetry data.</param>
/// <param name="extensionMap">The input extension collection.</param>
/// <param name="extensions">The input extension collection.</param>
internal static void AddExtensionTelemetry(
IDictionary<string, object> metrics,
Dictionary<string, HashSet<string>> extensionMap)
Dictionary<string, HashSet<string>> extensions)
{
metrics.Add(
TelemetryDataConstants.DiscoveredExtensions,
SerializeExtensionMap(extensionMap));
SerializeExtensionDictionary(extensions));
}

/// <summary>
Expand Down Expand Up @@ -385,21 +385,21 @@ internal void SetTestExtensionsCacheStatusToTrue<TPluginInfo>() where TPluginInf
/// Gets the cached extensions for the current process.
/// </summary>
///
/// <returns>A map representing the cached extensions for the current process.</returns>
/// <returns>A dictionary representing the cached extensions for the current process.</returns>
internal Dictionary<string, HashSet<string>> GetCachedExtensions()
{
var extensionMap = new Dictionary<string, HashSet<string>>();
var extensions = new Dictionary<string, HashSet<string>>();

// Write all "known" cached extension.
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
AddCachedExtensionToExtensionMap(extensionMap, "TestDiscoverers", TestDiscoverers?.Values.ToList());
AddCachedExtensionToExtensionMap(extensionMap, "TestExecutors", TestExecutors?.Values.ToList());
AddCachedExtensionToExtensionMap(extensionMap, "TestExecutors2", TestExecutors2?.Values.ToList());
AddCachedExtensionToExtensionMap(extensionMap, "TestSettingsProviders", TestSettingsProviders?.Values.ToList());
AddCachedExtensionToExtensionMap(extensionMap, "TestLoggers", TestLoggers?.Values.ToList());
AddCachedExtensionToExtensionMap(extensionMap, "TestHosts", TestHosts?.Values.ToList());
AddCachedExtensionToExtensionMap(extensionMap, "DataCollectors", DataCollectors?.Values.ToList());

return extensionMap;
AddCachedExtensionToDictionary(extensions, "TestDiscoverers", TestDiscoverers?.Values.ToList());
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
AddCachedExtensionToDictionary(extensions, "TestExecutors", TestExecutors?.Values.ToList());
AddCachedExtensionToDictionary(extensions, "TestExecutors2", TestExecutors2?.Values.ToList());
AddCachedExtensionToDictionary(extensions, "TestSettingsProviders", TestSettingsProviders?.Values.ToList());
AddCachedExtensionToDictionary(extensions, "TestLoggers", TestLoggers?.Values.ToList());
AddCachedExtensionToDictionary(extensions, "TestHosts", TestHosts?.Values.ToList());
AddCachedExtensionToDictionary(extensions, "DataCollectors", DataCollectors?.Values.ToList());

return extensions;
}

/// <summary>
Expand Down Expand Up @@ -485,24 +485,25 @@ private void SetTestExtensionCache<TPluginInfo>(Dictionary<string, TPluginInfo>
}
}

private void AddCachedExtensionToExtensionMap<T>(
Dictionary<string, HashSet<string>> extensionMap,
private void AddCachedExtensionToDictionary<T>(
Dictionary<string, HashSet<string>> extensionDict,
string extensionType,
IList<T> extensions) where T : TestPluginInformation
IEnumerable<T> extensions)
where T : TestPluginInformation
{
if (extensions == null)
{
return;
}

extensionMap.Add(extensionType, new HashSet<string>(extensions.Select(e => e.IdentifierData)));
extensionDict.Add(extensionType, new HashSet<string>(extensions.Select(e => e.IdentifierData)));
}

private static string SerializeExtensionMap(IDictionary<string, HashSet<string>> extensionMap)
private static string SerializeExtensionDictionary(IDictionary<string, HashSet<string>> extensions)
{
StringBuilder sb = new();

foreach (var kvp in extensionMap)
foreach (var kvp in extensions)
{
if (kvp.Value?.Count > 0)
{
Expand All @@ -515,12 +516,14 @@ private static string SerializeExtensionMap(IDictionary<string, HashSet<string>>

private static HashSet<string> MergeSets(HashSet<string> firstSet, HashSet<string> secondSet)
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
{
var mergedSet = new HashSet<string>(firstSet);

// No need to worry about duplicates as the set implementation handles this already.
foreach (var key in secondSet)
{
firstSet.Add(key);
mergedSet.Add(key);
}

return firstSet;
return mergedSet;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public ParallelDiscoveryDataAggregator()
IsAborted = false;
TotalTests = 0;
_metricsAggregator = new ConcurrentDictionary<string, object>();
DiscoveredExtensions = new Dictionary<string, HashSet<string>>();
DiscoveredExtensions = new();
}

/// <summary>
Expand Down Expand Up @@ -111,7 +111,7 @@ public void Aggregate(
TotalTests += totalTests;

// Aggregate the discovered extensions.
DiscoveredExtensions = TestExtensions.MergeDictionaries(DiscoveredExtensions, discoveredExtensions);
DiscoveredExtensions = TestExtensions.CreateMergedDictionary(DiscoveredExtensions, discoveredExtensions);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public void Aggregate(
}

// Aggregate the discovered extensions.
DiscoveredExtensions = TestExtensions.MergeDictionaries(DiscoveredExtensions, discoveredExtensions);
DiscoveredExtensions = TestExtensions.CreateMergedDictionary(DiscoveredExtensions, discoveredExtensions);
}
}

Expand Down