Edit

Share via


.NET SDK and .NET CLI telemetry

The .NET SDK includes a telemetry feature that collects usage data and sends it to Microsoft when you use .NET CLI commands. The usage data includes exception information when the .NET CLI crashes. The .NET CLI comes with the .NET SDK and is the set of verbs that enable you to build, test, and publish your .NET apps. Telemetry data helps the .NET team understand how the tools are used so they can be improved. Information on failures helps the team resolve problems and fix bugs.

The collected data is published in aggregate under the Creative Commons Attribution License. Some of the collected data is published at .NET CLI Telemetry Data.

Scope

dotnet has two functions: to run apps and to execute CLI commands. Telemetry isn't collected when using dotnet to start an application in the following format:

  • dotnet [path-to-app].dll

Telemetry is collected when using any of the .NET CLI commands, such as:

  • dotnet build
  • dotnet pack
  • dotnet run

How to opt out

The .NET SDK telemetry feature is enabled by default for Microsoft distributions of the SDK. To opt out of the telemetry feature, set the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to 1 or true.

The .NET SDK installer sends a single telemetry entry when a successful installation happens. To opt out, set the DOTNET_CLI_TELEMETRY_OPTOUT environment variable before you install the .NET SDK.

Important

To opt out after you start the installer: close the installer, set the environment variable, and then run the installer again with that value set.

Disclosure

The .NET SDK displays text similar to the following output when you first run one of the .NET CLI commands (for example, dotnet build). The text might vary slightly depending on the version of the SDK you're running. This "first run" experience is how Microsoft notifies you about data collection.

Telemetry
---------
The .NET tools collect usage data in order to help us improve your experience. The data is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

To disable this message and the .NET welcome message, set the DOTNET_NOLOGO environment variable to true. This variable has no effect on telemetry opt out.

Note

Breaking change: The behavior of telemetry messages written to stderr changed in recent versions of the .NET SDK. For more information, see dotnet CLI commands log non-command-relevant data to stderr.

Data points

The telemetry feature doesn't collect personal data, such as usernames or email addresses. It doesn't scan your code and doesn't extract project-level data, such as name, repository, or author. It doesn't extract the contents of any data files accessed or created by your apps, dumps of any memory occupied by your apps' objects, or the contents of the clipboard. The data is sent securely to Microsoft servers by using Azure Monitor technology. The data is held under restricted access and published under strict security controls from secure Azure Storage systems.

Protecting your privacy is important to Microsoft. If you suspect the telemetry is collecting sensitive data or the data is being insecurely or inappropriately handled, file an issue in the dotnet/sdk repository.

For more information about your privacy and personal data collected, see the Microsoft Privacy Statement.

