105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
127 |
128 |
--------------------------------------------------------------------------------
/azure_status_page.jobs/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Reflection;
4 | using System.Threading;
5 | using azure_status_page.core;
6 | using azure_status_page.core.Repositories;
7 |
8 | namespace azure_status_page.jobs
9 | {
10 | class MainClass
11 | {
12 | public static void Main(string[] args)
13 | {
14 | // initialize the environment
15 | AzureEnvironmentService.Initialize();
16 |
17 | using (var shutdownService = new AzureWebJobShutdownService())
18 | {
19 | // generate the waithandle we are using for the innermost loop
20 | ManualResetEvent timeoutHandle = new ManualResetEvent(false);
21 | bool bShutdown = false;
22 |
23 | // configure our shutdown handler
24 | shutdownService.OnShutdown += (sender) => {
25 | Console.WriteLine("Detected Shutdown, interupting the loop");
26 | bShutdown = true;
27 | timeoutHandle.Set();
28 | };
29 |
30 | shutdownService.OnPeek += (sender) => {
31 | Console.WriteLine("Detected Peek, forcing a loop");
32 | timeoutHandle.Set();
33 | };
34 |
35 | // start the inner most loop
36 | do
37 | {
38 | // reset our event
39 | timeoutHandle.Reset();
40 |
41 | // load the config
42 | Console.WriteLine("Loading the Azure WebJob Configuration...");
43 | var config = (new SiteExtensionConfigurationService()).LoadConfiguration();
44 |
45 | // executing the server side checks
46 | Console.WriteLine("Executing Server Side Checks");
47 | var meterManagerEx = new MeterManagerEx(config);
48 | meterManagerEx.ExecuteServerSideChecks();
49 |
50 | // check the meters
51 | Console.WriteLine("Checking the different Meters");
52 | var checkMeterService = new CheckMeterService(config);
53 | var results = checkMeterService.Check();
54 |
55 | // notify if needed
56 | Console.WriteLine("Notify failed Meters");
57 | checkMeterService.Notify(results);
58 |
59 | // get the path of the job
60 | var jobAssetPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Assets");
61 | var jobSiteTemplate = Path.Combine(jobAssetPath, "default-template.html");
62 |
63 | // update the static status page
64 | Console.WriteLine("Updating Status Page");
65 | var siteGenerator = new StatusPageGeneratorService(Path.Combine(AzureEnvironmentService.WebSiteLocation, "index.html"), jobSiteTemplate);
66 | siteGenerator.UpdateSite(config.Title, config.Brand, config.FavIcon, results);
67 |
68 | // done
69 | Console.WriteLine("Waiting for the next cycle (5mins)");
70 |
71 | } while (!timeoutHandle.WaitOne(5 * 60 * 1000) || !bShutdown);
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/azure_status_page.jobs/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 |
4 | // Information about this assembly is defined by the following attributes.
5 | // Change them to the values specific to your project.
6 |
7 | [assembly: AssemblyTitle("azure_status_page.jobs")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("")]
12 | [assembly: AssemblyCopyright("${AuthorCopyright}")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
19 |
20 | [assembly: AssemblyVersion("1.0.*")]
21 |
22 | // The following attributes are used to specify the signing key for the assembly,
23 | // if desired. See the Mono documentation for more information about signing.
24 |
25 | //[assembly: AssemblyDelaySign(false)]
26 | //[assembly: AssemblyKeyFile("")]
27 |
--------------------------------------------------------------------------------
/azure_status_page.jobs/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/azure_status_page.jobs/azure_status_page.jobs.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {FF395F21-BE10-4C4F-A27C-238AD6697C5E}
7 | Exe
8 | azure_status_page.jobs
9 | run
10 | v4.5
11 | 0.0.2
12 |
13 |
14 | true
15 | full
16 | false
17 | ..\azure_status_page\App_Data\WebJob
18 | DEBUG;
19 | prompt
20 | 4
21 | true
22 |
23 |
24 | true
25 | ..\azure_status_page\App_Data\WebJob
26 | prompt
27 | 4
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | {31878B8D-7325-47B0-BF2B-1809B72E63EC}
41 | azure_status_page.core
42 |
43 |
44 | {EBD3A11E-FD34-4BF9-8768-BE5A613F7AE7}
45 | azure_status_page.client
46 |
47 |
48 |
49 |
50 |
51 | PreserveNewest
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/azure_status_page.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "azure_status_page", "azure_status_page\azure_status_page.csproj", "{25464043-8444-49E0-8EDE-566B1409D7DF}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "azure_status_page.core", "azure_status_page.core\azure_status_page.core.csproj", "{31878B8D-7325-47B0-BF2B-1809B72E63EC}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "azure_status_page.jobs", "azure_status_page.jobs\azure_status_page.jobs.csproj", "{FF395F21-BE10-4C4F-A27C-238AD6697C5E}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "azure_status_page.client", "azure_status_page.client\azure_status_page.client.csproj", "{EBD3A11E-FD34-4BF9-8768-BE5A613F7AE7}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "azure_status_page.client.demo", "azure_status_page.client.demo\azure_status_page.client.demo.csproj", "{B35B4ED1-AD7C-4E44-956C-6E508E68711E}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {25464043-8444-49E0-8EDE-566B1409D7DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {25464043-8444-49E0-8EDE-566B1409D7DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {25464043-8444-49E0-8EDE-566B1409D7DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {25464043-8444-49E0-8EDE-566B1409D7DF}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {31878B8D-7325-47B0-BF2B-1809B72E63EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {31878B8D-7325-47B0-BF2B-1809B72E63EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {31878B8D-7325-47B0-BF2B-1809B72E63EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {31878B8D-7325-47B0-BF2B-1809B72E63EC}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {FF395F21-BE10-4C4F-A27C-238AD6697C5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {FF395F21-BE10-4C4F-A27C-238AD6697C5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {FF395F21-BE10-4C4F-A27C-238AD6697C5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {FF395F21-BE10-4C4F-A27C-238AD6697C5E}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {EBD3A11E-FD34-4BF9-8768-BE5A613F7AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {EBD3A11E-FD34-4BF9-8768-BE5A613F7AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {EBD3A11E-FD34-4BF9-8768-BE5A613F7AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {EBD3A11E-FD34-4BF9-8768-BE5A613F7AE7}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {B35B4ED1-AD7C-4E44-956C-6E508E68711E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {B35B4ED1-AD7C-4E44-956C-6E508E68711E}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {B35B4ED1-AD7C-4E44-956C-6E508E68711E}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {B35B4ED1-AD7C-4E44-956C-6E508E68711E}.Release|Any CPU.Build.0 = Release|Any CPU
40 | EndGlobalSection
41 | GlobalSection(MonoDevelopProperties) = preSolution
42 | version = 0.0.2
43 | EndGlobalSection
44 | EndGlobal
45 |
--------------------------------------------------------------------------------
/azure_status_page/App_Start/RouteConfig.cs:
--------------------------------------------------------------------------------
1 | using System.Web.Mvc;
2 | using System.Web.Routing;
3 |
4 | namespace azure_status_page
5 | {
6 | public class RouteConfig
7 | {
8 | public static void RegisterRoutes(RouteCollection routes)
9 | {
10 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
11 |
12 | routes.MapRoute(
13 | name: "Default",
14 | url: "{controller}/{action}/{id}",
15 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
16 | );
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/azure_status_page/App_Start/WebApiConfig.cs:
--------------------------------------------------------------------------------
1 | using System.Web.Http;
2 |
3 | namespace azure_status_page
4 | {
5 | public static class WebApiConfig
6 | {
7 | public static void Register(HttpConfiguration config)
8 | {
9 | // Web API configuration and services
10 |
11 | // Web API routes
12 | config.MapHttpAttributeRoutes();
13 |
14 | config.Routes.MapHttpRoute(
15 | name: "DefaultApi",
16 | routeTemplate: "api/{controller}/{id}",
17 | defaults: new { id = RouteParameter.Optional }
18 | );
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/azure_status_page/Content/bs-callout.css:
--------------------------------------------------------------------------------
1 |
2 | /* Side notes for calling out things
3 | -------------------------------------------------- */
4 |
5 | /* Base styles (regardless of theme) */
6 | .bs-callout {
7 | margin: 20px 0;
8 | padding: 15px 30px 15px 15px;
9 | border-left: 5px solid #eee;
10 | }
11 | .bs-callout h4 {
12 | margin-top: 0;
13 | }
14 | .bs-callout p:last-child {
15 | margin-bottom: 0;
16 | }
17 | .bs-callout code,
18 | .bs-callout .highlight {
19 | background-color: #fff;
20 | }
21 |
22 | /* Themes for different contexts */
23 | .bs-callout-danger {
24 | background-color: #fcf2f2;
25 | border-color: #dFb5b4;
26 | }
27 | .bs-callout-warning {
28 | background-color: #fefbed;
29 | border-color: #f1e7bc;
30 | }
31 | .bs-callout-info {
32 | background-color: #f0f7fd;
33 | border-color: #d0e3f0;
34 | }
--------------------------------------------------------------------------------
/azure_status_page/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Web;
6 | using System.Web.Mvc;
7 | using System.Web.Mvc.Ajax;
8 | using azure_status_page.core;
9 |
10 | namespace azure_status_page.Controllers
11 | {
12 | public class HomeController : Controller
13 | {
14 | private SiteExtensionConfigurationService configService = new SiteExtensionConfigurationService();
15 | private AzureWebJobInstaller webJobInstaller = new AzureWebJobInstaller("CheckMetersAndUpdateSite", Path.Combine(AzureEnvironmentService.SiteExtensionLocation, "App_Data", "WebJob"), AzureEnvironmentService.WebSiteLocation);
16 |
17 | private void PrepareViewBag()
18 | {
19 | // check if the webjob is installed
20 | ViewBag.WebJobInstalled = webJobInstaller.IsWebJobInstalled();
21 | }
22 |
23 | [HttpGet]
24 | public ActionResult Index()
25 | {
26 | // load the configuration
27 | var config = configService.LoadConfiguration();
28 |
29 | // prepare our default view bag
30 | PrepareViewBag();
31 |
32 | // render the config
33 | return View(config);
34 | }
35 |
36 | [HttpPost]
37 | public ActionResult Index(MeterStorageConfigurationModel config)
38 | {
39 | // store the config
40 | configService.VerifyAndStoreConfiguration(config);
41 |
42 | // prepare our default view bag
43 | PrepareViewBag();
44 |
45 | // render the config
46 | return View(config);
47 | }
48 |
49 | [HttpPost]
50 | public ActionResult Install()
51 | {
52 | // install the webjob
53 | webJobInstaller.InstallOrUpdateWebJob();
54 |
55 | // render the config
56 | return RedirectToAction("Index");
57 | }
58 |
59 | [HttpPost]
60 | public ActionResult Generate()
61 | {
62 | // Trigger
63 | AzureWebJobShutdownService.Peek();
64 |
65 | // prepare our default view bag
66 | PrepareViewBag();
67 |
68 | // render the config
69 | return RedirectToAction("Index");
70 | }
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/azure_status_page/Controllers/MetersController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Mvc;
6 | using azure_status_page.core;
7 | using azure_status_page.core.Models;
8 | using azure_status_page.core.Repositories;
9 | using azure_status_page.ViewModels;
10 |
11 | namespace azure_status_page.Controllers
12 | {
13 | public class MetersController : Controller
14 | {
15 | private SiteExtensionConfigurationService configService = new SiteExtensionConfigurationService();
16 |
17 | private MeterManagerEx initializeMeterManager()
18 | {
19 | // try to load the configruation
20 | var config = configService.LoadConfiguration();
21 |
22 | // generate the repository
23 | var repository = new AzureTableMeterManagerExRepository(config.StorageKey, config.StorageSecret, config.StorageTableName);
24 |
25 | // instantiate the meter manager
26 | return new MeterManagerEx(repository);
27 | }
28 |
29 | [HttpGet]
30 | public ActionResult Index()
31 | {
32 | // instantiate the meter manager
33 | var meterManagerEx = initializeMeterManager();
34 |
35 | // build the view model
36 | var viewModel = new MetersViewModel();
37 |
38 | // get all the MeterDefinitions for the client side meters
39 | viewModel.ClientSideMeters = meterManagerEx.GetClientSideDefinitions();
40 |
41 | // get all Server Based MeterDefinitions
42 | viewModel.StatusPageMeters = meterManagerEx.GetServerBasedDefinitions();
43 |
44 | // render the view
45 | return View (viewModel);
46 | }
47 |
48 | [HttpGet]
49 | public ActionResult Add()
50 | {
51 | // create the model
52 | var meterDefinition = new MeterDefinitionServerBased()
53 | {
54 | MeterId = Guid.NewGuid().ToString(),
55 | MeterType = client.Models.nMeterTypes.Heartbeat,
56 | MeterServerCheckType = "HTTP",
57 | MeterServerCheckInformation = String.Empty
58 | };
59 |
60 | return View("Add", meterDefinition);
61 | }
62 |
63 | [HttpPost]
64 | public ActionResult Add(MeterDefinitionServerBased model)
65 | {
66 | // instantiate the meter manager
67 | var meterManagerEx = initializeMeterManager();
68 |
69 | // store the meterdefinition to the settings
70 | meterManagerEx.CreateOrUpdateServerSideDefinition(model);
71 |
72 | // trigger the webjib
73 | AzureWebJobShutdownService.Peek();
74 |
75 | // Render the meters
76 | return RedirectToAction("Index");
77 | }
78 |
79 | [HttpGet]
80 | public ActionResult Edit(String Id, String CheckType)
81 | {
82 | // instantiate the meter manager
83 | var meterManagerEx = initializeMeterManager();
84 | var meterDefinition = meterManagerEx.GetServerBasedDefinition(Id, CheckType);
85 |
86 | // show the dialog
87 | return View("Add", meterDefinition);
88 | }
89 |
90 | [HttpGet]
91 | public ActionResult Delete(String Id, String CheckType)
92 | {
93 | // instantiate the meter manager
94 | var meterManagerEx = initializeMeterManager();
95 | meterManagerEx.DeleteServerSideDefinition(Id, CheckType);
96 |
97 | // Render the meters
98 | return RedirectToAction("Index");
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/azure_status_page/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Inherits="azure_status_page.Global" %>
2 |
--------------------------------------------------------------------------------
/azure_status_page/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System.Web;
2 | using System.Web.Mvc;
3 | using System.Web.Routing;
4 | using System.Web.Http;
5 | using azure_status_page.core;
6 |
7 | namespace azure_status_page
8 | {
9 | public class Global : HttpApplication
10 | {
11 | protected void Application_Start()
12 | {
13 | AreaRegistration.RegisterAllAreas();
14 | GlobalConfiguration.Configure(WebApiConfig.Register);
15 | RouteConfig.RegisterRoutes(RouteTable.Routes);
16 | AzureEnvironmentService.Initialize();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/azure_status_page/ViewModels/MetersViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using azure_status_page.client.Models;
4 | using azure_status_page.core.Models;
5 |
6 | namespace azure_status_page.ViewModels
7 | {
8 | public class MetersViewModel
9 | {
10 | public List ClientSideMeters { get; set; } = new List();
11 |
12 | public List StatusPageMeters { get; set; } = new List();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/azure_status_page/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @model azure_status_page.core.MeterStorageConfigurationModel
2 |
3 | @{
4 | ViewBag.Title = "Azure Status Page Generator - Configuration";
5 | }
6 |
7 |
10 |
11 | @if (!Model.Valid) {
12 |
13 | Please enter a valid storage account and fill out the customization options to generate a
14 | valid configuration. Currently no status page will be generated!
15 |
20 | Azure Status Pages implements the recurring update via webjob. This webjob is currently not installed.
21 | Please install the webjob to generate a status page
12 | Client side Meters are information delivered from the services as self, e.g. a heartbeat or some complex
13 | technical checks from time to time. This meters will be shown automatically in the status page. To integrate
14 | client side meters check our Status Page SDKs here:
15 |
48 | Status Page Meters are executed in the App Service the Status Page is hosted and can be used to check specific
49 | metrics from outside of the applicaton, e.g. the availability of a specific application
50 |