简体   繁体   中英

Allotted timeout while logging System.Net on Trace level

I'm having an issue with my program. I've created a service which is logging its actions with NLOG. Next to this service I've created a tool to catch this logging and show it to the user. This connection is based on WSDualHTTPBinding.

Besides the actions of the service, I'm also logging [System.Net], [System.ServiceModel] and [System.Windows] for a complete log report.

Now I'm getting the TimeOutException: The message could not be transferred within the allotted timeout of 00:01:00. There was nog space available in the reliable channel's transfer window. etc...

I've found out that this exception is thrown when the LogLevel for the System.Net.* is set to Trace. Otherwise the exception won't be thrown.

I've tried multiple solutions like increasing the Timeout; setting the DefaultConnectionLimit; setting the ServiceBehaviorAttribute and many more. None of them worked for me...

Could somebody help me with this?


ConsoleApplication Service:

class Program
{
    static void Main(string[] args)
    {
        IoC.Kernel.Bind<ILogging>().ToConstant(new Logging());

        try
        {
            //Normal binding
            var binding = new BasicHttpBinding();
            binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

            var host = new ServiceHost(typeof(Contract));
            host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;

            var path = "http://address:port/IContract";
            host.AddServiceEndpoint(typeof(IContract), binding, path);

            host.Open();

            //Duplex binding
            var duplexBinding = new WSDualHttpBinding();
            duplexBinding.Security.Mode = WSDualHttpSecurityMode.Message;
            duplexBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

            var duplexHost = new ServiceHost(typeof(DuplexContract));
            duplexHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;

            var duplexPath = "http://address:port/IDuplexContract";
            duplexHost.AddServiceEndpoint(typeof(IDuplexContract), duplexBinding, duplexPath);

            duplexHost.Open();
            IoC.Kernel.Get<ILogging>().Log("Listening.......");
        }
        catch (Exception ex)
        {
            IoC.Kernel.Get<ILogging>().Log(ex.ToString());
        }
        Console.ReadLine();
    }
}

Interfaces Service:

[ServiceContract]
public interface IContract
{
    [OperationContract]
    void Update(string i);
}

[ServiceContract(CallbackContract = typeof(IDuplexContractCallback), SessionMode = SessionMode.Required)]
public interface IDuplexContract
{
    [OperationContract(IsOneWay = true)]
    void AddListener();
}

public interface IDuplexContractCallback
{
    [OperationContract(IsOneWay = true)]
    void Logger(string obj);
    [OperationContract(IsOneWay = true)]
    void ReceivedCalculate(int i);
}

public interface ILogging
{
    void Log(string message);
    void AddObserver(Action<string> addEventLog);
}

Implementations Service:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class DuplexContract : IDuplexContract
{
    public void AddListener()
    {
        IoC.Kernel.Get<ILogging>().AddObserver(OperationContext.Current.GetCallbackChannel<IDuplexContractCallback>().Logger);
        IoC.Kernel.Get<ILogging>().Log("Added listener");
    }
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Contract : IContract
{
    public void Update(string i)
    {
        IoC.Kernel.Get<ILogging>().Log(string.Format("Received: {0}", i));
    }
}

public class Logging : ILogging
{
    public Logging()
    {
        if (LogManager.Configuration == null)
        {
            LogManager.Configuration = new LoggingConfiguration();
        }

        Target consoleTarget;
        consoleTarget = LogManager.Configuration.FindTargetByName(nameof(consoleTarget));
        if (consoleTarget == null)
        {
            consoleTarget = new ColoredConsoleTarget()
            {
                Layout = "${longdate} [${logger}] [${level:uppercase=true}]: ${message} ${onexception:inner=${newline} ${exception:format=ToString:maxInnerExceptionLevel=4:innerFormat=ToString:seperator=\r\n}}",
                Name = nameof(consoleTarget),
                UseDefaultRowHighlightingRules = false,
            };
            (consoleTarget as ColoredConsoleTarget).RowHighlightingRules.Add(new ConsoleRowHighlightingRule(ConditionParser.ParseExpression("level == LogLevel.Fatal"), ConsoleOutputColor.Magenta, ConsoleOutputColor.NoChange));
            (consoleTarget as ColoredConsoleTarget).RowHighlightingRules.Add(new ConsoleRowHighlightingRule(ConditionParser.ParseExpression("level == LogLevel.Error"), ConsoleOutputColor.Red, ConsoleOutputColor.NoChange));
            (consoleTarget as ColoredConsoleTarget).RowHighlightingRules.Add(new ConsoleRowHighlightingRule(ConditionParser.ParseExpression("level == LogLevel.Warn"), ConsoleOutputColor.Yellow, ConsoleOutputColor.NoChange));
            (consoleTarget as ColoredConsoleTarget).RowHighlightingRules.Add(new ConsoleRowHighlightingRule(ConditionParser.ParseExpression("level == LogLevel.Info"), ConsoleOutputColor.White, ConsoleOutputColor.NoChange));
            (consoleTarget as ColoredConsoleTarget).RowHighlightingRules.Add(new ConsoleRowHighlightingRule(ConditionParser.ParseExpression("level == LogLevel.Debug"), ConsoleOutputColor.Gray, ConsoleOutputColor.NoChange));
            (consoleTarget as ColoredConsoleTarget).RowHighlightingRules.Add(new ConsoleRowHighlightingRule(ConditionParser.ParseExpression("level == LogLevel.Trace"), ConsoleOutputColor.DarkGray, ConsoleOutputColor.NoChange));
            LogManager.Configuration.AddTarget(consoleTarget);
        }

        UpdateRules(consoleTarget);
        LogManager.ReconfigExistingLoggers();
    }

    public void Log(string message)
    {
        LogManager.GetLogger("CustomLogger").Trace(message);
    }

    private void UpdateRules(Target target)
    {
        var rules = LogManager.Configuration.LoggingRules.Where(u => u.Targets.Contains(target)).ToList();
        rules.ForEach(u => LogManager.Configuration.LoggingRules.Remove(u));

        LogManager.Configuration.LoggingRules.Add(new LoggingRule("System.Net.*", LogLevel.Trace, target)); //<-- Throws the exception
        LogManager.Configuration.LoggingRules.Add(new LoggingRule("System.ServiceModel.*", LogLevel.Trace, target));
        LogManager.Configuration.LoggingRules.Add(new LoggingRule("System.Windows.*", LogLevel.Trace, target));
        LogManager.Configuration.LoggingRules.Add(new LoggingRule("CustomLogger", LogLevel.Trace, target));
    }

    public void AddObserver(Action<string> addEventLog)
    {
        Target duplexCallbackTarget;
        duplexCallbackTarget = LogManager.Configuration.FindTargetByName(nameof(DuplexCallbackTarget));
        if (duplexCallbackTarget == null)
        {
            var layout = new XmlLayout();
            duplexCallbackTarget = new DuplexCallbackTarget()
            {
                Name = nameof(DuplexCallbackTarget),
                Layout = layout,
                CallbackAction = addEventLog,
            };
            LogManager.Configuration.AddTarget(duplexCallbackTarget);
        }
        UpdateRules(duplexCallbackTarget);
        LogManager.ReconfigExistingLoggers();
    }
}

[Target("DuplexCallback")]
public class DuplexCallbackTarget : TargetWithLayout
{
    /// <summary>
    /// The callback action from the client event viewer.
    /// </summary>
    public Action<string> CallbackAction { get; set; }

    /// <summary>
    /// Writes the specified log event information.
    /// </summary>
    /// <param name="logEventInfo">The log event information.</param>
    protected override void Write(LogEventInfo logEventInfo)
    {
        try
        {
            CallbackAction(logEventInfo.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

//Ninject
public static class IoC
{
    public static IKernel Kernel = new StandardKernel();
}

Implementation Listener:

public class ContractCallback : IDuplexContractCallback
{
    public void Logger(string obj)
    {
        Console.WriteLine(string.Format("Client received: {0}", obj));
    }

    public void ReceivedCalculate(int i)
    {
        Console.WriteLine(string.Format("Client received: {0}", i));
    }
}

ConsoleWindow Listener:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Waiting for server to be ready...");
        Console.ReadLine();

        var binding = new WSDualHttpBinding();
        binding.Security.Mode = WSDualHttpSecurityMode.Message;
        binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

        var factory = new DuplexChannelFactory<IDuplexContract>(new InstanceContext(new ContractCallback()), binding, new EndpointAddress("http://address:port/IDuplexContract"));
        var channel = factory.CreateChannel();
        channel.AddListener();
        Console.WriteLine("Listening at server....");
        Console.ReadLine();
    }
}

ConsoleWindow Client:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Waiting for server & listener to be ready...");
        Console.ReadLine();

        var binding = new BasicHttpBinding();
        binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

        var factory = new ChannelFactory<IContract>(binding, new EndpointAddress("http://address:port/IContract"));
        var channel = factory.CreateChannel();

        while (true)
        {
            channel.Update(Console.ReadLine());
        }
    }
}

The issue is an infinity loop. This is created by the System.Net class because when I'm calling my Callback function the System.Net namespace is tracing my call to the next server with the http message. This is logged and sent to the logger, etc, etc, etc...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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