简体   繁体   English

WCF 跟踪ASP.NET核心

[英]WCF Tracing in ASP.NET Core

We used to use WCF over ASP.NET and recently switched to WCF over ASP.NET Core.我们过去使用 WCF 而不是 ASP.NET,最近切换到 WCF 而不是 ASP.NET 核心。 This was quite hard to implement because ASP.Net Core doesn't support WCF out of the box.这很难实现,因为 ASP.Net Core 不支持开箱即用的 WCF。 For one thing, the whole web.config XML configuration model has been dumped in ASP.NET Core so we cannot configure WCF tracing there.一方面,整个 web.config XML 配置 model 已被转储到 ASP.NET 核心中,因此我们无法在那里配置 WCF 跟踪。

Ie this document is useless: https://learn.microsoft.com/en-us/do.net/framework/wcf/diagnostics/tracing/configuring-tracing即这个文件没用: https://learn.microsoft.com/en-us/do.net/framework/wcf/diagnostics/tracing/configuring-tracing

We had to hack ASP.NET Core by putting a http proxy between WCF and port 80. WCF is actually running on another port.我们不得不通过在 WCF 和端口 80 之间放置一个 http 代理来破解 ASP.NET 核心。WCF 实际上在另一个端口上运行。

The question is, how do we enable WCF tracing if ASP.NET Core doesn't pay attention to the web.config?问题是,如果 ASP.NET Core 不关注 web.config,我们如何启用 WCF 跟踪?

You'll use ETW Tracing for WCF on .NET Core 您将在.NET Core上使用ETW Tracing for WCF

https://github.com/dotnet/wcf/blob/master/Documentation/HowToUseETW.md https://github.com/dotnet/wcf/blob/master/Documentation/HowToUseETW.md

In my experience, you have some limitations 根据我的经验,你有一些限制

  1. Tracing is on for All WCF Apps, rather than configuring for a single app through config file 所有WCF应用程序都在进行跟踪,而不是通过配置文件配置单个应用程序
  2. You cannot output Messages with ETW tracing 您无法使用ETW跟踪输出消息
  3. SvcTraceViewer.exe doesn't work well for trace review, you'll need to move to PerfView.exe which may present a learning curve SvcTraceViewer.exe无法用于跟踪审查,您需要转移到可能呈现学习曲线的PerfView.exe

Benefits of ETW ETW的好处

  1. You avoid the performance hit from classic forms of tracing 您可以避免经典形式的跟踪造成的性能损失
  2. No more config change to start/stop tracing 没有更多的配置更改来启动/停止跟踪

In case of client side tracing I used custom endpoint behaviour ( IEndpointBehavior ) with custom message logging inspector ( IClientMessageInspector ) to get input and output messages. 在客户端侧的情况下,跟踪我使用的自定义端点行为( IEndpointBehavior )使用定制信息记录检查器( IClientMessageInspector ),以获得输入和输出消息。

Client initialization: 客户初始化:

_serviceClient = new MyCustomServiceClient();
_serviceClient.Endpoint.Address = new System.ServiceModel.EndpointAddress(_configParams.ServiceUri);
_serviceClient.Endpoint.EndpointBehaviors.Add(new EndpointLoggingBehavior("MyCustomService"));

Implementation of EndpointLoggingBehavior : EndpointLoggingBehavior实现:

public class EndpointLoggingBehavior : IEndpointBehavior
    {
        public EndpointLoggingBehavior(string serviceName)
        {
            _serviceName = serviceName;
        }

        private readonly string _serviceName;

        public void AddBindingParameters(ServiceEndpoint endpoint,
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

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

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

        public void Validate(ServiceEndpoint endpoint)
        {
        }
    }

Implementation of MessageLoggingInspector : MessageLoggingInspector实现:

public class MessageLoggingInspector : IClientMessageInspector
    {
        private readonly string _serviceName;
        public MessageLoggingInspector(string serviceName)
        {
            _serviceName = serviceName;
        }
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            // copying message to buffer to avoid accidental corruption
            var buffer = reply.CreateBufferedCopy(int.MaxValue);
            reply = buffer.CreateMessage();
            // creating copy
            var copy = buffer.CreateMessage();
            //getting full input message
            var fullInputMessage = copy.ToString();

        }
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            // copying message to buffer to avoid accidental corruption
            var buffer = request.CreateBufferedCopy(int.MaxValue);
            request = buffer.CreateMessage();
            // creating copy
            var copy = buffer.CreateMessage();
            //getting full output message
            var fullOutputMessage = copy.ToString();
            return null;
        }
    }

Then, of course, you will need to write these messages to any storage. 然后,当然,您需要将这些消息写入任何存储。

Building on the excellent answer by Petr Pokrovskiy, this is how you can redirect the trace to the standard .NET Core log:基于 Petr Pokrovskiy 的出色回答,您可以通过以下方式将跟踪重定向到标准 .NET 核心日志:

Client initialization:客户端初始化:

ILogger<MyCustomService> = ...; // use dependency injection to get instance
_serviceClient = new MyCustomServiceClient();
_serviceClient.Endpoint.Address = new System.ServiceModel.EndpointAddress(_configParams.ServiceUri);
_serviceClient.Endpoint.SetTraceLogging(logger);

Implementation of SetTraceLogging: SetTraceLogging 的实现:

using Microsoft.Extensions.Logging;
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace Common.ServiceModel.Logging
{
    public static class ServiceEndpointExtensions
    {
        public static void SetTraceLogging(this ServiceEndpoint serviceEndpoint, ILogger logger)
        {
            if (logger == null)
                throw new ArgumentNullException(nameof(logger));
            if (logger.IsEnabled(LogLevel.Trace))
                serviceEndpoint.EndpointBehaviors.Add(new ClientMessageLoggingBehavior(logger));
        }
    }

    internal sealed class ClientMessageLoggingBehavior :
        IEndpointBehavior
    {
        private readonly ILogger _logger;

        public ClientMessageLoggingBehavior(ILogger logger)
        {
            _logger = logger;
        }

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

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

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

        public void Validate(ServiceEndpoint endpoint)
        {
        }
    }

    internal sealed class ClientMessageLogger :
        IClientMessageInspector
    {
        private readonly ILogger _logger;

        public ClientMessageLogger(ILogger logger)
        {
            this._logger = logger;
        }

        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            // copying message to buffer to avoid accidental corruption
            reply = Clone(reply);
            this._logger.LogTrace("Received SOAP reply:\r\n{0}", reply.ToString());

        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            // copying message to buffer to avoid accidental corruption
            request = Clone(request);
            this._logger.LogTrace("Sending SOAP request:\r\n{0}", request.ToString());
            return null;
        }

        private static Message Clone(Message message)
        {
            return message.CreateBufferedCopy(int.MaxValue).CreateMessage();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM