github.com/grafana/pyroscope@v1.18.0/docs/sources/configure-client/language-sdks/dotnet.md (about) 1 --- 2 title: ".NET" 3 menuTitle: ".NET" 4 description: "Instrumenting .NET applications for continuous profiling." 5 weight: 40 6 aliases: 7 - /docs/phlare/latest/configure-client/language-sdks/dotnet/ 8 --- 9 10 # .NET 11 12 Our .NET Profiler is a powerful tool designed to enhance the performance analysis and optimization of .NET applications. It seamlessly integrates with Pyroscope, offering real-time insights into the resource usage and bottlenecks within your .NET codebase. This integration empowers developers to pinpoint inefficiencies, improve application speed, and ensure resource-efficient operation. 13 14 {{< admonition type="note" >}} 15 Refer to [Available profiling types](https://grafana.com/docs/pyroscope/<PYROSCOPE_VERSION>/configure-client/profile-types/) for a list of profile types supported by each language. 16 {{< /admonition >}} 17 18 ## Supported profiling types 19 20 The .NET Profiler supports the following profiling types: 21 22 * CPU 23 * Wall time 24 * Allocations 25 * Lock contention 26 * Exceptions 27 * Live heap (requires .NET 7+) 28 29 ### Compatibility 30 31 The only compatible operating system and architecture combination is Linux running on amd64 architecture. 32 33 Our .NET profiler works with the following .NET versions: 34 35 * .NET 6 36 * .NET 7 37 * .NET 8 38 39 40 ## Before you begin 41 42 To capture and analyze profiling data, you need either a hosted Pyroscope OSS server or a hosted [Pyroscope instance with Grafana Cloud Profiles](/products/cloud/profiles-for-continuous-profiling/) (requires a free Grafana Cloud account). 43 44 The Pyroscope server can be a local server for development or a remote server for production use. 45 46 ## Configure the .NET client 47 48 1. Obtain `Pyroscope.Profiler.Native.so` and `Pyroscope.Linux.ApiWrapper.x64.so` from the [latest tarball](https://github.com/pyroscope-io/pyroscope-dotnet/releases/): 49 50 ```bash 51 curl -s -L https://github.com/grafana/pyroscope-dotnet/releases/download/v0.13.0-pyroscope/pyroscope.0.13.0-glibc-x86_64.tar.gz | tar xvz -C . 52 ``` 53 54 Or copy them from the [latest docker image](https://hub.docker.com/r/pyroscope/pyroscope-dotnet/tags). We have `glibc` and `musl` versions: 55 ```dockerfile 56 COPY --from=pyroscope/pyroscope-dotnet:0.13.0-glibc /Pyroscope.Profiler.Native.so /dotnet/Pyroscope.Profiler.Native.so 57 COPY --from=pyroscope/pyroscope-dotnet:0.13.0-glibc /Pyroscope.Linux.ApiWrapper.x64.so /dotnet/Pyroscope.Linux.ApiWrapper.x64.so 58 ```` 59 60 2. Set the following required environment variables to enable profiler 61 ```shell 62 PYROSCOPE_APPLICATION_NAME=rideshare.dotnet.app 63 PYROSCOPE_SERVER_ADDRESS=http://localhost:4040 64 PYROSCOPE_PROFILING_ENABLED=1 65 CORECLR_ENABLE_PROFILING=1 66 CORECLR_PROFILER={BD1A650D-AC5D-4896-B64F-D6FA25D6B26A} 67 CORECLR_PROFILER_PATH=/dotnet/Pyroscope.Profiler.Native.so 68 LD_PRELOAD=/dotnet/Pyroscope.Linux.ApiWrapper.x64.so 69 LD_LIBRARY_PATH=/dotnet 70 ``` 71 72 {{< admonition type="note" >}} 73 The `LD_LIBRARY_PATH` environment variable should point to the directory containing the `Pyroscope.Profiler.Native.so` file. This ensures that the dynamic linker can locate the profiler's shared libraries at runtime. 74 {{< /admonition >}} 75 76 {{< admonition type="note" >}} 77 Since .NET version 8 the environment variable `DOTNET_EnableDiagnostics=0` (or its legacy equivalent `COMPlus_EnableDiagnostics=0`) will also disable the profiler. In order to get the previous behaviour (allowing profiling, but switch off IPC and Debugging) the following environment variables should be set instead: 78 79 ```shell 80 DOTNET_EnableDiagnostics=1 81 DOTNET_EnableDiagnostics_IPC=0 82 DOTNET_EnableDiagnostics_Debugger=0 83 DOTNET_EnableDiagnostics_Profiler=1 84 ``` 85 {{< /admonition >}} 86 87 ### .NET Profiler API 88 89 With a managed helper you can interact with the Pyroscope profiler from .NET runtime. You can add labels, turn on/off profiling types, and more. 90 91 To use it, first, add the Pyroscope dependency: 92 93 ```shell 94 dotnet add package Pyroscope 95 ``` 96 97 98 99 ### Add profiling labels to your application 100 101 You can add labels to the profiling data to filter the data in the UI. Common labels include: 102 * `hostname` 103 * `region` 104 * `team` 105 * `api_endpoint` 106 107 Create a `LabelSet` and wrap a piece of code with `Pyroscope.LabelsWrapper`. 108 109 ```cs 110 var labels = Pyroscope.LabelSet.Empty.BuildUpon() 111 .Add("key1", "value1") 112 .Build(); 113 Pyroscope.LabelsWrapper.Do(labels, () => 114 { 115 SlowCode(); 116 }); 117 ``` 118 119 Labels can be nested. For nesting LabelSets use `LabelSet.BuildUpon` on non-empty set. 120 ```cs 121 var labels = Pyroscope.LabelSet.Empty.BuildUpon() 122 .Add("key1", "value1") 123 .Build(); 124 Pyroscope.LabelsWrapper.Do(labels, () => 125 { 126 var labels2 = labels.BuildUpon() 127 .Add("key2", "value2") 128 .Build(); 129 Pyroscope.LabelsWrapper.Do(labels2, () => 130 { 131 SlowCode(); 132 }); 133 FastCode(); 134 }); 135 ``` 136 137 ### Dynamic control 138 139 It is possible to dynamically enable/disable specific profiling types. Profiling types have to be configured prior. 140 141 ```cs 142 // Enables or disables CPU/wall profiling dynamically. 143 // This function works in conjunction with the PYROSCOPE_PROFILING_CPU_ENABLED and 144 // PYROSCOPE_PROFILING_WALLTIME_ENABLED environment variables. If CPU/wall profiling is not 145 // configured, this function will have no effect. 146 Pyroscope.Profiler.Instance.SetCPUTrackingEnabled(enabled); 147 // Enables or disables allocation profiling dynamically. 148 // This function works in conjunction with the PYROSCOPE_PROFILING_ALLOCATION_ENABLED environment variable. 149 // If allocation profiling is not configured, this function will have no effect. 150 Pyroscope.Profiler.Instance.SetAllocationTrackingEnabled(enabled); 151 // Enables or disables contention profiling dynamically. 152 // This function works in conjunction with the PYROSCOPE_PROFILING_LOCK_ENABLED environment variable. 153 // If contention profiling is not configured, this function will have no effect. 154 Pyroscope.Profiler.Instance.SetContentionTrackingEnabled(enabled); 155 // Enables or disables exception profiling dynamically. 156 // This function works in conjunction with the PYROSCOPE_PROFILING_EXCEPTION_ENABLED environment variable. 157 // If exception profiling is not configured, this function will have no effect. 158 Pyroscope.Profiler.Instance.SetExceptionTrackingEnabled(enabled); 159 ``` 160 161 It is possible to dynamically change authorization credentials: 162 163 ```cs 164 // Set Basic authorization username and password. Clears any previous authorization credentials. 165 Pyroscope.Profiler.Instance.SetBasicAuth(basicAuthUser, BasicAuthPassword); 166 ``` 167 168 Here is a simple [example](https://github.com/grafana/pyroscope/blob/main/examples/language-sdk-instrumentation/dotnet/rideshare/example/Program.cs) exposing these APIs as HTTP endpoints. 169 170 ### Configuration options 171 172 | ENVIRONMENT VARIABLE | Type | DESCRIPTION | 173 |----------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------| 174 | PYROSCOPE_PROFILING_LOG_DIR | String | Sets the directory for .NET Profiler logs. Defaults to /var/log/pyroscope/. | 175 | PYROSCOPE_LABELS | String | Static labels to apply to an uploaded profile. Must be a list of key:value separated by commas such as: layer:api or team:intake. | 176 | PYROSCOPE_SERVER_ADDRESS | String | Address of the Pyroscope Server | 177 | PYROSCOPE_PROFILING_ENABLED | Boolean | If set to true, enables the .NET Profiler. Defaults to false. | 178 | PYROSCOPE_PROFILING_WALLTIME_ENABLED | Boolean | If set to false, disables the Wall time profiling. Defaults to false. | 179 | PYROSCOPE_PROFILING_CPU_ENABLED | Boolean | If set to false, disables the CPU profiling. Defaults to true. | 180 | PYROSCOPE_PROFILING_EXCEPTION_ENABLED | Boolean | If set to true, enables the Exceptions profiling. Defaults to false. | 181 | PYROSCOPE_PROFILING_ALLOCATION_ENABLED | Boolean | If set to true, enables the Allocations profiling. Defaults to false. | 182 | PYROSCOPE_PROFILING_LOCK_ENABLED | Boolean | If set to true, enables the Lock Contention profiling. Defaults to false. | 183 | PYROSCOPE_PROFILING_HEAP_ENABLED | Boolean | If set to true, enables the Live heap profiling. Requires .NET 7+. Defaults to false. | 184 | PYROSCOPE_BASIC_AUTH_USER | String | For HTTP Basic Authentication, use this to send profiles to authenticated server, for example Grafana Cloud | 185 | PYROSCOPE_BASIC_AUTH_PASSWORD | String | For HTTP Basic Authentication, use this to send profiles to authenticated server, for example Grafana Cloud | 186 | PYROSCOPE_TENANT_ID | String | Only needed if using multi-tenancy in Pyroscope. | 187 188 ## Send data to Pyroscope OSS or Grafana Cloud Profiles 189 190 To send profiling data from your .NET application, configure your environment for either Pyroscope OSS or Grafana Cloud Profiles using the following steps: 191 192 ```bash 193 export CORECLR_ENABLE_PROFILING=1 194 export CORECLR_PROFILER={BD1A650D-AC5D-4896-B64F-D6FA25D6B26A} 195 export CORECLR_PROFILER_PATH=/dotnet/Pyroscope.Profiler.Native.so 196 export LD_PRELOAD=/dotnet/Pyroscope.Linux.ApiWrapper.x64.so 197 export LD_LIBRARY_PATH=/dotnet 198 export PYROSCOPE_PROFILING_ENABLED=1 199 export PYROSCOPE_APPLICATION_NAME=example.dotnet.app 200 export PYROSCOPE_SERVER_ADDRESS=<URL> 201 # Use these environment variables to send data to Grafana Cloud Profiles 202 export PYROSCOPE_BASIC_AUTH_USER=<User> 203 export PYROSCOPE_BASIC_AUTH_PASSWORD=<Password> 204 # Optional Pyroscope tenant ID (only needed if using multi-tenancy). Not needed for Grafana Cloud. 205 # export PYROSCOPE_TENANT_ID=<TenantID> 206 ``` 207 208 To configure the .NET SDK to send data to Grafana Cloud Profiles or Pyroscope, replace the `<URL>` placeholder with the appropriate server URL. This could be the Grafana Cloud URL or your own custom Pyroscope server URL. 209 210 If you need to send data to Grafana Cloud, you'll have to configure HTTP Basic authentication. Replace `<User>` with your Grafana Cloud stack user and `<Password>` with your Grafana Cloud API key. 211 212 If your open source Pyroscope server has multi-tenancy enabled, you'll need to specify a tenant ID. Replace `<TenantID>` with your Pyroscope tenant ID. 213 214 ### Locate the URL, user, and password in Grafana Cloud Profiles 215 216 [//]: # 'Shared content for URl location in Grafana Cloud Profiles' 217 [//]: # 'This content is located in /pyroscope/docs/sources/shared/locate-url-pw-user-cloud-profiles.md' 218 219 {{< docs/shared source="pyroscope" lookup="locate-url-pw-user-cloud-profiles.md" version="latest" >}}