File: System\Net\Http\HttpTelemetry.AnyOS.cs
Web Access
Project: src\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Threading;
 
namespace System.Net.Http
{
    internal sealed partial class HttpTelemetry
    {
        private IncrementingPollingCounter? _startedRequestsPerSecondCounter;
        private IncrementingPollingCounter? _failedRequestsPerSecondCounter;
        private PollingCounter? _startedRequestsCounter;
        private PollingCounter? _currentRequestsCounter;
        private PollingCounter? _failedRequestsCounter;
        private PollingCounter? _totalHttp11ConnectionsCounter;
        private PollingCounter? _totalHttp20ConnectionsCounter;
        private PollingCounter? _totalHttp30ConnectionsCounter;
        private EventCounter? _http11RequestsQueueDurationCounter;
        private EventCounter? _http20RequestsQueueDurationCounter;
        private EventCounter? _http30RequestsQueueDurationCounter;
 
        [NonEvent]
        public void RequestLeftQueue(int versionMajor, TimeSpan duration)
        {
            Debug.Assert(versionMajor is 1 or 2 or 3);
 
            EventCounter? counter = versionMajor switch
            {
                1 => _http11RequestsQueueDurationCounter,
                2 => _http20RequestsQueueDurationCounter,
                _ => _http30RequestsQueueDurationCounter
            };
 
            double timeOnQueueMs = duration.TotalMilliseconds;
 
            counter?.WriteMetric(timeOnQueueMs);
 
            RequestLeftQueue(timeOnQueueMs, (byte)versionMajor, versionMinor: versionMajor == 1 ? (byte)1 : (byte)0);
        }
 
        protected override void OnEventCommand(EventCommandEventArgs command)
        {
            if (command.Command == EventCommand.Enable)
            {
                // This is the convention for initializing counters in the RuntimeEventSource (lazily on the first enable command).
                // They aren't disabled afterwards...
 
                // The cumulative number of HTTP requests started since the process started.
                _startedRequestsCounter ??= new PollingCounter("requests-started", this, () => Interlocked.Read(ref _startedRequests))
                {
                    DisplayName = "Requests Started",
                };
 
                // The number of HTTP requests started per second since the process started.
                _startedRequestsPerSecondCounter ??= new IncrementingPollingCounter("requests-started-rate", this, () => Interlocked.Read(ref _startedRequests))
                {
                    DisplayName = "Requests Started Rate",
                    DisplayRateTimeScale = TimeSpan.FromSeconds(1)
                };
 
                // The cumulative number of HTTP requests failed since the process started.
                // Failed means that an exception occurred during the handler's Send(Async) call as a result of a connection related error, timeout, or explicitly cancelled.
                // In case of using HttpClient's SendAsync(and friends) with buffering, this includes exceptions that occurred while buffering the response content
                // In case of using HttpClient's helper methods (GetString/ByteArray/Stream), this includes responses with non-success status codes
                _failedRequestsCounter ??= new PollingCounter("requests-failed", this, () => Interlocked.Read(ref _failedRequests))
                {
                    DisplayName = "Requests Failed"
                };
 
                // The number of HTTP requests failed per second since the process started.
                _failedRequestsPerSecondCounter ??= new IncrementingPollingCounter("requests-failed-rate", this, () => Interlocked.Read(ref _failedRequests))
                {
                    DisplayName = "Requests Failed Rate",
                    DisplayRateTimeScale = TimeSpan.FromSeconds(1)
                };
 
                // The current number of active HTTP requests that have started but not yet completed or failed.
                // Use (-_stoppedRequests + _startedRequests) to avoid returning a negative value if _stoppedRequests is
                // incremented after reading _startedRequests due to race conditions with completing the HTTP request.
                _currentRequestsCounter ??= new PollingCounter("current-requests", this, () => -Interlocked.Read(ref _stoppedRequests) + Interlocked.Read(ref _startedRequests))
                {
                    DisplayName = "Current Requests"
                };
 
                _totalHttp11ConnectionsCounter ??= new PollingCounter("http11-connections-current-total", this, () => Interlocked.Read(ref _openedHttp11Connections))
                {
                    DisplayName = "Current Http 1.1 Connections"
                };
 
                _totalHttp20ConnectionsCounter ??= new PollingCounter("http20-connections-current-total", this, () => Interlocked.Read(ref _openedHttp20Connections))
                {
                    DisplayName = "Current Http 2.0 Connections"
                };
 
                _totalHttp30ConnectionsCounter ??= new PollingCounter("http30-connections-current-total", this, () => Interlocked.Read(ref _openedHttp30Connections))
                {
                    DisplayName = "Current Http 3.0 Connections"
                };
 
                _http11RequestsQueueDurationCounter ??= new EventCounter("http11-requests-queue-duration", this)
                {
                    DisplayName = "HTTP 1.1 Requests Queue Duration",
                    DisplayUnits = "ms"
                };
 
                _http20RequestsQueueDurationCounter ??= new EventCounter("http20-requests-queue-duration", this)
                {
                    DisplayName = "HTTP 2.0 Requests Queue Duration",
                    DisplayUnits = "ms"
                };
 
                _http30RequestsQueueDurationCounter ??= new EventCounter("http30-requests-queue-duration", this)
                {
                    DisplayName = "HTTP 3.0 Requests Queue Duration",
                    DisplayUnits = "ms"
                };
            }
        }
    }
}