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  &nbsp;
    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" >}}