The following tabs show the telemetry data captured by SDK version:

  • SDK version 10.0.100 and later:
    • Hashed project identifier for dotnet run.
    • Application type of either file-based app or project-based for dotnet run.
    • The launch profile name if specified for dotnet run.
    • Whether a launch profile was specified for dotnet run.
    • The launch settings configuration model used (if any) for dotnet run.
    • Number of SDKs used for dotnet run.
    • Number of PackageReferences for dotnet run.
    • Number of ProjectReferences for dotnet run.
    • Number of additional properties for file-based apps with dotnet run.
    • Whether MSBuild was used for file-based apps with dotnet run.
    • Whether Roslyn compiler was used for file-based apps with dotnet run.
    • The detected LLM agent name if the CLI was invoked from an LLM agent. For more information, see LLM detection.
    • Captures the global.json state at the time a command is invoked. The state is one of the following values: not_found, valid, invalid_json, or invalid_data.
    • Which MSBuild task factories are used to load and run tasks (including inline C# tasks, multithreaded-aware tasks, and out-of-process tasks), and how many tasks they execute.
    • Number of MSBuild tasks executed in TaskHosts versus tasks not executed in TaskHosts.

Collected options

Certain commands send extra data. A subset of commands sends the first argument:

Command First argument data sent
dotnet help <arg> The command help is being queried for.
dotnet new <arg> The template name (hashed).
dotnet add <arg> The word package or reference.
dotnet remove <arg> The word package or reference.
dotnet list <arg> The word package or reference.
dotnet sln <arg> The word add, list, or remove.
dotnet nuget <arg> The word delete, locals, or push.
dotnet workload <subcommand> <arg> The word install, update, list, search, uninstall, repair, restore and the workload name (hashed).
dotnet tool <subcommand> <arg> The word install, update, list, search, uninstall, run and the dotnet tool name (hashed).

A subset of commands sends selected options if they're used, along with their values:

Option Commands
--verbosity All commands
--language dotnet new
--configuration dotnet build, dotnet clean, dotnet publish, dotnet run, dotnet test
--framework dotnet build, dotnet clean, dotnet publish, dotnet run, dotnet test, dotnet vstest
--runtime dotnet build, dotnet publish
--platform dotnet vstest
--logger dotnet vstest
--sdk-package-version dotnet migrate

When the SDK fails to resolve a built-in command, any command resolver that successfully resolves the command sends a hash of the command name along with the name of the command resolver type.

Starting with .NET Core 2.1.100 SDK, the SDK hashes all these values except for --verbosity and --sdk-package-version.

Template engine telemetry

Starting with .NET Core 2.1.100 SDK, the dotnet new template instantiation command collects extra data for Microsoft-authored templates:

  • --framework
  • --auth

dotnet run telemetry

Starting with .NET SDK 10.0.100, the dotnet run command collects feature-based telemetry to help drive development and usage of file-based apps.

Telemetry for all dotnet run executions:

  • Application type (file-based or project-based)
  • Hashed project or file identifier
  • Number of SDKs used
  • Number of PackageReferences
  • Number of ProjectReferences
  • Launch profile usage (whether --launch-profile or --no-launch-profile was used)
  • Whether the launch profile is a default profile
  • Launch settings model applied, if any

Telemetry for file-based apps only:

  • Number of additional properties (for example, #:property directives)
  • Whether MSBuild was used for building
  • Whether the Roslyn compiler was used directly

Crash exception telemetry

If the .NET CLI or SDK crashes, it collects the name of the exception and stack trace of the CLI or SDK code. The .NET CLI collects this information to assess problems and improve the quality of the .NET SDK and CLI.

The .NET CLI collects information for CLI or SDK exceptions only, not exceptions in your application. The collected data contains the name of the exception and the stack trace. This stack trace is of CLI or SDK code.

The following example shows the kind of data that is collected:

System.IO.IOException
at System.ConsolePal.WindowsConsoleStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Write(Char[] buffer)
at System.IO.TextWriter.WriteLine()
at System.IO.TextWriter.SyncTextWriter.WriteLine()
at Microsoft.DotNet.Cli.Utils.Reporter.WriteLine()
at Microsoft.DotNet.Tools.Run.RunCommand.EnsureProjectIsBuilt()
at Microsoft.DotNet.Tools.Run.RunCommand.Execute()
at Microsoft.DotNet.Tools.Run.RunCommand.Run(String[] args)
at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, ITelemetry telemetryClient)
at Microsoft.DotNet.Cli.Program.Main(String[] args)

.NET contributors and anyone else running a version of the .NET SDK that they built themselves should consider the path to their SDK source code. If a crash occurs while using a .NET SDK that is a custom debug build or configured with custom build symbol files, the SDK source file path from the build machine is collected as part of the stack trace and isn't hashed.

Because of this, you shouldn't place custom builds of the .NET SDK in directories whose path names expose personal or sensitive information.

Continuous integration detection

To detect if the .NET CLI is running in a continuous integration environment, the .NET CLI checks for the presence and values of several well-known environment variables that common CI providers set.

The following list shows the environment variables and how the .NET CLI uses their values. The .NET CLI doesn't collect the value of any environment variable; it only uses the value to set a Boolean flag.

Variable(s) Provider Action
TF_BUILD Azure Pipelines Parse boolean value
GITHUB_ACTIONS GitHub Actions Parse boolean value
APPVEYOR Appveyor Parse boolean value
CI Many/Most Parse boolean value
TRAVIS Travis CI Parse boolean value
CIRCLECI Circle CI Parse boolean value
CODEBUILD_BUILD_ID, AWS_REGION Amazon Web Services CodeBuild Check if all are present and non-null
BUILD_ID, BUILD_URL Jenkins Check if all are present and non-null
BUILD_ID, PROJECT_ID Google Cloud Build Check if all are present and non-null
TEAMCITY_VERSION TeamCity Check if present and non-null
JB_SPACE_API_URL JetBrains Space Check if present and non-null

LLM detection

To detect if the .NET CLI is running in the context of an LLM agent, the .NET CLI checks for the presence and values of several environment variables that LLM agents and AI coding assistants set.

The following table shows the agent name, environment variable used for detection, and value of the agent type that's reported. The actual values of these environment variables aren't collected—they're only used to identify the agent type.

LLM agent Variable Value
GitHub Copilot GITHUB_COPILOT_CLI_MODE "copilot"
Claude Code CLAUDECODE "claude"
Cursor CURSOR_EDITOR "cursor"
Google Gemini GEMINI_CLI "gemini"

If the .NET CLI detects multiple agents, it concatenates the different agent values with a comma to produce the final value.

See also