public async Task SendAsync(HealthCheckResults results)
        {
            if (ShouldSend(results) == false)
            {
                return;
            }

            if (string.IsNullOrEmpty(RecipientEmail))
            {
                return;
            }

            var message = _textService.Localize("healthcheck/scheduledHealthCheckEmailBody", new[]
            {
                DateTime.Now.ToShortDateString(),
                DateTime.Now.ToShortTimeString(),
                results.ResultsAsHtml(Verbosity)
            });

            var subject = _textService.Localize("healthcheck/scheduledHealthCheckEmailSubject");

            var mailSender = new EmailSender();

            using (var mailMessage = new MailMessage(UmbracoConfig.For.UmbracoSettings().Content.NotificationEmailAddress,
                                                     RecipientEmail,
                                                     string.IsNullOrEmpty(subject) ? "Umbraco Health Check Status" : subject,
                                                     message)
            {
                IsBodyHtml = message.IsNullOrWhiteSpace() == false &&
                             message.Contains("<") && message.Contains("</")
            })
            {
                await mailSender.SendAsync(mailMessage);
            }
        }
示例#2
0
        public override async Task SendAsync(HealthCheckResults results)
        {
            if (ShouldSend(results) == false)
            {
                return;
            }

            if (string.IsNullOrEmpty(RecipientEmail))
            {
                return;
            }

            var message = _textService?.Localize("healthcheck", "scheduledHealthCheckEmailBody", new[]
            {
                DateTime.Now.ToShortDateString(),
                DateTime.Now.ToShortTimeString(),
                _markdownToHtmlConverter?.ToHtml(results, Verbosity)
            });

            // Include the umbraco Application URL host in the message subject so that
            // you can identify the site that these results are for.
            var host = _hostingEnvironment?.ApplicationMainUrl?.ToString();

            var subject = _textService?.Localize("healthcheck", "scheduledHealthCheckEmailSubject", new[] { host });


            var  mailMessage = CreateMailMessage(subject, message);
            Task?task        = _emailSender?.SendAsync(mailMessage, Constants.Web.EmailTypes.HealthCheck);

            if (task is not null)
            {
                await task;
            }
        }
示例#3
0
        public override async Task SendAsync(HealthCheckResults results, CancellationToken token)
        {
            if (ShouldSend(results) == false)
            {
                return;
            }

            if (string.IsNullOrEmpty(RecipientEmail))
            {
                return;
            }

            var message = _textService.Localize("healthcheck/scheduledHealthCheckEmailBody", new[]
            {
                DateTime.Now.ToShortDateString(),
                DateTime.Now.ToShortTimeString(),
                results.ResultsAsHtml(Verbosity)
            });

            // Include the umbraco Application URL host in the message subject so that
            // you can identify the site that these results are for.
            var host = _runtimeState.ApplicationUrl;

            var subject = _textService.Localize("healthcheck/scheduledHealthCheckEmailSubject", new[] { host.ToString() });

            var mailSender = new EmailSender();

            using (var mailMessage = CreateMailMessage(subject, message))
            {
                await mailSender.SendAsync(mailMessage);
            }
        }
        public string ToHtml(HealthCheckResults results, HealthCheckNotificationVerbosity verbosity)
        {
            var mark = new Markdown();
            var html = mark.Transform(results.ResultsAsMarkDown(verbosity));

            html = ApplyHtmlHighlighting(html);
            return(html);
        }
示例#5
0
 protected void Page_Load(object sender, EventArgs e)
 {
     this.RegisterAsyncTask(new PageAsyncTask(async() =>
     {
         var healthCheckManager  = DependencyLocator.Current.GetInstance <IHealthCheckManager>();
         this.HealthCheckResults = await healthCheckManager.CheckHealth();
     }));
 }
