Skip to content
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

feat(ping): #41 improve logging #49

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions src/libp2p/Libp2p.Protocols.Ping/LogMessages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: MIT

using Microsoft.Extensions.Logging;
using Nethermind.Libp2p.Core;

namespace Nethermind.Libp2p.Protocols.Ping;

internal static partial class LogMessages
{
private const int EventId = 200_000;

[LoggerMessage(
EventId = EventId + 1,
EventName = nameof(ReadingPong),
Message = "Reading pong",
Level = LogLevel.Trace)]
internal static partial void ReadingPong(
this ILogger logger);

[LoggerMessage(
EventId = EventId + 2,
EventName = nameof(VerifyingPong),
Message = "Verifying pong",
Level = LogLevel.Trace)]
internal static partial void VerifyingPong(
this ILogger logger);

[LoggerMessage(
EventId = EventId + 3,
EventName = nameof(ReadingPing),
Message = "Reading ping",
Level = LogLevel.Trace)]
internal static partial void ReadingPing(
this ILogger logger);

[LoggerMessage(
EventId = EventId + 4,
EventName = nameof(ReturningPong),
Message = "Returning pong",
Level = LogLevel.Trace)]
internal static partial void ReturningPong(
this ILogger logger);

[LoggerMessage(
EventId = EventId + 5,
EventName = nameof(LogPing),
Message = "Ping {remotePeer}",
Level = LogLevel.Debug)]
internal static partial void LogPing(
this ILogger logger,
Multiaddr remotePeer);

[LoggerMessage(
EventId = EventId + 6,
EventName = nameof(LogPinged),
Message = "Pinged",
Level = LogLevel.Debug)]
internal static partial void LogPinged(
this ILogger logger);

[LoggerMessage(
EventId = EventId + 7,
EventName = nameof(PingListenStarted),
Message = "Ping listen started from {remotePeer}",
Level = LogLevel.Debug)]
internal static partial void PingListenStarted(
this ILogger logger,
Multiaddr remotePeer);

[LoggerMessage(
EventId = EventId + 8,
EventName = nameof(PingFinished),
Message = "Ping finished",
Level = LogLevel.Debug)]
internal static partial void PingFinished(
this ILogger logger);

[LoggerMessage(
EventId = EventId + 9,
EventName = nameof(PingFailed),
Message = "Wrong response to ping from {remotePeer}",
Level = LogLevel.Warning)]
internal static partial void PingFailed(
this ILogger logger,
Multiaddr remotePeer);
}
56 changes: 37 additions & 19 deletions src/libp2p/Libp2p.Protocols.Ping/PingProtocol.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
// SPDX-License-Identifier: MIT

using System.Buffers;
using Microsoft.Extensions.Logging;
using Nethermind.Libp2p.Core;
using System.Buffers;
using Nethermind.Libp2p.Protocols.Ping;

namespace Nethermind.Libp2p.Protocols;

Expand All @@ -12,7 +13,9 @@ namespace Nethermind.Libp2p.Protocols;
/// </summary>
public class PingProtocol : IProtocol
{
public string Id => "/ipfs/ping/1.0.0";
private const int PayloadLength = 32;

public string Id => "/ipfs/ping/1.0.0"; // TODO: order in class: fields, constructors, properties, methods?
private readonly Random _random = new();
private readonly ILogger<PingProtocol>? _logger;

Expand All @@ -24,33 +27,48 @@ public PingProtocol(ILoggerFactory? loggerFactory = null)
public async Task DialAsync(IChannel channel, IChannelFactory? channelFactory,
IPeerContext context)
{
byte[] bytes = new byte[32];
_random.NextBytes(bytes.AsSpan(0, 32));
_logger?.LogDebug("Ping {remotePeer}", context.RemotePeer.Address);
await channel.WriteAsync(new ReadOnlySequence<byte>(bytes));
_logger?.LogTrace("Reading pong");
ReadOnlySequence<byte> response = await channel.ReadAsync(32, ReadBlockingMode.WaitAll);
_logger?.LogTrace("Verifing pong");
if (!Enumerable.SequenceEqual(bytes[0..32], response.ToArray()))
byte[] byteArray = new byte[PayloadLength];
_random.NextBytes(byteArray.AsSpan(0, PayloadLength));
ReadOnlySequence<byte> bytes = new(byteArray);

_logger?.LogPing(context.RemotePeer.Address);
await channel.WriteAsync(bytes);

_logger?.ReadingPong();
ReadOnlySequence<byte> response = await channel.ReadAsync(PayloadLength, ReadBlockingMode.WaitAll);

_logger?.VerifyingPong();
if (!byteArray[0..PayloadLength].SequenceEqual(response.ToArray()))
{
_logger?.LogWarning("Wrong response to ping from {from}", context.RemotePeer);
throw new ApplicationException();
// TODO: do we need log context.RemotePeer or context.RemotePeer.Address?
chertby marked this conversation as resolved.
Show resolved Hide resolved
// _logger?.LogWarning("Wrong response to ping from {from}", context.RemotePeer);

// TODO: if we throw exception, probably LogLevel bigger than warning?
chertby marked this conversation as resolved.
Show resolved Hide resolved
_logger?.PingFailed(context.RemotePeer.Address);
throw new ApplicationException(); // TODO: add specific exception?
chertby marked this conversation as resolved.
Show resolved Hide resolved
}
_logger?.LogDebug("Pinged");

_logger?.LogPinged(); // TODO: add context.RemotePeer.Address?
chertby marked this conversation as resolved.
Show resolved Hide resolved
}

public async Task ListenAsync(IChannel channel, IChannelFactory? channelFactory,
IPeerContext context)
{
_logger?.LogDebug("Ping listen started from {remotePeer}", context.RemotePeer);
// TODO: do we need log context.RemotePeer or context.RemotePeer.Address?
chertby marked this conversation as resolved.
Show resolved Hide resolved
// _logger?.LogDebug("Ping listen started from {remotePeer}", context.RemotePeer);
_logger?.PingListenStarted(context.RemotePeer.Address);

while (!channel.IsClosed)
{
_logger?.LogTrace("Reading ping");
byte[] request = (await channel.ReadAsync(32, ReadBlockingMode.WaitAll)).ToArray();
_logger?.LogTrace("Returning back");
await channel.WriteAsync(new ReadOnlySequence<byte>(request));
_logger?.ReadingPing();
ReadOnlySequence<byte> request = await channel.ReadAsync(PayloadLength, ReadBlockingMode.WaitAll);
byte[] byteArray = request.ToArray(); // TODO: do we need convert to array and then again to ReadOnlySequence?
chertby marked this conversation as resolved.
Show resolved Hide resolved
ReadOnlySequence<byte> bytes = new(byteArray);

_logger?.ReturningPong();
await channel.WriteAsync(bytes);
}
_logger?.LogDebug("Ping finished");

_logger?.PingFinished();
}
}
Loading