So I have been working on the dotnet-monitor tool team since inception and there is some really interesting underlying tech in the .NET Core CLR that makes it all tick, and I thought it might be helpful to talk about that here.

Diagnostics Port

The .NET Core runtime exposes a service endpoint that allows other processes to send diagnostic commands and receive responses over an IPC channel. The endpoint is referred to as a diagnostic port. You can send commands to the diagnostic port to capture memory dumps, GC Dumps, traces, metrics and command line info. The diagnostic port is supported across multiple OS’s by using Named Pipes on Windows and Unix Domain Sockets on Linux.

The runtime will create diagnostics ports in a well defined location on Windows and Linux (and macOS for that matter) in the following format:

  • Windows Named Pipe: \\.\pipe\dotnet-diagnostic-{pid}
  • Linux Unix Domain Socket: {temp}/dotnet-diagnostic-{pid}-{disambiguation_key}-socket

dotnet-monitor in Listen or Connect mode

Given that these diagnostics ports are in a well defined location we use dotnet-monitor (and other tools like dotnet-trace) to simply look in these folders and examine them for ports and we can use the REST API to issue commands that gather information or collect and store diagnostics artifacts. These diagnostics ports can be configured in either Connect or Listen mode.

Connect mode

dotnet-monitor gets put into Connect mode by default, and looks for diagnostics ports in the default location. The following JSON snippet is actually how you explicitly configure dotnet-monitor for Connect mode:

"DiagnosticPort": {
    "ConnectionMode": "Connect",
    "EndpointName": null
}

Listen mode

Alternatively dotnet-monitor can be configure to start in Listen mode, this incredibly useful as some important events (or problems) only occur during startup and thus might be missed by a tool like dotnet-monitor. We set dotnet-monitor into Listen mode as follows:

"DiagnosticPort": {
    "ConnectionMode": "Listen",
    "EndpointName": "/diag/port.sock"
    "MaxConnections": "10"
}

With dotnet monitor in Listen mode, you then configure your .NET processes to connect to dotnet monitor immediately even prior to managed code startup. You can do so by specifying the following environment variable on your .NET process in Linux as follows:

export DOTNET_DiagnosticPorts=/diag/port.sock,suspend

You could also do the equivalent in Windows by using PowerShell (note the naming convention for named pipes differs on Windows):

$env:DOTNET_DiagnosticPorts="dotnet-monitor-pipe,suspend"
Three massive white cranes on a water front contrasted against a blue sky. The sun is position behind the middle crane.


Comment Section

Comments are closed.