Example #1
0
        /// <summary>
        /// Clear previous jobs
        /// </summary>
        private void ClearRecurringJobs()
        {
            try
            {
                using IStorageConnection connection = JobStorage.Current.GetConnection();
                foreach (RecurringJobDto recurringJob in connection.GetRecurringJobs())
                {
                    if (recurringJob != null)
                    {
                        RecurringJob.RemoveIfExists(recurringJob.Id);
                    }
                }

                IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();
                while (monitoringApi.Servers().Count > 1)
                {
                    var serverToRemove = monitoringApi.Servers().Last();
                    connection.RemoveServer(serverToRemove.Name);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
        private static int serverCountFromHangfire(IMonitoringApi monitor)
        {
            var       runningServerCount = _retry.Execute(() => monitor.Servers().Count);
            const int startingServer     = 1;

            return(runningServerCount + startingServer);
        }
Example #3
0
        public static void RemoveUnusedHangfireServers(this IApplicationBuilder app)
        {
            IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();

            foreach (var item in monitoringApi.Servers())
            {
                var name = item.Name.Split(':')[0];

                if (!_options.HangfireServerName.Any(x => x.ToLower().Equals(name.ToLower())))
                {
                    JobStorage.Current.GetConnection().RemoveServer(item.Name);
                }
            }
        }
Example #4
0
        public static void SetupHangfireServers(this IApplicationBuilder app)
        {
            IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();

            foreach (var item in _options.HangfireServerName)
            {
                if (!monitoringApi.Servers().Any(x => x.Name.ToLower().Contains(item.ToLower())))
                {
                    var options = new BackgroundJobServerOptions
                    {
                        ServerName = $"{item}"
                    };
                    app.UseHangfireServer(options);
                }
            }
        }
Example #5
0
        public bool BackgroundWorkers()
        {
            IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();

            return(monitoringApi.Servers().Any());
        }
        /// <summary>
        /// Checks various HangFire settings, i.e., failing jobs and a positive number of servers
        /// </summary>
        /// <param name="context"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            _logger.LogInformation("Health check HangFire");

            var status = HealthStatus.Healthy;
            var data   = new Dictionary <string, object>();

            // Check servers
            var servers = _hangFireMonitoringApi.Servers();

            if (servers.Count < 1)
            {
                var message = $"Number of servers is less than expected at time {DateTime.Now}";
                _logger.LogWarning(message);
                status = HealthStatus.Unhealthy;
                data.Add(message, servers.Count);
            }

            // Check status of recurring jobs
            var recurringJobs           = _healthCheckHangFireService.GetRecurringJobs();
            var noOfActuallyEnabledJobs = recurringJobs.Count(j => j.NextExecution != null);
            var noOfExpectedEnabledJobs = _appSettingsConfig.HealthCheckSettings.NoOfEnabledJobs;

            if (noOfActuallyEnabledJobs < noOfExpectedEnabledJobs)
            {
                var message = $"Number of enabled jobs is less than expected at time {DateTime.Now}. Expected:{noOfExpectedEnabledJobs} - Actual:{noOfActuallyEnabledJobs}";
                _logger.LogWarning(message);
                status = HealthStatus.Unhealthy;
                data.Add(message, noOfActuallyEnabledJobs);

                var enabledJobIds = _appSettingsConfig.HealthCheckSettings.EnabledJobIds;
                foreach (var jobId in enabledJobIds)
                {
                    var job = recurringJobs.First(j => j.Id == jobId);
                    if (job.NextExecution != null)
                    {
                        continue;
                    }

                    var jobMessage = $"Job '{jobId}' is not enabled as expected";
                    _logger.LogWarning(jobMessage);
                    status = HealthStatus.Unhealthy;
                    var info = job.LastExecution != null
                        ? $"Last execution time: {job.LastExecution}"
                        : $"No last execution time for {jobId}";
                    data.Add(jobMessage, info);
                }
            }

            // Check failing jobs
            var failingJobsCount = _hangFireMonitoringApi.FailedCount();

            if (failingJobsCount > 0)
            {
                status = HealthStatus.Unhealthy;
                data.Add("failed jobs count", failingJobsCount);

                _logger.LogWarning("HangFire has one or more failed jobs");

                var jobs = _hangFireMonitoringApi.FailedJobs(0, 10);
                foreach (var job in jobs)
                {
                    var key = job.Key;
                    var val = job.Value;
                    _logger.LogWarning($"Failed job ID '{key}' - {val.ExceptionDetails} - {val.ExceptionMessage}");

                    try
                    {
                        var serializedVal = JsonSerializer.Serialize(val, val.GetType());
                        data.Add($"Job ID {key}", serializedVal);
                    }
                    catch (Exception e)
                    {
                        var errorMessage = $"Error in health check HangFire. {e.Message} - {e.StackTrace}";
                        _logger.LogError(errorMessage);

                        // Adding extra details from the failed job to data
                        var failedJobDetails = $"JOB FAILED: EXCEPTION DETAILS: {val.ExceptionDetails} - EXCEPTION MESSAGE: {val.ExceptionMessage} - EXCEPTION TYPE: {val.ExceptionType} - FAILED AT: {val.FailedAt}";
                        data.Add($"Job ID {key}. HangFire health check could not serialize class {val.GetType()}", failedJobDetails);

                        return(Task.FromResult(new HealthCheckResult(
                                                   status,
                                                   Description,
                                                   e,
                                                   data)));
                    }
                }
            }

            if (data.Count == 0)
            {
                data.Add("State", "HangFire jobs and servers are in expected state");
            }

            return(Task.FromResult(new HealthCheckResult(
                                       status,
                                       Description,
                                       data: data)));
        }