示例#6
0
        public override async Task PerformExecuteAsync(object?state)
        {
            if (_healthChecksSettings.Notification.Enabled == false)
            {
                return;
            }

            if (_runtimeState.Level != RuntimeLevel.Run)
            {
                return;
            }

            switch (_serverRegistrar.CurrentServerRole)
            {
            case ServerRole.Subscriber:
                _logger.LogDebug("Does not run on subscriber servers.");
                return;

            case ServerRole.Unknown:
                _logger.LogDebug("Does not run on servers with unknown role.");
                return;
            }

            // Ensure we do not run if not main domain, but do NOT lock it
            if (_mainDom.IsMainDom == false)
            {
                _logger.LogDebug("Does not run if not MainDom.");
                return;
            }

            // Ensure we use an explicit scope since we are running on a background thread and plugin health
            // checks can be making service/database calls so we want to ensure the CallContext/Ambient scope
            // isn't used since that can be problematic.
            using (ICoreScope scope = _scopeProvider.CreateCoreScope())
                using (_profilingLogger.DebugDuration <HealthCheckNotifier>("Health checks executing", "Health checks complete"))
                {
                    // Don't notify for any checks that are disabled, nor for any disabled just for notifications.
                    Guid[] disabledCheckIds = _healthChecksSettings.Notification.DisabledChecks
                                              .Select(x => x.Id)
                                              .Union(_healthChecksSettings.DisabledChecks
                                                     .Select(x => x.Id))
                                              .Distinct()
                                              .ToArray();

                    IEnumerable <HealthCheck> checks = _healthChecks
                                                       .Where(x => disabledCheckIds.Contains(x.Id) == false);

                    var results = await HealthCheckResults.Create(checks);

                    results.LogResults();

                    // Send using registered notification methods that are enabled.
                    foreach (IHealthCheckNotificationMethod notificationMethod in _notifications.Where(x => x.Enabled))
                    {
                        await notificationMethod.SendAsync(results);
                    }
                }
        }
示例#7
0
        public async Task <HealthCheckResults> GetHealthAsync(
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var healthCheckResults = new HealthCheckResults();

            var tasks = _healthChecks.Select(c => new { name = c.Key, result = c.Value.CheckHealthAsync() });

            var sw = new Stopwatch();

            foreach (var task in tasks)
            {
                try
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    sw.Reset();
                    sw.Start();
                    var result = await task.result;
                    sw.Stop();
                    healthCheckResults.Entries.Add(task.name,
                                                   new HealthCheckResultExtended(result)
                    {
                        ResponseTime = sw.ElapsedMilliseconds
                    });
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch
                {
                    healthCheckResults.Entries.Add(task.name,
                                                   new HealthCheckResultExtended(new HealthCheckResult(HealthStatus.Unhealthy)));
                }
            }

            var status = HealthStatus.Healthy;

            foreach (var healthCheckResultExtended in healthCheckResults.Entries.Values)
            {
                if (healthCheckResultExtended.Status == HealthStatus.Unhealthy)
                {
                    status = HealthStatus.Unhealthy;
                    break;
                }

                if (healthCheckResultExtended.Status == HealthStatus.Degraded)
                {
                    status = HealthStatus.Degraded;
                }
            }

            healthCheckResults.Status            = status;
            healthCheckResults.TotalResponseTime = healthCheckResults.Entries.Values.Sum(c => c.ResponseTime);

            return(healthCheckResults);
        }
