{"id":28715,"date":"2020-06-23T10:13:00","date_gmt":"2020-06-23T17:13:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=28715"},"modified":"2021-05-20T07:21:02","modified_gmt":"2021-05-20T14:21:02","slug":"introducing-dotnet-monitor","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/introducing-dotnet-monitor\/","title":{"rendered":"Introducing dotnet-monitor, an experimental tool"},"content":{"rendered":"<p><code>dotnet-monitor<\/code> is an experimental tool that makes it easier to get access to diagnostics information in a dotnet process.<\/p>\n<p>When running a dotnet application differences in diverse local and production environments can make collecting diagnostics artifacts (e.g., logs, traces, process dumps) challenging. <code>dotnet-monitor<\/code> aims to simplify the process by exposing a consistent REST API regardless of where your application is run.<\/p>\n<p>This blog post details how to get started with <code>dotnet-monitor<\/code> and covers the following:<\/p>\n<ol>\n<li>How to setup <code>dotnet-monitor<\/code><\/li>\n<li>What diagnostics artifacts can be collected; and<\/li>\n<li>How to collect each of the artifacts<\/li>\n<\/ol>\n<h2 id=\"tour-of-dotnet-monitor\">Tour of dotnet-monitor<\/h2>\n<h3 id=\"setup-dotnet-monitor-\">Setup <code>dotnet-monitor<\/code><\/h3>\n<p><code>dotnet-monitor<\/code> will be made available via two different distribution mechanism:<\/p>\n<ol>\n<li>As a .NET Core global tool; and<\/li>\n<li>As a container image available via the Microsoft Container Registry (MCR)<\/li>\n<\/ol>\n<p>The setup instructions for <code>dotnet-monitor<\/code> vary based on the target environment. The following section covers some common environments.<\/p>\n<p>In the default configuration <code>dotnet-monitor<\/code> binds to two different groups of URLs. The URLs controlled via the <code>--urls<\/code> parameter (defaults to <a href=\"http:\/\/localhost:52323\">http:\/\/localhost:52323<\/a>) expose all the collection endpoints. The URLs controlled via the <code>--metricUrls<\/code> parameter (defaults to <a href=\"http:\/\/localhost:52325\">http:\/\/localhost:52325<\/a>) only expose the <code>\/metrics<\/code> endpoint. Since diagnostics artifacts such as logs, dumps, and traces can leak sensitive information about the application, it is <strong>strongly recommended<\/strong> that you do not publicly expose these endpoints.<\/p>\n<h4 id=\"local-machine\">Local Machine<\/h4>\n<p>To get started with <code>dotnet-monitor<\/code> locally, you will need to have <a href=\"https:\/\/dotnet.microsoft.com\/download\">.NET Core<\/a> installed on your machine. You can then install<code>dotnet-monitor<\/code> as a global tool using the following command:<\/p>\n<pre><code class=\"lang-bash\">dotnet tool install -g dotnet-monitor --<span class=\"hljs-built_in\">add<\/span>-<span class=\"hljs-keyword\">source<\/span> http<span class=\"hljs-variable\">s:<\/span>\/\/dnceng.pkgs.visualstudio.<span class=\"hljs-keyword\">com<\/span>\/public\/_packaging\/dotnet-tools\/nuget\/v3\/<span class=\"hljs-built_in\">index<\/span>.json --<span class=\"hljs-keyword\">version<\/span> <span class=\"hljs-number\">5.0<\/span>.<span class=\"hljs-number\">0<\/span>-preview.*\r\n<\/code><\/pre>\n<p>Once installed you can run <code>dotnet-monitor<\/code> via the following command:<\/p>\n<pre><code class=\"lang-bash\">dotnet<span class=\"hljs-built_in\"> monitor <\/span>collect\r\n<\/code><\/pre>\n<h4 id=\"running-in-docker\">Running in Docker<\/h4>\n<p>When consuming <code>dotnet-monitor<\/code> as a container image, it can be pulled from <a href=\"https:\/\/hub.docker.com\/_\/microsoft-dotnet-nightly-monitor\/\">MCR<\/a> using the following command:<\/p>\n<pre><code class=\"lang-bash\">docker pull mcr<span class=\"hljs-selector-class\">.microsoft<\/span><span class=\"hljs-selector-class\">.com<\/span>\/dotnet\/nightly\/monitor:<span class=\"hljs-number\">5.0<\/span>.<span class=\"hljs-number\">0<\/span>-preview.1\r\n<\/code><\/pre>\n<p>Once you have the image pulled locally, you will need to share a volume mount between your application container and <code>dotnet-monitor<\/code> using the following commands:<\/p>\n<pre><code class=\"lang-bash\">docker volume create diagnosticserver\r\ndocker run -d --rm -<span class=\"hljs-selector-tag\">p<\/span> <span class=\"hljs-number\">8000<\/span>:<span class=\"hljs-number\">80<\/span> -v diagnosticsserver:\/tmp mcr<span class=\"hljs-selector-class\">.microsoft<\/span><span class=\"hljs-selector-class\">.com<\/span>\/dotnet\/core\/samples:aspnetapp\r\ndocker run -it --rm -<span class=\"hljs-selector-tag\">p<\/span> <span class=\"hljs-number\">52323<\/span>:<span class=\"hljs-number\">52323<\/span> -v diagnosticsserver:\/tmp mcr<span class=\"hljs-selector-class\">.microsoft<\/span><span class=\"hljs-selector-class\">.com<\/span>\/dotnet\/nightly\/monitor:<span class=\"hljs-number\">5.0<\/span>.<span class=\"hljs-number\">0<\/span>-preview.1 --urls http:<span class=\"hljs-comment\">\/\/*:52323<\/span>\r\n<\/code><\/pre>\n<h4 id=\"running-in-a-kubernetes-cluster\">Running in a Kubernetes cluster<\/h4>\n<p>When running in a cluster, it is recommend to run the <code>dotnet-monitor<\/code> container as a sidecar alongside your application container in the same pod. The sample Kubernetes manifest below shows how to configure your deployment to include a sidecar container.<\/p>\n<pre><code class=\"lang-yaml\"><span class=\"hljs-attribute\">apiVersion<\/span>: apps\/v1\r\n<span class=\"hljs-attribute\">kind<\/span>: Deployment\r\n<span class=\"hljs-attribute\">metadata<\/span>:\r\n  <span class=\"hljs-attribute\">name<\/span>: dotnet-hello-world\r\n<span class=\"hljs-attribute\">spec<\/span>:\r\n  <span class=\"hljs-attribute\">replicas<\/span>: <span class=\"hljs-number\">1<\/span>\r\n  <span class=\"hljs-attribute\">selector<\/span>:\r\n    <span class=\"hljs-attribute\">matchLabels<\/span>:\r\n      <span class=\"hljs-attribute\">app<\/span>: dotnet-hello-world\r\n  <span class=\"hljs-attribute\">template<\/span>:\r\n    <span class=\"hljs-attribute\">metadata<\/span>:\r\n      <span class=\"hljs-attribute\">labels<\/span>:\r\n        <span class=\"hljs-attribute\">app<\/span>: dotnet-hello-world\r\n    <span class=\"hljs-attribute\">spec<\/span>:\r\n      <span class=\"hljs-attribute\">volumes<\/span>:\r\n      - <span class=\"hljs-attribute\">name<\/span>: diagnostics\r\n        <span class=\"hljs-attribute\">emptyDir<\/span>: {}\r\n      <span class=\"hljs-attribute\">containers<\/span>:\r\n      - <span class=\"hljs-attribute\">name<\/span>: server\r\n        <span class=\"hljs-attribute\">image<\/span>: mcr.microsoft.com\/dotnet\/core\/<span class=\"hljs-attribute\">samples<\/span>:aspnetapp\r\n        <span class=\"hljs-attribute\">ports<\/span>:\r\n        - <span class=\"hljs-attribute\">containerPort<\/span>: <span class=\"hljs-number\">80<\/span>\r\n        <span class=\"hljs-attribute\">volumeMounts<\/span>:\r\n          - <span class=\"hljs-attribute\">mountPath<\/span>: \/tmp\r\n            <span class=\"hljs-attribute\">name<\/span>: diagnostics\r\n      - <span class=\"hljs-attribute\">name<\/span>: sidecar\r\n        <span class=\"hljs-attribute\">image<\/span>: mcr.microsoft.com\/dotnet\/nightly\/monitor:5.0.0-preview.1\r\n        <span class=\"hljs-attribute\">ports<\/span>:\r\n        - <span class=\"hljs-attribute\">containerPort<\/span>: <span class=\"hljs-number\">52325<\/span>\r\n        # <span class=\"hljs-attribute\">args<\/span>: [<span class=\"hljs-string\">\"--urls\"<\/span>, <span class=\"hljs-string\">\"http:\/\/*:52323\"<\/span>, <span class=\"hljs-string\">\"--metricUrls\"<\/span>, <span class=\"hljs-string\">\"http:\/\/*:52325\"<\/span>]\r\n        <span class=\"hljs-attribute\">volumeMounts<\/span>:\r\n          - <span class=\"hljs-attribute\">name<\/span>: diagnostics\r\n            <span class=\"hljs-attribute\">mountPath<\/span>: \/tmp\r\n<\/code><\/pre>\n<p>Unlike other target environments, this configuration does not make the diagnostics endpoint available on your host network. You will need to port forward traffic from your host to your target cluster.<\/p>\n<p>To do this, obtain the name of the pod you wish to forward traffic to using the <code>kubectl<\/code> command:<\/p>\n<pre><code class=\"lang-bash\">$ kubectl get pod -l app=dotnet-hello-world\r\nNAME                                 READY   STATUS    RESTARTS   AGE\r\ndotnet-hello-world-dc6f67566-t2dzd   <span class=\"hljs-number\">2<\/span>\/<span class=\"hljs-number\">2<\/span>     Running   <span class=\"hljs-number\">0<\/span>          <span class=\"hljs-number\">37<\/span>m\r\n<\/code><\/pre>\n<p>Once you have your target pod name, forward traffic using the <code>kubectl port-forward<\/code> command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; <span class=\"hljs-built_in\">$job<\/span> = Start-<span class=\"hljs-keyword\">Job<\/span> -ScriptBlock { kubectl port-forward pods\/dotnet-hello-world-dc6f67566-t2dzd <span class=\"hljs-number\">52323<\/span>:<span class=\"hljs-number\">52323<\/span> }\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\">$ kubectl port-forward pods\/dotnet-hello-world-dc<span class=\"hljs-number\">6f67566<\/span>-t2dzd <span class=\"hljs-number\">52323:52323<\/span> &gt;\/dev\/null &amp;\r\n<\/code><\/pre>\n<p>Once you have started forwarding traffic from your local network to the desired pod, you can make your desired API call. As an example, you can run the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Invoke-RestMethod <span class=\"hljs-string\">http:<\/span><span class=\"hljs-comment\">\/\/localhost:52323\/processes<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\"><span class=\"hljs-variable\">$ <\/span>curl -s <span class=\"hljs-symbol\">http:<\/span>\/<span class=\"hljs-regexp\">\/localhost:52323\/processes<\/span> | jq\r\n<\/code><\/pre>\n<p>Once you have completed collecting the desired diagnostics artifacts, you can stop forwarding traffic into the container using the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Stop-<span class=\"hljs-keyword\">Job<\/span> <span class=\"hljs-built_in\">$job<\/span>\r\nPS&gt; Remove-<span class=\"hljs-keyword\">Job<\/span> <span class=\"hljs-built_in\">$job<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\"><span class=\"hljs-variable\">$ <\/span>pkill kubectl\r\n<\/code><\/pre>\n<h3 id=\"endpoints\">Endpoints<\/h3>\n<p>The REST API exposed by dotnet-monitor exposes the following endpoints:<\/p>\n<ul>\n<li><code>\/processes<\/code><\/li>\n<li><code>\/dump\/{pid?}<\/code><\/li>\n<li><code>\/gcdump\/{pid?}<\/code><\/li>\n<li><code>\/trace\/{pid?}<\/code><\/li>\n<li><code>\/logs\/{pid?}<\/code><\/li>\n<li><code>\/metrics<\/code><\/li>\n<\/ul>\n<p>In the sections that follow, we&#8217;ll look at the functionality exposed by each of these endpoints and use these endpoints to collect diagnostics artifacts.<\/p>\n<h3 id=\"processes\">Processes<\/h3>\n<p>The <code>\/processes<\/code> endpoint returns a list of target processes accessible to <code>dotnet-monitor<\/code>.<\/p>\n<p>To get a list of available processes, run the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Invoke-RestMethod http:\/\/localhost:52323\/processes\r\n\r\n<span class=\"hljs-section\">pid\r\n---<\/span>\r\n<span class=\"hljs-code\">  1<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\">$ curl -<span class=\"hljs-keyword\">s<\/span> http:<span class=\"hljs-regexp\">\/\/localhost<\/span>:<span class=\"hljs-number\">52323<\/span>\/processes | j<span class=\"hljs-string\">q\r\n[\r\n  {\r\n    \"pid\": 1\r\n  }\r\n]<\/span>\r\n<\/code><\/pre>\n<p>As a convenience, when there is only one accessible process, <code>dotnet-monitor<\/code> does not require you to specify a process id for the remaining diagnostic endpoints.<\/p>\n<blockquote><p>Known Issue: When running locally the <code>dotnet-monitor<\/code> tools lists itself as one of the target processes.<\/p><\/blockquote>\n<h3 id=\"dump\">Dump<\/h3>\n<p>The <code>\/dump<\/code> endpoint returns a process dump of the target process.<\/p>\n<p>To collect a process dump, run the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Start-<span class=\"hljs-built_in\">Process<\/span> http:<span class=\"hljs-comment\">\/\/localhost:52323\/dump<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\"><span class=\"hljs-variable\">$ <\/span>wget --content-disposition <span class=\"hljs-symbol\">http:<\/span>\/<span class=\"hljs-regexp\">\/localhost:52323\/dump<\/span>\r\n<\/code><\/pre>\n<p>A dump artifact cannot be analyzed on a machine of a different OS\/Architecture than where it was captured. When collecting a dump from a Kubernetes cluster running Linux, the resulting core dump cannot be analyzed on a Windows or a macOS machine. You can however use the existing <a href=\"https:\/\/docs.microsoft.com\/dotnet\/core\/diagnostics\/dotnet-dump\">dotnet-dump<\/a> tool to analyze the generated dump in a Docker container using the following commands:<\/p>\n<pre><code class=\"lang-bash\">docker run --rm -it -v C:<span class=\"hljs-regexp\">\/dumpFiles:\/<\/span>dumpFiles mcr.microsoft.com<span class=\"hljs-regexp\">\/dotnet\/<\/span>sdk <span class=\"hljs-regexp\">\/bin\/<\/span>sh\r\n\r\n<span class=\"hljs-comment\"># Now in the context of the docker container<\/span>\r\ndotnet tool install -g dotnet-dump\r\n<span class=\"hljs-regexp\">\/root\/<\/span>.dotnet<span class=\"hljs-regexp\">\/tools\/<\/span>dotnet-dump analyze <span class=\"hljs-regexp\">\/dumpFiles\/<\/span>core_20200618_083349\r\n<\/code><\/pre>\n<h3 id=\"gc-dump\">GC Dump<\/h3>\n<p>The <code>\/gcdump<\/code> endpoint returns a GC dump of the target process.<\/p>\n<p>To collect a GC dump, run the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Start-<span class=\"hljs-built_in\">Process<\/span> http:<span class=\"hljs-comment\">\/\/localhost:52323\/gcdump<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\"><span class=\"hljs-variable\">$ <\/span>wget --content-disposition <span class=\"hljs-symbol\">http:<\/span>\/<span class=\"hljs-regexp\">\/localhost:52323\/gcdump<\/span>\r\n<\/code><\/pre>\n<p>Unlike a process dump, a GC dump is a portable format which can be analyzed by Visual Studio and <a href=\"https:\/\/github.com\/microsoft\/perfview\">perfview<\/a> regardless of the platform it was collected on. To learn more about when to collect GC dumps and how to analyze them, take a look at our <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/collecting-and-analyzing-memory-dumps\/\">earlier blog post<\/a>.<\/p>\n<h3 id=\"traces\">Traces<\/h3>\n<p>The <code>\/trace<\/code> endpoint returns a trace of the target process. The default trace profile includes sampled CPU stacks, HTTP request start\/stop events, and metrics for a duration of 30 seconds.<\/p>\n<p>The duration of collection can be customized via the <code>durationSeconds<\/code> querystring parameter. The diagnostic data present in the trace can be customized via the <code>profile<\/code> querystring parameter to include any combination of the preset profiles:<\/p>\n<ul>\n<li><code>CPU<\/code> (CPU profiler),<\/li>\n<li><code>Http<\/code> (Request start\/stop events from ASP.NET Core),<\/li>\n<li><code>Logs<\/code> (Logging from the <code>EventSourceLogger<\/code> from <code>Microsoft.Extensions.Logging<\/code> library); and<\/li>\n<li><code>Metrics<\/code>(Runtime and ASP.NET Core <code>EventCounters<\/code>).<\/li>\n<\/ul>\n<p>For example, a request to <code>\/trace?profile=cpu,logs<\/code> will enable the collection of the CPU profiler and logs.<\/p>\n<p>In addition to the <code>GET<\/code> endpoint, there is <code>POST<\/code> version of the endpoint which allows you to specify what <code>EventSource<\/code> providers to enable via the request body.<\/p>\n<p>To collect a trace of the target process, run the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Start-<span class=\"hljs-built_in\">Process<\/span> http:<span class=\"hljs-comment\">\/\/localhost:52323\/trace<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\"><span class=\"hljs-variable\">$ <\/span>wget --content-disposition <span class=\"hljs-symbol\">http:<\/span>\/<span class=\"hljs-regexp\">\/localhost:52323\/trace<\/span>\r\n<\/code><\/pre>\n<p>The resulting <code>.nettrace<\/code> file can be analyzed with both Visual Studio and PerfView.<\/p>\n<h3 id=\"logs\">Logs<\/h3>\n<p>The <code>\/logs<\/code> endpoint will stream logs from the target process for a duration of 30 seconds.<\/p>\n<p>The duration of collection can be customized via the <code>durationSeconds<\/code> querystring parameter. The logs endpoint is capable of returning either newline delimited JSON (<a href=\"https:\/\/github.com\/ndjson\/ndjson-spec\">application\/x-ndjson<\/a>) or the Event stream format (<a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Server-sent_events\/Using_server-sent_events#Event_stream_format\">text\/event-stream<\/a>) based on the specified <code>Accept<\/code> header in the HTTP request.<\/p>\n<p>To start streaming logs from the target process, run the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Start-<span class=\"hljs-built_in\">Process<\/span> http:<span class=\"hljs-comment\">\/\/localhost:52323\/logs<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\">$ curl -H <span class=\"hljs-string\">\"Accept:application\/x-ndjson\"<\/span> http:\/\/localhost:<span class=\"hljs-number\">52323<\/span>\/logs --no-buffer\r\n\r\n{<span class=\"hljs-string\">\"LogLevel\"<\/span>:<span class=\"hljs-string\">\"Information\"<\/span>,<span class=\"hljs-string\">\"EventId\"<\/span>:<span class=\"hljs-string\">\"1\"<\/span>,<span class=\"hljs-string\">\"Category\"<\/span>:<span class=\"hljs-string\">\"Microsoft.AspNetCore.Hosting.Diagnostics\"<\/span>,<span class=\"hljs-string\">\"Message\"<\/span>:<span class=\"hljs-string\">\"Request starting HTTP\/1.1 GET http:\/\/localhost:7001\/  \"<\/span>,<span class=\"hljs-string\">\"Scopes\"<\/span>:{<span class=\"hljs-string\">\"RequestId\"<\/span>:<span class=\"hljs-string\">\"0HM0N9ARKHVJK:00000002\"<\/span>,<span class=\"hljs-string\">\"RequestPath\"<\/span>:<span class=\"hljs-string\">\"\/\"<\/span>,<span class=\"hljs-string\">\"SpanId\"<\/span>:<span class=\"hljs-string\">\"|88c401de-4df03365b379aaa4.\"<\/span>,<span class=\"hljs-string\">\"TraceId\"<\/span>:<span class=\"hljs-string\">\"88c401de-4df03365b379aaa4\"<\/span>,<span class=\"hljs-string\">\"ParentId\"<\/span>:<span class=\"hljs-string\">\"\"<\/span>},<span class=\"hljs-string\">\"Arguments\"<\/span>:{<span class=\"hljs-string\">\"Protocol\"<\/span>:<span class=\"hljs-string\">\"HTTP\/1.1\"<\/span>,<span class=\"hljs-string\">\"Method\"<\/span>:<span class=\"hljs-string\">\"<span class=\"hljs-keyword\">GET<\/span>\"<\/span>,<span class=\"hljs-string\">\"ContentType\"<\/span>:null,<span class=\"hljs-string\">\"ContentLength\"<\/span>:null,<span class=\"hljs-string\">\"Scheme\"<\/span>:<span class=\"hljs-string\">\"http\"<\/span>,<span class=\"hljs-string\">\"Host\"<\/span>:<span class=\"hljs-string\">\"localhost:7001\"<\/span>,<span class=\"hljs-string\">\"PathBase\"<\/span>:<span class=\"hljs-string\">\"\"<\/span>,<span class=\"hljs-string\">\"Path\"<\/span>:<span class=\"hljs-string\">\"\/\"<\/span>,<span class=\"hljs-string\">\"QueryString\"<\/span>:<span class=\"hljs-string\">\"\"<\/span>}}\r\n{<span class=\"hljs-string\">\"LogLevel\"<\/span>:<span class=\"hljs-string\">\"Information\"<\/span>,<span class=\"hljs-string\">\"EventId\"<\/span>:<span class=\"hljs-string\">\"ExecutingEndpoint\"<\/span>,<span class=\"hljs-string\">\"Category\"<\/span>:<span class=\"hljs-string\">\"Microsoft.AspNetCore.Routing.EndpointMiddleware\"<\/span>,<span class=\"hljs-string\">\"Message\"<\/span>:<span class=\"hljs-string\">\"Executing endpoint \\u0027\/Index\\u0027\"<\/span>,<span class=\"hljs-string\">\"Scopes\"<\/span>:{<span class=\"hljs-string\">\"RequestId\"<\/span>:<span class=\"hljs-string\">\"0HM0N9ARKHVJK:00000002\"<\/span>,<span class=\"hljs-string\">\"RequestPath\"<\/span>:<span class=\"hljs-string\">\"\/\"<\/span>,<span class=\"hljs-string\">\"SpanId\"<\/span>:<span class=\"hljs-string\">\"|88c401de-4df03365b379aaa4.\"<\/span>,<span class=\"hljs-string\">\"TraceId\"<\/span>:<span class=\"hljs-string\">\"88c401de-4df03365b379aaa4\"<\/span>,<span class=\"hljs-string\">\"ParentId\"<\/span>:<span class=\"hljs-string\">\"\"<\/span>},<span class=\"hljs-string\">\"Arguments\"<\/span>:{<span class=\"hljs-string\">\"EndpointName\"<\/span>:<span class=\"hljs-string\">\"\/Index\"<\/span>,<span class=\"hljs-string\">\"{OriginalFormat}\"<\/span>:<span class=\"hljs-string\">\"Executing endpoint \\u0027{EndpointName}\\u0027\"<\/span>}}\r\n<\/code><\/pre>\n<h3 id=\"metrics\">Metrics<\/h3>\n<p>The <code>\/metrics<\/code> endpoint will return a snapshot of runtime and ASP.NET Core metrics in the <a href=\"https:\/\/prometheus.io\/docs\/instrumenting\/exposition_formats\/#text-based-format\">prometheus exposition format<\/a>. Unlike the other diagnostics endpoints, the metrics endpoint will not be available if <code>dotnet-trace<\/code> detects more than one target process. In addition to being accessible via the URLs configured via the <code>--urls<\/code> parameters, the metrics endpoint is also accessible from the URLs configured via the <code>--metricUrls<\/code>. When running in Kubernetes, it may be suitable to expose the metrics URL to other services in your cluster to allow them to scrape metrics.<\/p>\n<p>When deploying in-cluster, a common pattern to collect metrics is to use Prometheus or another monitoring tool to scrape the metrics endpoint exposed by your application. As an example, when running in Azure Kubernetes Services (AKS), you can <a href=\"https:\/\/docs.microsoft.com\/azure\/azure-monitor\/insights\/container-insights-prometheus-integration\">configure Azure Monitor to scrape prometheus metrics<\/a> exposed by <code>dotnet-monitor<\/code>. By following the instructions in the linked document, you can enable Azure Monitor to <a href=\"https:\/\/gist.github.com\/shirhatti\/0222017e8e2fdb481f735002f7bd72f7\/revisions\">enable monitoring pods<\/a> that have been <a href=\"https:\/\/gist.github.com\/shirhatti\/ad7a986137d7ca6b1dc094a3e0a61a0d#file-hello-world-deployment-yaml-L18-L19\">annotated<\/a>.<\/p>\n<p>Like in the case of the other diagnostics endpoints, it is also possible to view a snapshot of current metrics by running the following command:<\/p>\n<p>In PowerShell,<\/p>\n<pre><code class=\"lang-powershell\">PS&gt; Invoke-RestMethod <span class=\"hljs-string\">http:<\/span><span class=\"hljs-comment\">\/\/localhost:52323\/metrics<\/span>\r\n<\/code><\/pre>\n<p>In bash,<\/p>\n<pre><code class=\"lang-bash\">$ curl -S http:\/\/localhost:52323\/metrics\r\n\r\n<span class=\"hljs-comment\"># HELP systemruntime_alloc_rate_bytes Allocation Rate<\/span>\r\n<span class=\"hljs-comment\"># TYPE systemruntime_alloc_rate_bytes gauge<\/span>\r\nsystemruntime_alloc_rate_bytes<span class=\"hljs-number\"> 96784 <\/span>1592899673335\r\nsystemruntime_alloc_rate_bytes<span class=\"hljs-number\"> 96784 <\/span>1592899683336\r\nsystemruntime_alloc_rate_bytes<span class=\"hljs-number\"> 96784 <\/span>1592899693336\r\n<span class=\"hljs-comment\"># HELP systemruntime_assembly_count Number of Assemblies Loaded<\/span>\r\n<span class=\"hljs-comment\"># TYPE systemruntime_assembly_count gauge<\/span>\r\nsystemruntime_assembly_count<span class=\"hljs-number\"> 136 <\/span>1592899673335\r\nsystemruntime_assembly_count<span class=\"hljs-number\"> 136 <\/span>1592899683336\r\nsystemruntime_assembly_count<span class=\"hljs-number\"> 136 <\/span>1592899693336\r\n<span class=\"hljs-comment\"># HELP systemruntime_active_timer_count Number of Active Timers<\/span>\r\n<span class=\"hljs-comment\"># TYPE systemruntime_active_timer_count gauge<\/span>\r\nsystemruntime_active_timer_count<span class=\"hljs-number\"> 1 <\/span>1592899673335\r\nsystemruntime_active_timer_count<span class=\"hljs-number\"> 1 <\/span>1592899683336\r\nsystemruntime_active_timer_count<span class=\"hljs-number\"> 1 <\/span>1592899693336\r\n<span class=\"hljs-comment\"># ...<\/span>\r\n<span class=\"hljs-comment\"># (Output truncated)<\/span>\r\n<\/code><\/pre>\n<p>While metrics collection is enabled by default when <code>dotnet-monitor<\/code> detects exactly one target process, it can be configured to disable to collection of metrics entirely via the <code>--metrics<\/code> parameter. In the example below, metrics collection will not be enabled.<\/p>\n<pre><code class=\"lang-bash\">dotnet<span class=\"hljs-built_in\"> monitor <\/span>collect --metrics false\r\n<\/code><\/pre>\n<h2 id=\"roadmap\">Roadmap<\/h2>\n<p>While we are excited about the promise dotnet-monitor holds, it is an experimental project and not a committed product. During this experimental phase we expect to engage deeply with anyone trying out dotnet-monitor to hear feedback and suggestions.<\/p>\n<p>dotnet-monitor is currently committed as an experiment until .NET 5 ships. At which point we will be evaluating what we have and all that we\u2019ve learnt to decide what we should do in the future.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>We are excited to introduce the first preview of <code>dotnet-monitor<\/code> and want your feedback. Let us know what we can do to make it easier to diagnose what&#8217;s wrong with your dotnet application. We&#8217;d love for you to try it out and let us know what you think.<\/p>\n<p>You can create issues or just follow along with the progress of the project on our <a href=\"https:\/\/github.com\/dotnet\/diagnostics\">GitHub repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>dotnet-monitor is an experimental tool that makes it easier to get access to diagnostics information in a dotnet process. When running a dotnet application differences in diverse local and production environments can make collecting diagnostics artifacts (e.g., logs, traces, process dumps) challenging. dotnet-monitor aims to simplify the process by exposing a consistent REST API regardless [&hellip;]<\/p>\n","protected":false},"author":1233,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196,7237],"tags":[],"class_list":["post-28715","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core","category-containers"],"acf":[],"blog_post_summary":"<p>dotnet-monitor is an experimental tool that makes it easier to get access to diagnostics information in a dotnet process. When running a dotnet application differences in diverse local and production environments can make collecting diagnostics artifacts (e.g., logs, traces, process dumps) challenging. dotnet-monitor aims to simplify the process by exposing a consistent REST API regardless [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/28715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1233"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=28715"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/28715\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=28715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=28715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=28715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}