Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
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
29 changes: 3 additions & 26 deletions src/Microsoft.DotNet.Cli.Utils/CommandContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public static class Variables
public static readonly string AnsiPassThru = Prefix + "ANSI_PASS_THRU";
}

private static Lazy<bool> _verbose = new Lazy<bool>(() => GetBool(Variables.Verbose));
private static Lazy<bool> _ansiPassThru = new Lazy<bool>(() => GetBool(Variables.AnsiPassThru));
private static Lazy<bool> _verbose = new Lazy<bool>(() => Env.GetEnvironmentVariableAsBool(Variables.Verbose));
private static Lazy<bool> _ansiPassThru = new Lazy<bool>(() => Env.GetEnvironmentVariableAsBool(Variables.AnsiPassThru));

public static bool IsVerbose()
{
Expand All @@ -25,29 +25,6 @@ public static bool IsVerbose()
public static bool ShouldPassAnsiCodesThrough()
{
return _ansiPassThru.Value;
}

private static bool GetBool(string name, bool defaultValue = false)
{
var str = Environment.GetEnvironmentVariable(name);
if (string.IsNullOrEmpty(str))
{
return defaultValue;
}

switch (str.ToLowerInvariant())
{
case "true":
case "1":
case "yes":
return true;
case "false":
case "0":
case "no":
return false;
default:
return defaultValue;
}
}
}
}
}
5 changes: 5 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/Env.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,10 @@ public static string GetCommandPathFromRootPath(string rootPath, string commandN
{
return _environment.GetCommandPathFromRootPath(rootPath, commandName, extensions);
}

public static bool GetEnvironmentVariableAsBool(string name, bool defaultValue = false)
{
return _environment.GetEnvironmentVariableAsBool(name, defaultValue);
}
}
}
24 changes: 24 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/EnvironmentProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,29 @@ public string GetCommandPathFromRootPath(string rootPath, string commandName, IE

return GetCommandPathFromRootPath(rootPath, commandName, extensionsArr);
}

public bool GetEnvironmentVariableAsBool(string name, bool defaultValue)
{
var str = Environment.GetEnvironmentVariable(name);
if (string.IsNullOrEmpty(str))
{
return defaultValue;
}

switch (str.ToLowerInvariant())
{
case "true":
case "1":
case "yes":
return true;
case "false":
case "0":
case "no":
return false;
default:
return defaultValue;
}
}

}
}
2 changes: 2 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/IEnvironmentProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ public interface IEnvironmentProvider
string GetCommandPathFromRootPath(string rootPath, string commandName, params string[] extensions);

string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable<string> extensions);

bool GetEnvironmentVariableAsBool(string name, bool defaultValue);
}
}
13 changes: 13 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/ITelemetry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;

namespace Microsoft.DotNet.Cli.Utils
{
public interface ITelemetry
{
void TrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements);
}
}
17 changes: 17 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/Product.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Reflection;

namespace Microsoft.DotNet.Cli.Utils
{
public class Product
{
public static readonly string LongName = ".NET Command Line Tools";
public static readonly string Version = GetProductVersion();

private static string GetProductVersion()
{
var attr = typeof(Product).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
return attr?.InformationalVersion;
}
}
}
125 changes: 125 additions & 0 deletions src/Microsoft.DotNet.Cli.Utils/Telemetry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using Microsoft.ApplicationInsights;
using Microsoft.Extensions.PlatformAbstractions;
using System.Diagnostics;

