> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/web-application-and-api-protection-waap/installation/tracing-agent/language-agents/net-agent.md).

# .NET agent

The Traceable .NET agent is an in-app tracing agent that collects telemetry data from your .NET application and forwards it to the Traceable Platform Agent (TPA). The TPA then processes and sends this data to the Traceable platform for security analysis, observability, and runtime protection.

This topic walks you through the support matrix, prerequisites, installation steps, configuration options, upgrade and uninstallation procedures, and troubleshooting guidelines.

***

## Before You Begin

Ensure the following requirements are met before installing the .NET agent:

* You are using \*\*.\*\*NET Core 6, 7, 8, and 9.
* Your application is not built on .NET Framework. .NET Framework-based applications are not supported.
* You have access to modify environment variables or update the application startup files.
* You have access to the deployed Traceable Platform Agent (TPA) endpoint (for example, `http://agent.traceableai:5442`). For a TLS connection, the port would be `5443`.
* You have permission to install NuGet packages (for manual instrumentation).
* The underlying OS is supported if you plan to use blocking or sampling features.

***

## Support Matrix

| **Component** | **Versions Supported**            | **Notes**                             |
| ------------- | --------------------------------- | ------------------------------------- |
| ASP.NET Core  | 6, 7, 8, 9                        | Full support for tracing and blocking |
| gRPC (Core)   | 2.53.0 and later                  | Supports gRPC server instrumentation  |
| HttpClient    | All .NET Core 6, 7, 8, 9 versions | Supported by default                  |
| RestSharp     | Same as HttpClient                | Wrapper over HttpClient               |

### Support for request blocking

Traceable provides request-blocking support on the following operating system versions. You can install the Traceable .NET agent on other operating systems and continue to collect telemetry data. However, request blocking is not supported on any other operating system.

* Debian 10+
* Ubuntu 18.04+
* Amazon Linux 2+
* CentOS 7+

{% hint style="info" %}
**Note**

.NET Framework is not supported.
{% endhint %}

***

## Installation Options and Steps

Traceable provides two options for instrumenting your .NET application. Choose the method that best suits your deployment setup and control preferences.

### Option A – Auto Instrumentation

Auto-instrumentation allows you to trace your application without modifying the code. This method works by setting environment variables that hook into the application startup.

#### Steps

1. **Download the agent binaries for your runtime**

   ```language-bash
   curl -L https://downloads.traceable.ai/agent/dotnet/latest/<rid>/<framework>/dotnetagent-<rid>-<framework>.zip -o dotnet-traceable.zip
   ```

   Replace `<rid>` with your Runtime Identifier (for example, `win-x64`, `linux-x64`) and `<framework>` with your .NET version (for example, `net8.0`).

   This command fetches the pre-compiled Traceable .NET agent specific to your environment.
2. **Extract the contents of the downloaded ZIP file**

   ```language-bash
   unzip dotnet-traceable.zip && cd traceable
   ```

   This unzips the agent package into a folder named traceable, which contains binaries and setup scripts.
3. **Run the installation script to set the required environment variables**
   * On **Windows**:

     ```language-powershell
     .\install.ps1
     ```
   * On **Linux**:

     ```language-bash
     ./install.sh
     ```

     These scripts configure three essential environment variables that enable the agent to hook into .NET runtime:
   * `DOTNET_STARTUP_HOOKS`: Specifies the startup hook assembly.
   * `DOTNET_SHARED_STORE`: Points to shared dependencies for auto instrumentation.
   * `DOTNET_ADDITIONAL_DEPS`: Includes additional dependency declarations.

     **Example values**:

     ```language-plaintext
     DOTNET_STARTUP_HOOKS=<path>/traceable/net/Traceable.StartupHook.dll
     DOTNET_SHARED_STORE=<path>/traceable/store/
     DOTNET_ADDITIONAL_DEPS=<path>/traceable/additionalDeps/
     ```