示例#8
0
        public override async Task <bool> PerformRunAsync(CancellationToken token)
        {
            if (_runtimeState.Level != RuntimeLevel.Run)
            {
                return(true); // repeat...
            }
            switch (_runtimeState.ServerRole)
            {
            case ServerRole.Replica:
                _logger.Debug <HealthCheckNotifier>("Does not run on replica servers.");
                return(true);    // DO repeat, server role can change

            case ServerRole.Unknown:
                _logger.Debug <HealthCheckNotifier>("Does not run on servers with unknown role.");
                return(true);    // DO repeat, server role can change
            }

            // ensure we do not run if not main domain, but do NOT lock it
            if (_runtimeState.IsMainDom == false)
            {
                _logger.Debug <HealthCheckNotifier>("Does not run if not MainDom.");
                return(false); // do NOT repeat, going down
            }

            // Ensure we use an explicit scope since we are running on a background thread and plugin health
            // checks can be making service/database calls so we want to ensure the CallContext/Ambient scope
            // isn't used since that can be problematic.
            using (var scope = _scopeProvider.CreateScope())
                using (_logger.DebugDuration <HealthCheckNotifier>("Health checks executing", "Health checks complete"))
                {
                    var healthCheckConfig = Current.Configs.HealthChecks();

                    // Don't notify for any checks that are disabled, nor for any disabled
                    // just for notifications
                    var disabledCheckIds = healthCheckConfig.NotificationSettings.DisabledChecks
                                           .Select(x => x.Id)
                                           .Union(healthCheckConfig.DisabledChecks
                                                  .Select(x => x.Id))
                                           .Distinct()
                                           .ToArray();

                    var checks = _healthChecks
                                 .Where(x => disabledCheckIds.Contains(x.Id) == false);

                    var results = new HealthCheckResults(checks);
                    results.LogResults();

                    // Send using registered notification methods that are enabled
                    foreach (var notificationMethod in _notifications.Where(x => x.Enabled))
                    {
                        await notificationMethod.SendAsync(results, token);
                    }
                }

            return(true); // repeat
        }
示例#9
0
        /// <summary>
        /// Performas a health check of all depdendencies of the API service.
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public Task <HealthCheckResults> HealthCheckApi(string userId, string app)
        {
            var healthCheckResults = new HealthCheckResults()
            {
                Status      = HealthCheckStatus.OK,
                Application = app
            };

            return(Task.FromResult <HealthCheckResults>(healthCheckResults));
        }
示例#10
0
        public static HealthCheckResults Run()
        {
            var results = new HealthCheckResults();

            // Here's the list of checks to run
            results.Add(Ogr2OgrIExeIsCorrectVersion.Run());
            results.Add(HeadlessGoogleChromeIsAvailable.Run());
            results.Add(SqlServerSpatialDllSeemsToWork.Run());
            return(results);
        }
    protected void Page_Load(object sender, EventArgs e)
    {
        this.RegisterAsyncTask(new PageAsyncTask(async() =>
        {
            var timeout  = new CancellationTokenSource(TimeSpan.FromSeconds(3));
            var combined = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, this.Context.Request.TimedOutToken, this.Context.Response.ClientDisconnectedToken);

            var healthCheckManager  = DependencyLocator.Current.GetInstance <IHealthCheckManager>();
            this.HealthCheckResults = await healthCheckManager.CheckHealth(combined.Token);
        }));
    }
