ASP.NET C#

Listening to IIS Application pool recycle events in ASP.NET

One of my .NET apps was having some strange issues. It was attached to an IIS app pool, so it was possible that the app pool was recycling due to some other application’s events or otherwise. I decided to create a listener to detect whenever the app pool was recycling and log what was causing it.

Here’s the class created to listen for recycling events:

public class ApplicationPoolRecycleListener
{
    public enum RecycleReason
    {
        IisReset = 3202,
        ReachedProcessingTimeLimit = 5074,
        ReachedAllowedRequestLimit = 5075,
        ReachedScheduledRecycleTime = 5076,
        ReachedVirtualMemoryLimit = 5077,
        ReachedPrivateBytesMemoryLimit = 5117,
        AdministratorRequest = 5079,
        AppPoolConfigurationChange = 5080,
        IisConfigurationError = 5081
    }

    private readonly string _targetApplicationPoolName;
    private bool _stopListening;

    public Func<EntryWrittenEventArgs, RecycleReason, bool> OnTargetApplicationRecycled { get; set; }
    public Func<EntryWrittenEventArgs, RecycleReason, bool> OnNonTargetApplicationRecycled { get; set; }

    public ApplicationPoolRecycleListener(string targetApplicationPoolName)
    {
        _targetApplicationPoolName = targetApplicationPoolName;
        _stopListening = false;
    }

    public void StartListening()
    {
        var eventLog = new EventLog { Log = "System", EnableRaisingEvents = true };
        eventLog.EntryWritten += EventWrittenCallback;

        var eventLog2 = new EventLog { Log = "Application", EnableRaisingEvents = true };
        eventLog2.EntryWritten += EventWrittenCallback;
        while (_stopListening == false) { }
    }

    private void EventWrittenCallback(object sender, EntryWrittenEventArgs e)
    {
        var eventId = e.Entry.EventID;

        if (Enum.IsDefined(typeof (RecycleReason), eventId))
        {
            var recycleReason = (RecycleReason)eventId;

            if (recycleReason == RecycleReason.IisReset)
            {
                _stopListening = OnTargetApplicationRecycled?.Invoke(e, recycleReason) ?? false;
            }
            else
            {
                if (e.Entry.Message.ToLower().Contains($"serving application pool '{_targetApplicationPoolName.ToLower()}'"))
                {
                    _stopListening = OnTargetApplicationRecycled?.Invoke(e, recycleReason) ?? false;
                }
                else
                {
                    _stopListening = OnNonTargetApplicationRecycled?.Invoke(e, recycleReason) ?? false;
                }
            }
        }
    }
}

Now I was able to debug or log to detect why the recycling was occuring.

Example use:

using System;
using System.Diagnostics;
using System.Net;

namespace EventLogListener
{
    class Program
    {
        static void Main(string[] args)
        {
            var listener = new ApplicationPoolRecycleListener("StreamingServer")
            {
                OnTargetApplicationRecycled = (entry, recycleReason) =>
                {
                    // do something
                    return true;
                },

                OnNonTargetApplicationRecycled = (entry, recycleReason) =>
                {
                    // do something
                    return true;
                }
            };

            listener.StartListening();
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *