WCF 客户端日志记录 dotnet 核心

WCF client logging dotnet core

我在 windows 上使用 asp.net 核心 并且有一个 类 由 dotnet 生成的文件-svcutil。我正在使用 nlog 进行日志记录。有没有一种方法可以记录进出外部服务的所有 原始请求和响应

已经尝试过 logman https://github.com/dotnet/wcf/blob/master/Documentation/HowToUseETW.md,但首先 - 它不显示原始肥皂,仅显示事件,其次 - 我需要由配置的 nlog 记录日志。

在这里找到答案: https://docs.microsoft.com/en-us/dotnet/framework/wcf/extending/how-to-inspect-or-modify-messages-on-the-client

操作顺序:

  1. Implement the System.ServiceModel.Dispatcher.IClientMessageInspector interface. Here you can inspect/modify/log messages
  2. Implement a System.ServiceModel.Description.IEndpointBehavior or System.ServiceModel.Description.IContractBehavior depending upon the scope at which you want to insert the client message inspector. System.ServiceModel.Description.IEndpointBehavior allows you to change behavior at the endpoint level. System.ServiceModel.Description.IContractBehavior allows you to change behavior at the contract level.
  3. Insert the behavior prior to calling the ClientBase.Open or the ICommunicationObject.Open method on the System.ServiceModel.ChannelFactory.

行为:

public class LoggingEndpointBehaviour : IEndpointBehavior
{
    public LoggingMessageInspector MessageInspector { get; }

    public LoggingEndpointBehaviour(LoggingMessageInspector messageInspector)
    {
        MessageInspector = messageInspector ?? throw new ArgumentNullException(nameof(messageInspector));
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(MessageInspector);
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

检查员:

 public class LoggingMessageInspector : IClientMessageInspector
{
    public LoggingMessageInspector(ILogger<LoggingMessageInspector> logger)
    {
        Logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
    }

    public ILogger<LoggingMessageInspector> Logger { get; }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        using (var buffer = reply.CreateBufferedCopy(int.MaxValue))
        {
            var document = GetDocument(buffer.CreateMessage());
            Logger.LogTrace(document.OuterXml);

            reply = buffer.CreateMessage();
        }
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        using (var buffer = request.CreateBufferedCopy(int.MaxValue))
        {
            var document = GetDocument(buffer.CreateMessage());
            Logger.LogTrace(document.OuterXml);

            request = buffer.CreateMessage();
            return null;
        }
    }

    private XmlDocument GetDocument(Message request)
    {
        XmlDocument document = new XmlDocument();
        using (MemoryStream memoryStream = new MemoryStream())
        {
            // write request to memory stream
            XmlWriter writer = XmlWriter.Create(memoryStream);
            request.WriteMessage(writer);
            writer.Flush();
            memoryStream.Position = 0;

            // load memory stream into a document
            document.Load(memoryStream);
        }

        return document;
    }
}

用法:

 if (configuration.GetValue<bool>("Logging:MessageContent"))
     client.Endpoint.EndpointBehaviors.Add(serviceProvider.GetRequiredService<LoggingEndpointBehaviour>());