This repository has been archived by the owner on Apr 13, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ccbe008
commit 7fe5019
Showing
14 changed files
with
284 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
src/BeatPulse.StatusPageTracker/BeatPulse.StatusPageTracker.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>$(NetStandardTargetVersion)</TargetFramework> | ||
<PackageLicenseUrl>$(PackageLicenseUrl)</PackageLicenseUrl> | ||
<PackageProjectUrl>$(PackageProjectUrl)</PackageProjectUrl> | ||
<PackageTags>BeatPulse;HealthCheck;Beat;Health;StatusPage;StatusPage IO;statuspage.ioTracker;Trackers;</PackageTags> | ||
<Description>BeatPulse.StatusPage is a BeatPulseTracker for StatusPage.IO component status system.</Description> | ||
<Version>$(BeatPulseStatusPageTracker)</Version> | ||
<RepositoryUrl>$(RepositoryUrl)</RepositoryUrl> | ||
<Company>$(Company)</Company> | ||
<Authors>$(Authors)</Authors> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BeatPulse\BeatPulse.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
19 changes: 19 additions & 0 deletions
19
src/BeatPulse.StatusPageTracker/BeatPulseContextExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using BeatPulse.Core; | ||
using BeatPulse.StatusPageTracker; | ||
using System; | ||
|
||
namespace BeatPulse | ||
{ | ||
public static class BeatPulseContextExtensions | ||
{ | ||
public static BeatPulseContext AddStatusPageTracker(this BeatPulseContext context,Action<StatusPageComponent> setup) | ||
{ | ||
var component = new StatusPageComponent(); | ||
setup(component); | ||
|
||
context.AddTracker(new StatusPageIOTracker(component)); | ||
|
||
return context; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
|
||
namespace BeatPulse.StatusPageTracker | ||
{ | ||
static class HttpClientExtensions | ||
{ | ||
public static async Task<HttpResponseMessage> PatchAsync(this HttpClient client, string requestUri, HttpContent content) | ||
{ | ||
var method = new HttpMethod("PATCH"); | ||
|
||
var request = new HttpRequestMessage(method, requestUri) | ||
{ | ||
Content = content | ||
}; | ||
|
||
var response = await client.SendAsync(request); | ||
|
||
return response; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace BeatPulse.StatusPageTracker | ||
{ | ||
class StatusPageClient | ||
{ | ||
|
||
private readonly HttpClient _httpClient; | ||
private readonly StatusPageComponent _statusPageComponent; | ||
|
||
public StatusPageClient(StatusPageComponent statusPageComponent) | ||
{ | ||
_statusPageComponent = statusPageComponent ?? throw new ArgumentNullException(nameof(statusPageComponent)); | ||
|
||
_httpClient = new HttpClient( | ||
new StatusPageAuthorizationHandler(statusPageComponent.ApiKey)) | ||
{ | ||
BaseAddress = new Uri("https://api.statuspage.io/v1/") | ||
}; | ||
} | ||
|
||
public async Task CreateIncident(string failure) | ||
{ | ||
var incidentId = await FindUnresolvedComponentIncident(); | ||
|
||
if (String.IsNullOrWhiteSpace(incidentId)) | ||
{ | ||
var incident = $"incident[name]={_statusPageComponent.IncidentName}&incident[status]=investigating&incident[body]={failure}&incident[component_ids][]={_statusPageComponent.ComponentId}&incident[components][{_statusPageComponent.ComponentId}]=major_outage"; | ||
|
||
var content = new StringContent(incident, Encoding.UTF8, "application/x-www-form-urlencoded"); | ||
|
||
await _httpClient.PostAsync($"pages/{_statusPageComponent.PageId}/incidents.json", content); | ||
} | ||
} | ||
|
||
public async Task SolveIncident() | ||
{ | ||
var incidentId = await FindUnresolvedComponentIncident(); | ||
|
||
if (!String.IsNullOrEmpty(incidentId)) | ||
{ | ||
var content = $"incident[status]=resolved&incident[components][{_statusPageComponent.ComponentId}]=operational"; | ||
|
||
await _httpClient.PatchAsync($"pages/{_statusPageComponent.PageId}/incidents/{incidentId}.json", new StringContent(content, Encoding.UTF8, "application/x-www-form-urlencoded")); | ||
} | ||
} | ||
|
||
async Task<string> FindUnresolvedComponentIncident() | ||
{ | ||
var response = await _httpClient.GetAsync($"pages/{_statusPageComponent.PageId}/incidents/unresolved.json"); | ||
|
||
var unresolved = JsonConvert.DeserializeObject<IEnumerable<WebStatusIncident>>( | ||
await response.Content.ReadAsStringAsync()); | ||
|
||
if (unresolved.Any()) | ||
{ | ||
return unresolved.Where(ws => ws.Name.Equals(_statusPageComponent.IncidentName, StringComparison.InvariantCultureIgnoreCase)) | ||
.Select(ws => ws.Id) | ||
.SingleOrDefault(); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
|
||
private class StatusPageAuthorizationHandler : DelegatingHandler | ||
{ | ||
private readonly string _apiKey; | ||
|
||
public StatusPageAuthorizationHandler(string apiKey) | ||
{ | ||
_apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey)); | ||
InnerHandler = new HttpClientHandler(); | ||
} | ||
|
||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
request.Headers | ||
.TryAddWithoutValidation("Authorization", $"OAuth {_apiKey}"); | ||
|
||
return await base.SendAsync(request, cancellationToken); | ||
} | ||
} | ||
|
||
private class WebStatusIncident | ||
{ | ||
public string Id { get; set; } | ||
|
||
public string Name { get; set; } | ||
|
||
public string Status { get; set; } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
namespace BeatPulse.StatusPageTracker | ||
{ | ||
public class StatusPageComponent | ||
{ | ||
public string ApiKey { get; set; } | ||
|
||
public string PageId { get; set; } | ||
|
||
public string ComponentId { get; set; } | ||
|
||
public string IncidentName { get; set; } | ||
|
||
public StatusPageComponent() | ||
{ | ||
ApiKey = "your-api-key-here"; | ||
PageId = "your-pageid-here"; | ||
ComponentId = "your-componentid-here"; | ||
IncidentName = "your-incidentname-here"; | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using BeatPulse.Core; | ||
using System.Threading.Tasks; | ||
|
||
namespace BeatPulse.StatusPageTracker | ||
{ | ||
class StatusPageIOTracker | ||
: IBeatPulseTracker | ||
{ | ||
private readonly StatusPageClient _statusPageClient; | ||
|
||
public StatusPageIOTracker(StatusPageComponent statusPageComponent) | ||
{ | ||
_statusPageClient = new StatusPageClient(statusPageComponent); | ||
} | ||
|
||
public async Task Track(LivenessResult response) | ||
{ | ||
if (response.IsHealthy) | ||
{ | ||
await _statusPageClient.SolveIncident(); | ||
} | ||
else | ||
{ | ||
await _statusPageClient.CreateIncident(response.Message); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
[assembly: InternalsVisibleTo("UnitTests")] |
40 changes: 40 additions & 0 deletions
40
tests/UnitTests/BeatPulse.StatusPageTracker/BeatPulseContextExtensionTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using BeatPulse; | ||
using BeatPulse.Core; | ||
using BeatPulse.StatusPageTracker; | ||
using FluentAssertions; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.TestHost; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Linq; | ||
using UnitTests.Base; | ||
using Xunit; | ||
|
||
namespace UnitTests.BeatPulse.StatusPageTracker | ||
{ | ||
public class beat_pulse_context_should | ||
{ | ||
[Fact] | ||
public void register_statuspage_tracker() | ||
{ | ||
var webHostBuilder = new WebHostBuilder() | ||
.UseBeatPulse() | ||
.UseStartup<DefaultStartup>() | ||
.ConfigureServices(svc => | ||
{ | ||
svc.AddBeatPulse(context => | ||
{ | ||
context.AddStatusPageTracker(setup => { }); | ||
}); | ||
}); | ||
|
||
var beatPulseContext = new TestServer(webHostBuilder) | ||
.Host | ||
.Services | ||
.GetService<BeatPulseContext>(); | ||
|
||
beatPulseContext.GetAllTrackers() | ||
.Where(hc => hc.GetType() == typeof(StatusPageIOTracker)) | ||
.Should().HaveCount(1); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters