private void GetStatusAnswers(string domain, FailoverType type, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List <DnsResourceRecord> answers) { { HealthCheckResponse response = _healthService.QueryStatus(domain, DnsResourceRecordType.A, healthCheck, healthCheckUrl, false); string text = "app=failover; cnameType=" + type.ToString() + "; domain=" + domain + "; qType: A; healthCheck=" + healthCheck + (healthCheckUrl is null ? "" : "; healthCheckUrl=" + healthCheckUrl.AbsoluteUri) + "; healthStatus=" + response.Status.ToString() + ";"; if (response.Status == HealthStatus.Failed) { text += " failureReason=" + response.FailureReason + ";"; } answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, appRecordTtl, new DnsTXTRecord(text))); } { HealthCheckResponse response = _healthService.QueryStatus(domain, DnsResourceRecordType.AAAA, healthCheck, healthCheckUrl, false); string text = "app=failover; cnameType=" + type.ToString() + "; domain=" + domain + "; qType: AAAA; healthCheck=" + healthCheck + (healthCheckUrl is null ? "" : "; healthCheckUrl=" + healthCheckUrl.AbsoluteUri) + "; healthStatus=" + response.Status.ToString() + ";"; if (response.Status == HealthStatus.Failed) { text += " failureReason=" + response.FailureReason + ";"; } answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, appRecordTtl, new DnsTXTRecord(text))); } }
private IReadOnlyList <DnsResourceRecord> GetAnswers(string domain, DnsQuestionRecord question, string zoneName, uint appRecordTtl, string healthCheck, Uri healthCheckUrl) { HealthCheckResponse response = _healthService.QueryStatus(domain, question.Type, healthCheck, healthCheckUrl, true); switch (response.Status) { case HealthStatus.Unknown: if (question.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)) //check for zone apex { return new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.ANAME, DnsClass.IN, 30, new DnsANAMERecord(domain)) } } ; //use ANAME else { return new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.CNAME, DnsClass.IN, 30, new DnsCNAMERecord(domain)) } }; case HealthStatus.Healthy: if (question.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)) //check for zone apex { return new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.ANAME, DnsClass.IN, appRecordTtl, new DnsANAMERecord(domain)) } } ; //use ANAME else { return new DnsResourceRecord[] { new DnsResourceRecord(question.Name, DnsResourceRecordType.CNAME, DnsClass.IN, appRecordTtl, new DnsCNAMERecord(domain)) } }; } return(null); }
public Task SendAlertAsync(IPAddress address, string healthCheck, HealthCheckResponse healthCheckResponse) { if (!_enabled || (_mailFrom is null) || (_alertTo is null) || (_alertTo.Length == 0)) { return(Task.CompletedTask); } MailMessage message = new MailMessage(); message.From = _mailFrom; foreach (MailAddress alertTo in _alertTo) { message.To.Add(alertTo); } message.Subject = "[Alert] Address [" + address.ToString() + "] Status Is " + healthCheckResponse.Status.ToString().ToUpper(); switch (healthCheckResponse.Status) { case HealthStatus.Failed: message.Body = @"Hi, The DNS Failover App was successfully able to perform a health check [" + healthCheck + "] on the address [" + address.ToString() + @"] and found that the address failed to respond. Address: " + address.ToString() + @" Health Check: " + healthCheck + @" Status: " + healthCheckResponse.Status.ToString().ToUpper() + @" Alert Time: " + healthCheckResponse.DateTime.ToString("R") + @" Failure Reason: " + healthCheckResponse.FailureReason + @" Regards, DNS Failover App "; break; default: message.Body = @"Hi, The DNS Failover App was successfully able to perform a health check [" + healthCheck + "] on the address [" + address.ToString() + @"] and found that the address status was " + healthCheckResponse.Status.ToString().ToUpper() + @". Address: " + address.ToString() + @" Health Check: " + healthCheck + @" Status: " + healthCheckResponse.Status.ToString().ToUpper() + @" Alert Time: " + healthCheckResponse.DateTime.ToString("R") + @" Regards, DNS Failover App "; break; } return(SendMailAsync(message)); }
private void GetAnswers(dynamic jsonAddresses, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List <DnsResourceRecord> answers) { if (jsonAddresses == null) { return; } switch (question.Type) { case DnsResourceRecordType.A: foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetwork) { HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, true); switch (response.Status) { case HealthStatus.Unknown: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, 30, new DnsARecord(address))); break; case HealthStatus.Healthy: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.A, question.Class, appRecordTtl, new DnsARecord(address))); break; } } } break; case DnsResourceRecordType.AAAA: foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); if (address.AddressFamily == AddressFamily.InterNetworkV6) { HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, true); switch (response.Status) { case HealthStatus.Unknown: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, 30, new DnsAAAARecord(address))); break; case HealthStatus.Healthy: answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.AAAA, question.Class, appRecordTtl, new DnsAAAARecord(address))); break; } } } break; } }
public Task CallAsync(IPAddress address, string healthCheck, HealthCheckResponse healthCheckResponse) { if (!_enabled) { return(Task.CompletedTask); } HttpContent content; { using (MemoryStream mS = new MemoryStream()) { JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(mS)); jsonWriter.WriteStartObject(); jsonWriter.WritePropertyName("address"); jsonWriter.WriteValue(address.ToString()); jsonWriter.WritePropertyName("healthCheck"); jsonWriter.WriteValue(healthCheck); jsonWriter.WritePropertyName("status"); jsonWriter.WriteValue(healthCheckResponse.Status.ToString()); if (healthCheckResponse.Status == HealthStatus.Failed) { jsonWriter.WritePropertyName("failureReason"); jsonWriter.WriteValue(healthCheckResponse.FailureReason); } jsonWriter.WritePropertyName("dateTime"); jsonWriter.WriteValue(healthCheckResponse.DateTime); jsonWriter.WriteEndObject(); jsonWriter.Flush(); content = new ByteArrayContent(mS.ToArray()); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); } } return(CallAsync(content)); }
private void GetStatusAnswers(dynamic jsonAddresses, FailoverType type, DnsQuestionRecord question, uint appRecordTtl, string healthCheck, Uri healthCheckUrl, List <DnsResourceRecord> answers) { if (jsonAddresses == null) { return; } foreach (dynamic jsonAddress in jsonAddresses) { IPAddress address = IPAddress.Parse(jsonAddress.Value); HealthCheckResponse response = _healthService.QueryStatus(address, healthCheck, healthCheckUrl, false); string text = "app=failover; addressType=" + type.ToString() + "; address=" + address.ToString() + "; healthCheck=" + healthCheck + (healthCheckUrl is null ? "" : "; healthCheckUrl=" + healthCheckUrl.AbsoluteUri) + "; healthStatus=" + response.Status.ToString() + ";"; if (response.Status == HealthStatus.Failed) { text += " failureReason=" + response.FailureReason + ";"; } answers.Add(new DnsResourceRecord(question.Name, DnsResourceRecordType.TXT, question.Class, appRecordTtl, new DnsTXTRecord(text))); } }
public HealthMonitor(IDnsServer dnsServer, IPAddress address, HealthCheck healthCheck, Uri healthCheckUrl) { _dnsServer = dnsServer; _address = address; _healthCheck = healthCheck; _healthCheckTimer = new Timer(async delegate(object state) { try { if (_healthCheck is null) { _lastHealthCheckResponse = null; } else { HealthCheckResponse healthCheckResponse = await _healthCheck.IsHealthyAsync(_address, healthCheckUrl); bool statusChanged = false; bool maintenance = false; if (_lastHealthCheckResponse is null) { switch (healthCheckResponse.Status) { case HealthStatus.Failed: statusChanged = true; break; case HealthStatus.Maintenance: statusChanged = true; maintenance = true; break; } } else { if (_lastHealthCheckResponse.Status != healthCheckResponse.Status) { statusChanged = true; if ((_lastHealthCheckResponse.Status == HealthStatus.Maintenance) || (healthCheckResponse.Status == HealthStatus.Maintenance)) { maintenance = true; } } } if (statusChanged) { switch (healthCheckResponse.Status) { case HealthStatus.Failed: _dnsServer.WriteLog("ALERT! Address [" + _address.ToString() + "] status is FAILED based on '" + _healthCheck.Name + "' health check. The failure reason is: " + healthCheckResponse.FailureReason); break; default: _dnsServer.WriteLog("ALERT! Address [" + _address.ToString() + "] status is " + healthCheckResponse.Status.ToString().ToUpper() + " based on '" + _healthCheck.Name + "' health check."); break; } if (healthCheckResponse.Exception is not null) { _dnsServer.WriteLog(healthCheckResponse.Exception); } if (!maintenance) { //avoid sending email alerts when switching from or to maintenance EmailAlert emailAlert = _healthCheck.EmailAlert; if (emailAlert is not null) { _ = emailAlert.SendAlertAsync(_address, _healthCheck.Name, healthCheckResponse); } } WebHook webHook = _healthCheck.WebHook; if (webHook is not null) { _ = webHook.CallAsync(_address, _healthCheck.Name, healthCheckResponse); } } _lastHealthCheckResponse = healthCheckResponse; } } catch (Exception ex) { _dnsServer.WriteLog(ex); if (_lastHealthCheckResponse is null) { EmailAlert emailAlert = _healthCheck.EmailAlert; if (emailAlert is not null) { _ = emailAlert.SendAlertAsync(_address, _healthCheck.Name, ex); } WebHook webHook = _healthCheck.WebHook; if (webHook is not null) { _ = webHook.CallAsync(_address, _healthCheck.Name, ex); } _lastHealthCheckResponse = new HealthCheckResponse(HealthStatus.Failed, ex.ToString(), ex); } else { _lastHealthCheckResponse = null; } } finally { if (!_disposed && (_healthCheck is not null)) { _healthCheckTimer.Change(_healthCheck.Interval, Timeout.Infinite); } } }, null, Timeout.Infinite, Timeout.Infinite); _healthCheckTimer.Change(HEALTH_CHECK_TIMER_INITIAL_INTERVAL, Timeout.Infinite); }