-
Notifications
You must be signed in to change notification settings - Fork 5k
Socket's connect operations tracing #38620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
870f476
aec1bc4
b4b42fe
7002376
c693fe7
a6d7e3d
f16a84d
4e89fed
245458e
d64ba15
abd9c9d
ecce3af
6c305f2
33707e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// 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; | ||
|
||
namespace System.Net.Sockets | ||
{ | ||
[EventSource(Name = "System.Net.Sockets")] | ||
internal sealed class SocketsTelemetry : EventSource | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally, you have one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @alnikola, this doesn't need to block your PR, but I do want us to resolve this for .NET 5. Can you please make sure there's an issue for it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issue already exists, but it's outside .NET 5.0 scope. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is related but different. These PRs are actively doubling the number of event sources used. How is a customer supposed to reason about that: they want socket events, but they need to enable two different providers depending on the events they want? There's no good reason for it. If we're doing a new one because we don't like the old one, we should remove the old one. If we're fine with the old one, we shouldn't introduce the new class. Adding new types like this adds overhead, adds confusion, and adds legacy code to be maintained. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (and if we really want to use that same issue, the description and the milestone should be updated) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created a dedicated issue #38754 for this, but it needs to be triaged to see if it can fit in .NET 5.0 scope. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added some thoughts to #38754 and may have more once I get a chance to look into this more |
||
{ | ||
public static readonly SocketsTelemetry Log = new SocketsTelemetry(); | ||
|
||
[Event(1, Level = EventLevel.Informational)] | ||
public void ConnectStart(string? address) | ||
{ | ||
if (IsEnabled(EventLevel.Informational, EventKeywords.All)) | ||
{ | ||
WriteEvent(eventId: 1, address ?? ""); | ||
} | ||
} | ||
|
||
[Event(2, Level = EventLevel.Informational)] | ||
public void ConnectStop() | ||
{ | ||
if (IsEnabled(EventLevel.Informational, EventKeywords.All)) | ||
{ | ||
WriteEvent(eventId: 2); | ||
} | ||
} | ||
|
||
[Event(3, Level = EventLevel.Error)] | ||
public void ConnectFailed(SocketError error, string? exceptionMessage) | ||
{ | ||
if (IsEnabled(EventLevel.Error, EventKeywords.All)) | ||
{ | ||
WriteEvent(eventId: 3, (int)error, exceptionMessage ?? string.Empty); | ||
} | ||
} | ||
|
||
[Event(4, Level = EventLevel.Warning)] | ||
public void ConnectCanceled() | ||
{ | ||
if (IsEnabled(EventLevel.Warning, EventKeywords.All)) | ||
{ | ||
WriteEvent(eventId: 4); | ||
} | ||
} | ||
|
||
[NonEvent] | ||
public void ConnectStart(Internals.SocketAddress address) | ||
{ | ||
ConnectStart(address.ToString()); | ||
} | ||
|
||
[NonEvent] | ||
public void ConnectStart(EndPoint address) | ||
{ | ||
ConnectStart(address.ToString()); | ||
} | ||
|
||
[NonEvent] | ||
public void ConnectCanceledAndStop() | ||
{ | ||
alnikola marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ConnectCanceled(); | ||
ConnectStop(); | ||
alnikola marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
[NonEvent] | ||
public void ConnectFailedAndStop(SocketError error, string? exceptionMessage) | ||
{ | ||
ConnectFailed(error, exceptionMessage); | ||
ConnectStop(); | ||
} | ||
} | ||
} | ||
alnikola marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections.Concurrent; | ||
using System.Diagnostics.Tracing; | ||
using Microsoft.DotNet.RemoteExecutor; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
|
||
namespace System.Net.Sockets.Tests | ||
{ | ||
public class TelemetryTest | ||
{ | ||
public readonly ITestOutputHelper _output; | ||
|
||
public TelemetryTest(ITestOutputHelper output) | ||
{ | ||
_output = output; | ||
} | ||
|
||
[Fact] | ||
public static void EventSource_ExistsWithCorrectId() | ||
{ | ||
Type esType = typeof(Socket).Assembly.GetType("System.Net.Sockets.SocketsTelemetry", throwOnError: true, ignoreCase: false); | ||
Assert.NotNull(esType); | ||
|
||
Assert.Equal("System.Net.Sockets", EventSource.GetName(esType)); | ||
Assert.Equal(Guid.Parse("d5b2e7d4-b6ec-50ae-7cde-af89427ad21f"), EventSource.GetGuid(esType)); | ||
|
||
Assert.NotEmpty(EventSource.GenerateManifest(esType, esType.Assembly.Location)); | ||
} | ||
|
||
[OuterLoop] | ||
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] | ||
public void EventSource_EventsRaisedAsExpected() | ||
{ | ||
RemoteExecutor.Invoke(() => | ||
{ | ||
using (var listener = new TestEventListener("System.Net.Sockets", EventLevel.Verbose)) | ||
{ | ||
var events = new ConcurrentQueue<EventWrittenEventArgs>(); | ||
listener.RunWithCallback(events.Enqueue, () => | ||
{ | ||
// Invoke several tests to execute code paths while tracing is enabled | ||
|
||
new SendReceiveSync(null).SendRecv_Stream_TCP(IPAddress.Loopback, false).GetAwaiter(); | ||
new SendReceiveSync(null).SendRecv_Stream_TCP(IPAddress.Loopback, true).GetAwaiter(); | ||
|
||
new SendReceiveTask(null).SendRecv_Stream_TCP(IPAddress.Loopback, false).GetAwaiter(); | ||
new SendReceiveTask(null).SendRecv_Stream_TCP(IPAddress.Loopback, true).GetAwaiter(); | ||
|
||
new SendReceiveEap(null).SendRecv_Stream_TCP(IPAddress.Loopback, false).GetAwaiter(); | ||
new SendReceiveEap(null).SendRecv_Stream_TCP(IPAddress.Loopback, true).GetAwaiter(); | ||
|
||
new SendReceiveApm(null).SendRecv_Stream_TCP(IPAddress.Loopback, false).GetAwaiter(); | ||
new SendReceiveApm(null).SendRecv_Stream_TCP(IPAddress.Loopback, true).GetAwaiter(); | ||
|
||
new NetworkStreamTest().CopyToAsync_AllDataCopied(4096, true).GetAwaiter().GetResult(); | ||
new NetworkStreamTest().Timeout_ValidData_Roundtrips().GetAwaiter().GetResult(); | ||
}); | ||
Assert.DoesNotContain(events, ev => ev.EventId == 0); // errors from the EventSource itself | ||
Assert.InRange(events.Count, 1, int.MaxValue); | ||
} | ||
}).Dispose(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style-wise I've always found it preferable to eliminate these IsEnabled() calls entirely and rely on the checks that occur inside the EventSource, but I think the mono-linker will fully remove this pattern so its purely style and tiny perf at this point. Style is best decided by the folks who have to work on the code rather than me : )