Skip to content

Commit

Permalink
Merge pull request #135 from dotnet-campus/t/lindexi/Logger
Browse files Browse the repository at this point in the history
完善 IPC 记录日志功能
  • Loading branch information
Firito authored Sep 19, 2023
2 parents 8fad70f + eb15f8d commit 38444ad
Show file tree
Hide file tree
Showing 24 changed files with 975 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/dotnetCampus.Ipc/Context/IpcConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class IpcConfiguration
/// <summary>
/// 为 IPC 记录日志。
/// </summary>
/// <remarks>根据当前的 Ipc 名获取到日志对象,一般写法是<code>IpcLoggerProvider = name => new IpcLogger(name)</code></remarks>
public Func<string, IpcLogger>? IpcLoggerProvider { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using dotnetCampus.Ipc.Messages;
using dotnetCampus.Ipc.Utils.IO;
using dotnetCampus.Ipc.Utils.Logging;

namespace dotnetCampus.Ipc.Context.LoggingContext;

internal static class IpcContextLoggerExtension
{
/// <summary>
/// 记录接收到业务消息
/// </summary>
/// <param name="context"></param>
/// <param name="stream"></param>
/// <param name="remotePeerName"></param>
public static void LogReceiveMessage(this IpcContext context, ByteListMessageStream stream,
string remotePeerName)
{
const LogLevel logLevel = LogLevel.Debug;
if (!context.Logger.IsEnabled(logLevel))
{
return;
}

var ipcMessageBody = new IpcMessageBody(stream.GetBuffer(), (int) stream.Position,
(int) (stream.Length - stream.Position));

context.Logger.Log(logLevel, LoggerEventIds.ReceiveMessageEventId,
new ReceiveMessageBodyLogState(ipcMessageBody, context.PipeName, remotePeerName, isBusinessMessage: true),
null,
ReceiveMessageBodyLogState.Format);
}

/// <summary>
/// 记录接收到原始裸消息,包含消息头信息
/// </summary>
/// <param name="context"></param>
/// <param name="ipcMessageResult"></param>
/// <param name="remotePeerName"></param>
public static void LogReceiveOriginMessage(this IpcContext context, IpcMessageResult ipcMessageResult,
string? remotePeerName)
{
const LogLevel logLevel = LogLevel.Trace; // 一般框架信息是不关注的
if (!context.Logger.IsEnabled(logLevel))
{
return;
}

var ipcMessageBody = new IpcMessageBody(ipcMessageResult.IpcMessageContext.MessageBuffer, 0,
(int) ipcMessageResult.IpcMessageContext.MessageLength);
context.Logger.Log(logLevel, LoggerEventIds.ReceiveOriginMessageEventId,
new ReceiveMessageBodyLogState(ipcMessageBody, context.PipeName, remotePeerName, isBusinessMessage: false),
null,
ReceiveMessageBodyLogState.Format);
}

/// <summary>
/// 记录发送消息
/// </summary>
/// <param name="context"></param>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <param name="remotePeerName"></param>
public static void LogSendMessage(this IpcContext context, byte[] buffer, int offset, int count,
string remotePeerName)
{
LogSendMessage(context, new IpcMessageBody(buffer, offset, count), remotePeerName);
}

/// <summary>
/// 记录发送消息
/// </summary>
/// <param name="context"></param>
/// <param name="ipcMessageBody"></param>
/// <param name="remotePeerName"></param>
public static void LogSendMessage(this IpcContext context, in IpcMessageBody ipcMessageBody, string remotePeerName)
{
const LogLevel logLevel = LogLevel.Debug;
if (!context.Logger.IsEnabled(logLevel))
{
return;
}

context.Logger.Log(logLevel, LoggerEventIds.SendMessageEventId,
new SendMessageBodyLogState(ipcMessageBody, context.PipeName, remotePeerName),
null,
SendMessageBodyLogState.Format);
}

/// <summary>
/// 记录发送消息
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
/// <param name="remotePeerName"></param>
public static void LogSendMessage(this IpcContext context, in IpcBufferMessageContext message,
string remotePeerName)
{
const LogLevel logLevel = LogLevel.Debug;
if (!context.Logger.IsEnabled(logLevel))
{
return;
}

context.Logger.Log(logLevel, LoggerEventIds.SendMessageEventId,
new SendMessageBodiesLogState(message.IpcBufferMessageList, context.PipeName, remotePeerName), null,
SendMessageBodiesLogState.Format);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Text;
using dotnetCampus.Ipc.Messages;

namespace dotnetCampus.Ipc.Context.LoggingContext;

static class IpcMessageBodyFormatter
{
public static int GetSendHeaderLength(string localPeerName, string remotePeerName)
{
// Send from {LocalPeerName} To {RemotePeerName}:
return SendText.Length + FromText.Length + localPeerName.Length + ToText.Length +
remotePeerName.Length +
" : ".Length;
}

public static void AppendSendHeader(StringBuilder stringBuilder, string localPeerName, string remotePeerName)
{
stringBuilder.Append(SendText)
.Append(FromText)
.Append(localPeerName)
.Append(ToText)
.Append(remotePeerName)
.Append(" : ");
}

public static int GetReceiveHeaderLength(string localPeerName, string remotePeerName)
{
// Receive from {RemotePeerName} To {LocalPeerName}:
return ReceiveText.Length + FromText.Length + localPeerName.Length + ToText.Length +
remotePeerName.Length +
" : ".Length;
}

public static void AppendReceiveHeader(StringBuilder stringBuilder, string localPeerName, string remotePeerName)
{
stringBuilder.Append(ReceiveText)
.Append(FromText)
.Append(remotePeerName)
.Append(ToText)
.Append(localPeerName)
.Append(" : ");
}

public static int GetIpcMessageBodyAsBinaryLength(IpcMessageBody ipcMessageBody)
{
return ipcMessageBody.Length * 3 /*一个byte转成两个字符加一个空格*/;
}

public static void AppendIpcMessageBodyAsBinary(StringBuilder stringBuilder, in IpcMessageBody ipcMessageBody)
{
for (int i = ipcMessageBody.Start; i < ipcMessageBody.Length; i++)
{
stringBuilder.Append(ipcMessageBody.Buffer[i].ToString("X2"));
if (i != ipcMessageBody.Length - 1)
{
// 不是最后一个
stringBuilder.Append(' ');
}
}
}

private const string ReceiveText = "Receive ";
private const string SendText = "Send ";
private const string FromText = "from ";
private const string ToText = " To ";
}
53 changes: 53 additions & 0 deletions src/dotnetCampus.Ipc/Context/LoggingContext/LoggerEventIds.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using dotnetCampus.Ipc.Utils.Logging;

namespace dotnetCampus.Ipc.Context.LoggingContext;

internal static class LoggerEventIds
{
/// <summary>
/// 发送消息
/// </summary>
public static EventId SendMessageEventId => new EventId(1, "SendMessage");

/// <summary>
/// 收到框架的消息,裸消息,包括消息头
/// </summary>
public static EventId ReceiveOriginMessageEventId => new EventId(2, "ReceiveOriginMessage");

/// <summary>
/// 收到消息,业务消息
/// </summary>
public static EventId ReceiveMessageEventId => new EventId(2, "ReceiveMessage");

/// <summary>
/// 收到 JsonIpcDirectRouted 通知消息
/// </summary>
public static EventId ReceiveJsonIpcDirectRoutedNotifyEventId => new EventId(3, "ReceiveJsonIpcDirectRoutedNotify");

/// <summary>
/// 收到 JsonIpcDirectRouted 请求消息
/// </summary>
public static EventId ReceiveJsonIpcDirectRoutedRequestEventId => new EventId(4, "ReceiveJsonIpcDirectRoutedRequest");

/// <summary>
/// 发送 JsonIpcDirectRouted 响应消息
/// </summary>
/// 在 <see cref="ReceiveJsonIpcDirectRoutedRequestEventId"/> 之后返回的响应
public static EventId SendJsonIpcDirectRoutedResponseEventId => new EventId(5, "SendJsonIpcDirectRoutedResponse");

/// <summary>
/// 发送 JsonIpcDirectRouted 通知消息
/// </summary>
public static EventId SendJsonIpcDirectRoutedNotifyEventId => new EventId(6, "SendJsonIpcDirectRoutedNotify");

/// <summary>
/// 发送 JsonIpcDirectRouted 请求消息
/// </summary>
public static EventId SendJsonIpcDirectRoutedRequestEventId => new EventId(7, "SendJsonIpcDirectRoutedRequest");

/// <summary>
/// 收到 JsonIpcDirectRouted 响应消息
/// </summary>
/// 在客户端发送 <see cref="SendJsonIpcDirectRoutedRequestEventId"/> 之后收到服务端的响应
public static EventId ReceiveJsonIpcDirectRoutedResponseEventId => new EventId(8, "SendJsonIpcDirectRoutedRequest");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Text;
using dotnetCampus.Ipc.Messages;

namespace dotnetCampus.Ipc.Context.LoggingContext;

/// <summary>
/// 收到的消息
/// </summary>
public readonly struct ReceiveMessageBodyLogState
{
/// <summary>
/// 收到的消息
/// </summary>
public ReceiveMessageBodyLogState(IpcMessageBody ipcMessageBody, string localPeerName, string? remotePeerName,
bool isBusinessMessage)
{
IpcMessageBody = ipcMessageBody;
LocalPeerName = localPeerName;
IsBusinessMessage = isBusinessMessage;
RemotePeerName = remotePeerName ?? string.Empty;
}

/// <summary>
/// 是否业务消息。如果不是,那消息包含消息头
/// </summary>
public bool IsBusinessMessage { get; }

/// <summary>
/// 消息内容
/// </summary>
public IpcMessageBody IpcMessageBody { get; }

/// <summary>
/// 本地当前的 Peer 名
/// </summary>
public string LocalPeerName { get; }

/// <summary>
/// 远端对方的 Peer 名
/// </summary>
public string RemotePeerName { get; }

/// <summary>
/// 格式化为 UTF8 字符串
/// </summary>
/// <returns></returns>
public string FormatAsText()
{
return
$"Receive from {RemotePeerName} To {LocalPeerName}: {Encoding.UTF8.GetString(IpcMessageBody.Buffer, IpcMessageBody.Start, IpcMessageBody.Length)}";
}

/// <summary>
/// 格式化二进制文本
/// </summary>
/// <returns></returns>
public string FormatAsBinary()
{
var length = IpcMessageBodyFormatter.GetReceiveHeaderLength(LocalPeerName, RemotePeerName)
+ IpcMessageBodyFormatter.GetIpcMessageBodyAsBinaryLength(IpcMessageBody);
var stringBuilder = new StringBuilder(length);
IpcMessageBodyFormatter.AppendReceiveHeader(stringBuilder, LocalPeerName, RemotePeerName);
IpcMessageBodyFormatter.AppendIpcMessageBodyAsBinary(stringBuilder, IpcMessageBody);

return stringBuilder.ToString();
}

/// <summary>
/// 格式化
/// </summary>
/// <param name="state"></param>
/// <param name="exception"></param>
/// <returns></returns>
public static string Format(ReceiveMessageBodyLogState state, Exception? exception)
{
return state.FormatAsBinary();
}
}
Loading

0 comments on commit 38444ad

Please sign in to comment.