4. **Restart your application**

   The .NET runtime reads the environment variables during application startup. A restart is required for instrumentation to begin.

{% hint style="info" %}
**Important:**\
The install script modifies environment variables only in the current terminal session. To persist these changes across reboots or systemd services, add them to your system profile, `.bashrc`, `.systemd` unit file, or equivalent.
{% endhint %}

***

### Option B – Manual Instrumentation (SDK-based)

Manual instrumentation provides more control and requires a minor code change. This method is preferred if you are already managing dependencies via `csproj`.

#### Steps

1. Add the Traceable .NET SDK package

   ```language-bash
   dotnet add package Traceable.Agent
   ```

   This command pulls the Traceable SDK from NuGet and adds it to your project file (.csproj).
2. Register the Traceable agent in your `Startup.cs` or `Program.cs`

   For example in `Startup.cs`,

   ```language-csharp
   using System.Text;
   public class Startup
   {
       // ... Rest of the code
       public void ConfigureServices(IServiceCollection services)
       {
           services.AddControllers();
           services.AddTraceableAgent(); // only change for Traceable Agent
       }
       // ... Rest of the code
       
   }
   ```

   This enables Traceable to start capturing telemetry and context-aware request data.
3. (Optional) If you want to control the position of Traceable’s Middleware, then `Startup.cs` or `Program.cs` file can be updated like

   Do either **Step 2** or **Step 3**, not both.

   ```language-csharp
   using System.Text;
   using Traceable.Instrumentation.AspNetCore.Implementation;
   public class Startup
   {
       // ... Rest of the code
       public void ConfigureServices(IServiceCollection services)
       {
           services.AddControllers();
           services.InitTraceableAgent(); //1st change for Traceable Agent
       }
       // ... Rest of the code
       
       <configure all the middlewares required before>    
       app.UseMiddleware<TraceableMiddleware>(); //2nd change for Traceable Agent
       <configure all the middlewares required after>    
   }
   ```

   You can choose whether Traceable runs before or after specific middleware (for example, CORS, Authentication), depending on what you want to capture.

***

## Configuration Variables

You can configure the .NET agent using either a `config.yaml` file or environment variables. Environment variables always take precedence over values set in the YAML file.

{% hint style="info" %}
**Note:**\
The .NET agent supports configuration through either a YAML file (`config.yaml`) or environment variables. This applies to both Auto and Manual instrumentation methods.

* To use a YAML file, set the environment variable `TA_CONFIG_FILE` to point to the config file path.
* Any environment variable will override the corresponding value in the YAML file.
  {% endhint %}

<details>

<summary>Below is the complete list of supported configuration options:</summary>

| **Config File Option**               | **Environment Variable**                       | **Description**                                                                      | **Default Value**                               |
| ------------------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------- |
| -                                    | `TA_CONFIG_FILE`                               | Path to `config.yaml` file used for configuration. Enables file-based configuration. | -                                               |
| `service_name`                       | `TA_SERVICE_NAME`                              | Service name shown in Traceable dashboard                                            | `dotnetagent`                                   |
| `environment`                        | `TA_ENVIRONMENT`                               | Environment name (e.g., dev, staging, prod)                                          | `""`                                            |
| `reporting.secure`                   | `TA_REPORTING_SECURE`                          | Use HTTPS to send spans to TPA                                                       | `false`                                         |
| `reporting.endpoint`                 | `TA_REPORTING_ENDPOINT`                        | URL of Traceable Platform Agent                                                      | `http://localhost:5442`                         |
| `reporting.trace_reporter_type`      | `TA_REPORTING_TRACE_REPORTER_TYPE`             | Reporter type (`OTLP` or `OTLP_HTTP`)                                                | `OTLP`                                          |
| `reporting.cert_file`                | `TA_REPORTING_CERT_FILE`                       | TLS certificate path for HTTPS reporting                                             | `""`                                            |
| `reporting.token`                    | `TA_REPORTING_TOKEN`                           | Token used to authenticate with TPA                                                  |                                                 |
| `data_capture.http_headers.request`  | `TA_DATA_CAPTURE_HTTP_HEADERS_REQUEST`         | Capture HTTP request headers                                                         | `true`                                          |
| `data_capture.http_headers.response` | `TA_DATA_CAPTURE_HTTP_HEADERS_RESPONSE`        | Capture HTTP response headers                                                        | `true`                                          |
| `data_capture.http_body.request`     | `TA_DATA_CAPTURE_HTTP_BODY_REQUEST`            | Capture HTTP request body                                                            | `true`                                          |
| `data_capture.http_body.response`    | `TA_DATA_CAPTURE_HTTP_BODY_RESPONSE`           | Capture HTTP response body                                                           | `true`                                          |
| `data_capture.rpc_metadata.request`  | `TA_DATA_CAPTURE_RPC_METADATA_REQUEST`         | Capture RPC request metadata                                                         | `true`                                          |
| `data_capture.rpc_metadata.response` | `TA_DATA_CAPTURE_RPC_METADATA_RESPONSE`        | Capture RPC response metadata                                                        | `true`                                          |
| `data_capture.rpc_body.request`      | `TA_DATA_CAPTURE_RPC_BODY_REQUEST`             | Capture RPC request body                                                             | `true`                                          |
| `data_capture.rpc_body.response`     | `TA_DATA_CAPTURE_RPC_BODY_RESPONSE`            | Capture RPC response body                                                            | `true`                                          |
| `remote.enabled`                     | `TA_REMOTE_CONFIG_ENABLED`                     | Enable remote config fetching from TPA                                               | `true`                                          |
| `remote.endpoint`                    | `TA_REMOTE_CONFIG_ENDPOINT`                    | Remote config endpoint                                                               | `localhost:5442`                                |
| `remote.poll_period_seconds`         | `TA_REMOTE_CONFIG_POLL_PERIOD_SECONDS`         | Polling interval in seconds                                                          | `30`                                            |
| `remote.cert_file`                   | `TA_REMOTE_CONFIG_CERT_FILE`                   | TLS certificate for remote config                                                    | `""`                                            |
| `remote.grpc_max_call_recv_msg_size` | `TA_REMOTE_CONFIG_GRPC_MAX_CALL_RECV_MSG_SIZE` | Max gRPC response size (bytes)                                                       | `33554432`                                      |
| `remote.use_secure_connection`       | `TA_REMOTE_CONFIG_USE_SECURE_CONNECTION`       | Use OS truststore for cert validation                                                | `false`                                         |
| `blocking.enabled`                   | `TA_BLOCKING_CONFIG_ENABLED`                   | Enable blocking functionality                                                        | `true`                                          |
| `blocking.evaluate_body`             | `TA_BLOCKING_CONFIG_EVALUATE_BODY`             | Evaluate request/response body for blocking                                          | `true`                                          |
| `blocking.skip_internal_request`     | `TA_BLOCKING_CONFIG_SKIP_INTERNAL_REQUEST`     | Skip blocking for internal IPs                                                       | `true`                                          |
| `blocking.max_recursion_depth`       | `TA_BLOCKING_CONFIG_MAX_RECURSION_DEPTH`       | Max recursion depth for blocking rules                                               | `20`                                            |
| `blocking.modsecurity.enabled`       | `TA_BLOCKING_CONFIG_MODSECURITY_ENABLED`       | Enable ModSecurity integration                                                       | `true`                                          |
| `blocking.region.enabled`            | `TA_BLOCKING_CONFIG_REGION_ENABLED`            | Enable region-based blocking                                                         | `true`                                          |
| `blocking.response_status_code`      | `TA_BLOCKING_CONFIG_RESPONSE_STATUS_CODE`      | Status code returned when blocked                                                    | `403`                                           |
| `blocking.response_message`          | `TA_BLOCKING_CONFIG_RESPONSE_MESSAGE`          | Message returned in blocked response                                                 | `Access Forbidden`                              |
| `logging.log_mode`                   | `TA_LOGGING_MODE`                              | Logging mode: `None`, `Stdout`, or `File`                                            | `Stdout`                                        |
| `logging.log_level`                  | `TA_LOGGING_LEVEL`                             | Logging level: `Trace`, `Debug`, `Info`, etc.                                        | `Info`                                          |
| `logging.log_file.max_files`         | `TA_LOGGING_LOG_FILE_MAX_FILES`                | Max number of rotated log files                                                      | `3`                                             |
| `logging.log_file.max_file_size`     | `TA_LOGGING_LOG_FILE_MAX_FILE_SIZE`            | Max size of each log file (bytes)                                                    | `10485760`                                      |
| `logging.log_file.file_path`         | `TA_LOGGING_LOG_FILE_FILE_PATH`                | Path to store log files                                                              | `/var/traceable/log/libtraceable-javaagent.log` |
| `sampling.enabled`                   | `TA_SAMPLING_ENABLED`                          | Enable server-side request sampling                                                  | `true`                                          |

</details>

Following is a sample `config.yaml` file:

```language-yaml
export TA_ENVIRONMENT="production"
export TA_SERVICE_NAME="example-service-name"
export TA_REPORTING_ENDPOINT="<http://agent.traceableai:5442>"
export TA_REPORTING_TRACE_REPORTER_TYPE="Otlp"
export TA_BLOCKING_CONFIG_ENABLED=true
export TA_REMOTE_CONFIG_ENDPOINT=agent.traceableai:5442
```

{% hint style="info" %}
**Info:** If you want to use TLS communication between the Traceable Platform Agent (TPA) and the .NET agent, you must use the `OTLP_HTTP` reporting type. This is because OpenTelemetry for .NET does not support TLS over OTLP/gRPC.

* For `config.yaml`:

  ```language-plaintext
  reporting:
    trace_reporter_type: OTLP_HTTP
  ```
* For environment variable:

  ```language-plaintext
  TA_REPORTING_TRACE_REPORTER_TYPE=OtlpHttp
  ```

The TPA endpoint will also need to change to a secure URL, for example: `https://agent.traceableai:5443/v1/traces`
{% endhint %}

***

## Upgrade

To upgrade to the latest version of the .NET agent:

* **Auto instrumentation**: Download the latest binary package and re-run the `install.ps1` or `install.sh` script.
* **Manual instrumentation**: Update the version in your `.csproj` file or run:

  ```language-bash
  dotnet add package Traceable.Agent -v <DESIRED_VERSION>
  ```

  Then execute:

  ```language-bash
  dotnet restore
  ```

***

## Uninstall

* **Manual instrumentation**:

  ```language-bash
  dotnet remove package Traceable.Agent
  ```

  Remove any related code (such as `AddTraceableAgent`) from `Startup.cs` or `Program.cs`.
* **Auto instrumentation**:\
  Delete the installed binaries and remove related environment variables from your shell or system configuration.

***

## Troubleshoot

If no data appears in the Traceable platform after setup:

* Check if logs are being generated. Traceable logs are written to the application logger or the `stdout`.
* Verify the platform agent endpoint is reachable.
* Look for startup logs confirming agent initialization.

### Common Issues

| **Problem**                  | **Troubleshooting Tip**                                              |
| ---------------------------- | -------------------------------------------------------------------- |
| No response body captured    | Ensure your app sets `Content-Type: application/json` on responses.  |
| No request body captured     | Ensure incoming requests include a `Content-Type` header.            |
| Status code not reported     | Make sure the app returns an explicit HTTP status code.              |
| Env variables not persisting | Add them to `.bashrc`, `.profile`, or systemd service configuration. |