示例#12
0
        public override async Task <bool> PerformRunAsync(CancellationToken token)
        {
            if (_appContext == null)
            {
                return(true);                     // repeat...
            }
            switch (_appContext.GetCurrentServerRole())
            {
            case ServerRole.Slave:
                LogHelper.Debug <HealthCheckNotifier>("Does not run on replica servers.");
                return(true);    // DO repeat, server role can change

            case ServerRole.Unknown:
                LogHelper.Debug <HealthCheckNotifier>("Does not run on servers with unknown role.");
                return(true);    // DO repeat, server role can change
            }

            // ensure we do not run if not main domain, but do NOT lock it
            if (_appContext.MainDom.IsMainDom == false)
            {
                LogHelper.Debug <HealthCheckNotifier>("Does not run if not MainDom.");
                return(false); // do NOT repeat, going down
            }

            using (_appContext.ProfilingLogger.DebugDuration <KeepAlive>("Health checks executing", "Health checks complete"))
            {
                var healthCheckConfig = UmbracoConfig.For.HealthCheck();

                // Don't notify for any checks that are disabled, nor for any disabled
                // just for notifications
                var disabledCheckIds = healthCheckConfig.NotificationSettings.DisabledChecks
                                       .Select(x => x.Id)
                                       .Union(healthCheckConfig.DisabledChecks
                                              .Select(x => x.Id))
                                       .Distinct()
                                       .ToArray();

                var checks = _healthCheckResolver.HealthChecks
                             .Where(x => disabledCheckIds.Contains(x.Id) == false);

                var results = new HealthCheckResults(checks);
                results.LogResults();

                // Send using registered notification methods that are enabled
                var registeredNotificationMethods = HealthCheckNotificationMethodResolver.Current.NotificationMethods.Where(x => x.Enabled);
                foreach (var notificationMethod in registeredNotificationMethods)
                {
                    await notificationMethod.SendAsync(results);
                }
            }

            return(true); // repeat
        }
        public override async Task <bool> PerformRunAsync(CancellationToken token)
        {
            if (_runtimeState.Level != RuntimeLevel.Run)
            {
                return(true); // repeat...
            }
            switch (_runtimeState.ServerRole)
            {
            case ServerRole.Replica:
                _logger.Debug <HealthCheckNotifier>("Does not run on replica servers.");
                return(true);    // DO repeat, server role can change

            case ServerRole.Unknown:
                _logger.Debug <HealthCheckNotifier>("Does not run on servers with unknown role.");
                return(true);    // DO repeat, server role can change
            }

            // ensure we do not run if not main domain, but do NOT lock it
            if (_runtimeState.IsMainDom == false)
            {
                _logger.Debug <HealthCheckNotifier>("Does not run if not MainDom.");
                return(false); // do NOT repeat, going down
            }

            using (_logger.DebugDuration <HealthCheckNotifier>("Health checks executing", "Health checks complete"))
            {
                var healthCheckConfig = Current.Configs.HealthChecks();

                // Don't notify for any checks that are disabled, nor for any disabled
                // just for notifications
                var disabledCheckIds = healthCheckConfig.NotificationSettings.DisabledChecks
                                       .Select(x => x.Id)
                                       .Union(healthCheckConfig.DisabledChecks
                                              .Select(x => x.Id))
                                       .Distinct()
                                       .ToArray();

                var checks = _healthChecks
                             .Where(x => disabledCheckIds.Contains(x.Id) == false);

                var results = new HealthCheckResults(checks);
                results.LogResults();

                // Send using registered notification methods that are enabled
                foreach (var notificationMethod in _notifications.Where(x => x.Enabled))
                {
                    await notificationMethod.SendAsync(results, token);
                }
            }

            return(true); // repeat
        }
        public void HealthCheckResults_WithSummaryVerbosity_ReturnsCorrectResultDescription()
        {
            var checks = new List <HealthCheck>
            {
                new StubHealthCheck1(StatusResultType.Success, "First check was successful"),
                new StubHealthCheck2(StatusResultType.Success, "Second check was successful"),
            };
            var results = new HealthCheckResults(checks);

            var resultAsMarkdown = results.ResultsAsMarkDown(HealthCheckNotificationVerbosity.Summary);

            Assert.IsTrue(resultAsMarkdown.IndexOf("Result: 'Success'\r\n") > -1);
        }
        public async Task HealthCheckResults_WithSummaryVerbosity_ReturnsCorrectResultDescription()
        {
            var checks = new List <HealthCheck>
            {
                new StubHealthCheck1(StatusResultType.Success, "First check was successful"),
                new StubHealthCheck2(StatusResultType.Success, "Second check was successful"),
            };
            var results = await HealthCheckResults.Create(checks);

            var resultAsMarkdown = results.ResultsAsMarkDown(HealthCheckNotificationVerbosity.Summary);

            Assert.IsTrue(resultAsMarkdown.IndexOf("Result: 'Success'" + Environment.NewLine) > -1);
        }
        protected bool ShouldSend(HealthCheckResults results)
        {
            if (Enabled == false)
            {
                return(false);
            }

            if (FailureOnly && results.AllChecksSuccessful)
            {
                return(false);
            }

            return(true);
        }
