Base solution for your next web application
Open Closed

How to get a Logger in an attribute class? #1309


User avatar
0
morindo created

Hi,

I'm trying to create an attribute class and I would like to get the ILogger but I'm getting a null reference, how can I inject the ILogger into an attribute class?

I've tried to register the class with an ITransientDependency and also in the PreInitialize() method:

IocManager.Register<SkipConcurrentExecutionAttribute>(DependencyLifeStyle.Transient);

Thank you,

/// <summary>
    /// Attribute to skip a job execution if the same job is already running.
    /// Mostly taken from: http://discuss.hangfire.io/t/job-reentrancy-avoidance-proposal/607
    /// </summary>
    public class SkipConcurrentExecutionAttribute : JobFilterAttribute, IServerFilter
    {
        public ILogger Logger { get; set; }

        private readonly int _timeoutInSeconds = 1;

        public SkipConcurrentExecutionAttribute()
        {
            Logger = NullLogger.Instance;
        }

        public SkipConcurrentExecutionAttribute(int timeoutInSeconds) : this()
        {
            if (timeoutInSeconds < 0) throw new ArgumentException("Timeout argument value should be greater that zero.");

            _timeoutInSeconds = timeoutInSeconds;
        }


        public void OnPerforming(PerformingContext filterContext)
        {
            var resource = String.Format(
                                 "{0}.{1}",
                                filterContext.Job.Type.FullName,
                                filterContext.Job.Method.Name);

            var timeout = TimeSpan.FromSeconds(_timeoutInSeconds);

            try
            {
                var distributedLock = filterContext.Connection.AcquireDistributedLock(resource, timeout);
                filterContext.Items["DistributedLock"] = distributedLock;
            }
            catch (Exception)
            {
                filterContext.Canceled = true;
                Logger.WarnFormat("Cancelling run for {0} job, id: {1} ", resource, filterContext.JobId); // Not logging anything...
            }
        }

        public void OnPerformed(PerformedContext filterContext)
        {
            if (!filterContext.Items.ContainsKey("DistributedLock"))
            {
                throw new InvalidOperationException("Can not release a distributed lock: it was not acquired.");
            }

            var distributedLock = (IDisposable)filterContext.Items["DistributedLock"];
            distributedLock.Dispose();
        }
    }

1 Answer(s)
  • User Avatar
    0
    morindo created

    Okay, I found a way.

    I created this SkipConcurrentExecutionAttribute class for Hangfire in order to skip concurrent task execution. Since Hangfire already supports logging with Log4Net, I've used the LogProvider.GetCurrentClassLogger() method to get the logger.

    See Hangfire documentation - Configuring logging [http://docs.hangfire.io/en/latest/configuration/configuring-logging.html])

    /// <summary>
        /// Attribute to skip a job execution if the same job is already running.
        /// Mostly taken from: http://discuss.hangfire.io/t/job-reentrancy-avoidance-proposal/607
        /// </summary>
        public class SkipConcurrentExecutionAttribute : JobFilterAttribute, IServerFilter
        {
            private static readonly ILog Logger = LogProvider.GetCurrentClassLogger();
    
            private readonly int _timeoutInSeconds = 1;
    
            public SkipConcurrentExecutionAttribute()
            {
            }
    
            public SkipConcurrentExecutionAttribute(int timeoutInSeconds) : this()
            {
                if (timeoutInSeconds < 0) throw new ArgumentException("Timeout argument value should be greater that zero.");
    
                _timeoutInSeconds = timeoutInSeconds;
            }
    
    
            public void OnPerforming(PerformingContext filterContext)
            {
                var resource = String.Format(
                                     "{0}.{1}",
                                    filterContext.Job.Type.FullName,
                                    filterContext.Job.Method.Name);
    
                var timeout = TimeSpan.FromSeconds(_timeoutInSeconds);
    
                try
                {
                    var distributedLock = filterContext.Connection.AcquireDistributedLock(resource, timeout);
                    filterContext.Items["DistributedLock"] = distributedLock;
                }
                catch (Exception)
                {
                    filterContext.Canceled = true;
                    Logger.WarnFormat("Cancelling run for {0} job, id: {1} ", resource, filterContext.JobId);
                }
            }
    
            public void OnPerformed(PerformedContext filterContext)
            {
                if (!filterContext.Items.ContainsKey("DistributedLock"))
                {
                    throw new InvalidOperationException("Can not release a distributed lock: it was not acquired.");
                }
    
                var distributedLock = (IDisposable)filterContext.Items["DistributedLock"];
                distributedLock.Dispose();
            }
        }