File: Telemetry\TopLevelCommandNameAndOptionToLog.cs
Web Access
Project: src\src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine;
using System.CommandLine.Parsing;
using Microsoft.DotNet.Cli.Extensions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Utils.Extensions;

namespace Microsoft.DotNet.Cli.Telemetry;

internal class TopLevelCommandNameAndOptionToLog(HashSet<string> topLevelCommandName, HashSet<string> optionsToLog) : IParseResultLogRule
{
    private HashSet<string> _topLevelCommandName { get; } = topLevelCommandName;
    private HashSet<string> _optionsToLog { get; } = optionsToLog;

    public List<TelemetryEntryFormat> AllowList(ParseResult parseResult)
    {
        var topLevelCommandName = parseResult.RootSubCommandResult();
        var result = new List<TelemetryEntryFormat>();
        foreach (var optionName in _optionsToLog)
        {
            if (_topLevelCommandName.Contains(topLevelCommandName)
                && parseResult.GetResult(optionName) is OptionResult optionResult
                && !parseResult.Errors.Any(error => error.SymbolResult == optionResult)
                && optionResult.GetValueOrDefault<object>() is object optionValue
                && optionValue is not null)
            {
                result.Add(new TelemetryEntryFormat(
                    "sublevelparser/command",
                    new Dictionary<string, string?>
                    {
                        { "verb", topLevelCommandName},
                        { optionName.RemovePrefix(), Stringify(optionValue) }
                    }));
            }
        }
        return result;
    }

    /// <summary>
    /// We're dealing with untyped payloads here, so we need to handle arrays vs non-array values
    /// </summary>
    private static string? Stringify(object value)
    {
        if (value is null)
        {
            return null;
        }
        if (value is IEnumerable<string> enumerable)
        {
            return string.Join(";", enumerable);
        }
        if (value is IEnumerable<object> enumerableOfObjects)
        {
            return string.Join(";", enumerableOfObjects);
        }
        if (value is object[] arr)
        {
            return string.Join(";", arr);
        }
        return value.ToString();
    }
}