Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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 builddotnet packdotnet 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.jsonstate 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.
- Hashed project identifier for
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-profileor--no-launch-profilewas 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,
#:propertydirectives) - 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.