|
// 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.Tracing;
using System.Runtime.CompilerServices;
namespace Microsoft.AspNetCore.Hosting;
internal sealed class HostingEventSource : EventSource
{
public static readonly HostingEventSource Log = new HostingEventSource();
private IncrementingPollingCounter? _requestsPerSecondCounter;
private PollingCounter? _totalRequestsCounter;
private PollingCounter? _failedRequestsCounter;
private PollingCounter? _currentRequestsCounter;
private long _totalRequests;
private long _currentRequests;
private long _failedRequests;
internal HostingEventSource()
: base("Microsoft.AspNetCore.Hosting", EventSourceSettings.EtwManifestEventFormat)
{
}
// Used for testing
internal HostingEventSource(string eventSourceName)
: base(eventSourceName, EventSourceSettings.EtwManifestEventFormat)
{
}
// NOTE
// - The 'Start' and 'Stop' suffixes on the following event names have special meaning in EventSource. They
// enable creating 'activities'.
// For more information, take a look at the following blog post:
// https://blogs.msdn.microsoft.com/vancem/2015/09/14/exploring-eventsource-activity-correlation-and-causation-features/
// - A stop event's event id must be next one after its start event.
[Event(1, Level = EventLevel.Informational)]
public void HostStart()
{
WriteEvent(1);
}
[Event(2, Level = EventLevel.Informational)]
public void HostStop()
{
WriteEvent(2);
}
[Event(3, Level = EventLevel.Informational)]
public void RequestStart(string method, string path)
{
Interlocked.Increment(ref _totalRequests);
Interlocked.Increment(ref _currentRequests);
WriteEvent(3, method, path);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[Event(4, Level = EventLevel.Informational)]
public void RequestStop()
{
Interlocked.Decrement(ref _currentRequests);
WriteEvent(4);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[Event(5, Level = EventLevel.Error)]
public void UnhandledException()
{
WriteEvent(5);
}
[Event(6, Level = EventLevel.Informational)]
public void ServerReady()
{
WriteEvent(6);
}
[NonEvent]
internal void RequestFailed()
{
Interlocked.Increment(ref _failedRequests);
}
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...
_requestsPerSecondCounter ??= new IncrementingPollingCounter("requests-per-second", this, () => Volatile.Read(ref _totalRequests))
{
DisplayName = "Request Rate",
DisplayRateTimeScale = TimeSpan.FromSeconds(1)
};
_totalRequestsCounter ??= new PollingCounter("total-requests", this, () => Volatile.Read(ref _totalRequests))
{
DisplayName = "Total Requests",
};
_currentRequestsCounter ??= new PollingCounter("current-requests", this, () => Volatile.Read(ref _currentRequests))
{
DisplayName = "Current Requests"
};
_failedRequestsCounter ??= new PollingCounter("failed-requests", this, () => Volatile.Read(ref _failedRequests))
{
DisplayName = "Failed Requests"
};
}
}
}
|