示例#17
0
        public async Task SendAsync(HealthCheckResults results)
        {
            if (ShouldSend(results) == false)
            {
                return;
            }

            if (string.IsNullOrEmpty(RecipientEmail))
            {
                return;
            }

            var message = _textService.Localize("healthcheck/scheduledHealthCheckEmailBody", new[]
            {
                DateTime.Now.ToShortDateString(),
                DateTime.Now.ToShortTimeString(),
                results.ResultsAsHtml(Verbosity)
            });

            // Include the umbraco Application URL host in the message subject so that
            // you can identify the site that these results are for.
            var umbracoApplicationUrl = ApplicationContext.Current.UmbracoApplicationUrl;
            var host = umbracoApplicationUrl;

            if (Uri.TryCreate(umbracoApplicationUrl, UriKind.Absolute, out var umbracoApplicationUri))
            {
                host = umbracoApplicationUri.Host;
            }
            else
            {
                LogHelper.Debug <EmailNotificationMethod>($"umbracoApplicationUrl {umbracoApplicationUrl} appears to be invalid");
            }

            var subject = _textService.Localize("healthcheck/scheduledHealthCheckEmailSubject", new[] { host });

            var mailSender = new EmailSender();

            using (var mailMessage = new MailMessage(UmbracoConfig.For.UmbracoSettings().Content.NotificationEmailAddress,
                                                     RecipientEmail,
                                                     string.IsNullOrEmpty(subject) ? "Umbraco Health Check Status" : subject,
                                                     message)
            {
                IsBodyHtml = message.IsNullOrWhiteSpace() == false &&
                             message.Contains("<") && message.Contains("</")
            })
            {
                await mailSender.SendAsync(mailMessage);
            }
        }
        public async Task HealthCheckResults_WithSuccessfulChecks_ReturnsCorrectResultDescription()
        {
            var checks = new List <HealthCheck>
            {
                new StubHealthCheck1(StatusResultType.Success, "First check was successful"),
                new StubHealthCheck2(StatusResultType.Success, "Second check was successful"),
            };
            var results = await HealthCheckResults.Create(checks);

            Assert.IsTrue(results.AllChecksSuccessful);

            var resultAsMarkdown = results.ResultsAsMarkDown(HealthCheckNotificationVerbosity.Summary);

            Assert.IsTrue(resultAsMarkdown.IndexOf("Checks for 'Stub check 1' all completed successfully.") > -1);
            Assert.IsTrue(resultAsMarkdown.IndexOf("Checks for 'Stub check 2' all completed successfully.") > -1);
        }
        public void HealthCheckResults_WithFailingChecks_ReturnsCorrectResultDescription()
        {
            var checks = new List <HealthCheck>
            {
                new StubHealthCheck1(StatusResultType.Success, "First check was successful"),
                new StubHealthCheck2(StatusResultType.Error, "Second check was not successful"),
            };
            var results = new HealthCheckResults(checks);

            Assert.IsFalse(results.AllChecksSuccessful);

            var resultAsMarkdown = results.ResultsAsMarkDown(HealthCheckNotificationVerbosity.Summary);

            Assert.IsTrue(resultAsMarkdown.IndexOf("Checks for 'Stub check 1' all completed succesfully.") > -1);
            Assert.IsTrue(resultAsMarkdown.IndexOf("Checks for 'Stub check 2' completed with errors.") > -1);
        }
示例#20
0
 public SiteMonitorNagiosViewData(FirmaSession currentFirmaSession, HealthCheckResults healthCheckResults) : base(currentFirmaSession)
 {
     HealthCheckResults   = healthCheckResults;
     CompleteNagiosOutput = HealthCheckResults.GetHealthCheckResultsAsCompleteNagiosOutputText();
     NagiosReturnCode     = HealthCheckResults.GetNagiosReturnCode();
 }
示例#21
0
 public abstract Task SendAsync(HealthCheckResults results);
示例#22
0
 protected bool ShouldSend(HealthCheckResults results)
 {
     return(Enabled && (!FailureOnly || !results.AllChecksSuccessful));
 }
 public abstract Task SendAsync(HealthCheckResults results, CancellationToken token);