namespace Microsoft.DotNet.Cli.Utils
{
public class Telemetry : ITelemetry
{
private bool _isInitialized = false;
private TelemetryClient _client = null;

private Dictionary<string, string> _commonProperties = null;
private Dictionary<string, double> _commonMeasurements = null;

private const string InstrumentationKey = "74cc1c9e-3e6e-4d05-b3fc-dde9101d0254";
private const string TelemetryOptout = "DOTNET_CLI_TELEMETRY_OPTOUT";
private const string OSVersion = "OS Version";
private const string OSPlatform = "OS Platform";
private const string RuntimeId = "Runtime Id";
private const string ProductVersion = "Product Version";

public Telemetry()
{
bool optout = Env.GetEnvironmentVariableAsBool(TelemetryOptout);

if (optout)

This comment was marked as spam.

This comment was marked as spam.

{
return;
}

try
{
_client = new TelemetryClient();
_client.InstrumentationKey = InstrumentationKey;
_client.Context.Session.Id = Guid.NewGuid().ToString();

var runtimeEnvironment = PlatformServices.Default.Runtime;
_client.Context.Device.OperatingSystem = runtimeEnvironment.OperatingSystem;

_commonProperties = new Dictionary<string, string>();
_commonProperties.Add(OSVersion, runtimeEnvironment.OperatingSystemVersion);
_commonProperties.Add(OSPlatform, runtimeEnvironment.OperatingSystemPlatform.ToString());
_commonProperties.Add(RuntimeId, runtimeEnvironment.GetRuntimeIdentifier());
_commonProperties.Add(ProductVersion, Product.Version);
_commonMeasurements = new Dictionary<string, double>();

_isInitialized = true;
}
catch (Exception)
{
// we dont want to fail the tool if telemetry fais. We should be able to detect abnormalities from data
// at the server end

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Debug.Fail("Exception during telemetry initialization");
}
}

public void TrackEvent(string eventName, IDictionary<string, string> properties, IDictionary<string, double> measurements)
{
if (!_isInitialized)

This comment was marked as spam.

This comment was marked as spam.

{
return;
}

Dictionary<string, double> eventMeasurements = GetEventMeasures(measurements);
Dictionary<string, string> eventProperties = GetEventProperties(properties);

try
{
_client.TrackEvent(eventName, eventProperties, eventMeasurements);
_client.Flush();
}
catch (Exception)
{
Debug.Fail("Exception during TrackEvent");
}
}


private Dictionary<string, double> GetEventMeasures(IDictionary<string, double> measurements)
{
Dictionary<string, double> eventMeasurements = new Dictionary<string, double>(_commonMeasurements);
if (measurements != null)
{
foreach (var measurement in measurements)
{
if (eventMeasurements.ContainsKey(measurement.Key))
{
eventMeasurements[measurement.Key] = measurement.Value;
}
else
{
eventMeasurements.Add(measurement.Key, measurement.Value);
}
}
}
return eventMeasurements;
}

private Dictionary<string, string> GetEventProperties(IDictionary<string, string> properties)
{
if (properties != null)
{
var eventProperties = new Dictionary<string, string>(_commonProperties);
foreach (var property in properties)
{
if (eventProperties.ContainsKey(property.Key))
{
eventProperties[property.Key] = property.Value;
}
else
{
eventProperties.Add(property.Key, property.Value);
}
}
return eventProperties;
}
else
{
return _commonProperties;
}
}
}
}
1 change: 1 addition & 0 deletions src/Microsoft.DotNet.Cli.Utils/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"warningsAsErrors": true
},
"dependencies": {
"Microsoft.ApplicationInsights": "2.0.0-rc1",
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100",
"NuGet.Versioning": "3.5.0-beta-1123",
Expand Down
35 changes: 24 additions & 11 deletions src/dotnet/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@ namespace Microsoft.DotNet.Cli
{
public class Program
{

public static int Main(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);

try
{
return ProcessArgs(args);
return Program.ProcessArgs(args, new Telemetry());
}
catch (CommandUnknownException e)
{
Expand All @@ -44,7 +43,7 @@ public static int Main(string[] args)

}

private static int ProcessArgs(string[] args)
internal static int ProcessArgs(string[] args, ITelemetry telemetryClient)
{
// CommandLineApplication is a bit restrictive, so we parse things ourselves here. Individual apps should use CLA.

Expand Down Expand Up @@ -117,22 +116,36 @@ private static int ProcessArgs(string[] args)
["test"] = TestCommand.Run
};

int exitCode;
Func<string[], int> builtIn;
if (builtIns.TryGetValue(command, out builtIn))
{
return builtIn(appArgs.ToArray());
exitCode = builtIn(appArgs.ToArray());
}
else
{
CommandResult result = Command.Create("dotnet-" + command, appArgs, FrameworkConstants.CommonFrameworks.NetStandardApp15)
.ForwardStdErr()
.ForwardStdOut()
.Execute();
exitCode = result.ExitCode;
}

return Command.Create("dotnet-" + command, appArgs, FrameworkConstants.CommonFrameworks.NetStandardApp15)
.ForwardStdErr()
.ForwardStdOut()
.Execute()
.ExitCode;
telemetryClient.TrackEvent(
command,
null,
new Dictionary<string, double>
{
["ExitCode"] = exitCode
});

return exitCode;

}

private static void PrintVersion()
{
Reporter.Output.WriteLine(HelpCommand.ProductVersion);
Reporter.Output.WriteLine(Product.Version);
}

private static void PrintInfo()
Expand All @@ -142,7 +155,7 @@ private static void PrintInfo()
var commitSha = GetCommitSha() ?? "N/A";
Reporter.Output.WriteLine();
Reporter.Output.WriteLine("Product Information:");
Reporter.Output.WriteLine($" Version: {HelpCommand.ProductVersion}");
Reporter.Output.WriteLine($" Version: {Product.Version}");
Reporter.Output.WriteLine($" Commit Sha: {commitSha}");
Reporter.Output.WriteLine();
var runtimeEnvironment = PlatformServices.Default.Runtime;
Expand Down
3 changes: 3 additions & 0 deletions src/dotnet/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("dotnet.Tests")]

This comment was marked as spam.

This comment was marked as spam.

14 changes: 3 additions & 11 deletions src/dotnet/commands/dotnet-help/HelpCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace Microsoft.DotNet.Tools.Help
{
public class HelpCommand
{
private const string ProductLongName = ".NET Command Line Tools";
private const string UsageText = @"Usage: dotnet [common-options] [command] [arguments]

Arguments:
Expand All @@ -29,13 +28,6 @@ run Compiles and immediately executes a .NET project
test Executes tests in a test project
repl Launch an interactive session (read, eval, print, loop)
pack Creates a NuGet package";
public static readonly string ProductVersion = GetProductVersion();

private static string GetProductVersion()
{
var attr = typeof(HelpCommand).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
return attr?.InformationalVersion;
}

public static int Run(string[] args)
{
Expand All @@ -58,10 +50,10 @@ public static void PrintHelp()

public static void PrintVersionHeader()
{
var versionString = string.IsNullOrEmpty(ProductVersion) ?
var versionString = string.IsNullOrEmpty(Product.Version) ?
string.Empty :
$" ({ProductVersion})";
Reporter.Output.WriteLine(ProductLongName + versionString);
$" ({Product.Version})";
Reporter.Output.WriteLine(Product.LongName + versionString);
}
}
}
Loading