Академический Документы
Профессиональный Документы
Культура Документы
GitHub Repository
Introduction
This guide is about how to create a service monitor application, but what is it? In simple words: it's an application that allows to
monitor services in a network and save results from monitoring in a database, SQL Server for this case.
I know there are a lot of tools that can provide this feature, also there are better tools that money can buy but my intention with this
guide is to show how to use .NET Core power to build an application that developers can extend for custom requirements.
The basic idea is this: have a process to run in infinite ways to monitor hosts, databases and APIs; save monitoring results in SQL
Server database, then we can build a fancy UI to end-user and show status for each service, we can have a lot of targets to
monitoring but it's better to allow users to subscribe for specific services and not all; for example DBAs need to watch database
servers not APIs, developers need to watch development databases and APIs, etc.
Also think about having big monitors in your development room and watching the status for your services and in the best of cases,
have charts. :)
One special feature could be to have a notification service to send messages for all administrators in case one or more services fail,
in this context, service means a target such as host, database, API.
Name Description
Background
As we said before, we'll create an application to monitoring existing targets (hosts, databases, APIs), so we need to have basic
knowledge about these concepts.
Hosts will be monitoring with ping action, so we'll add networking related packages to perform this action.
Databases will be monitoring with open and close connections, don't use integrated security because you'll need to impersonate
your service monitor process with your credentials, so in that case, it's better to have a specific user to connect with database and
only that action to avoid hacking.
RESTful APIs will be monitoring with REST client to target an action that returns simple JSON.
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 1/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
Database
Inside of repository, there is a directory with name \Resources\Database and this directory contains related database files, please
make sure to run the following files in this order:
Tables Description
Table Description
EnvironmentCate
Contains all categories for environments: development, qa and production
gory
ServiceCategory Contains all categories for services: database, rest API, server, URL and web service
Service Contains all services definitions
ServiceEnvironm Contains the relation for service and environment, for example we can define a service named
ent FinanceService with different environments: development, qa and production
ServiceEnvironm
Contains the status for each service per environment
entStatus
ServiceEnvironm
Contains the details for each service environment status
entStatusLog
Owner Contains the user list for application that represents all owners
PLEASE DON'T FORGET I'M WORKING WITH A SOLUTION ON MY LOCAL MACHINE, THERE IS A SAMPLE API IN
RESOURCES TO PERFORMING TESTS, BUT YOU NEED CHANGE THE CONNECTION STRING AND ADD YOUR SERVICES
ACCORDING TO YOUR REQUIREMENTS.
ALSO I DON'T RECOMMEND TO EXPOSE REAL CONNECTION STRINGS IN ServiceEnvironment TABLE, PLEASE
REQUEST TO YOUR DBA WHO PROVIDES TO YOU A SINGLE USER CAN ONLY PERFORM OPEN CONNECTION FOR
TARGET DATABASE, IN CASE THAT TASK IS FROM YOUR SIDE SO CREATE THE USERS FOR THOSE ACTIONS AND
PREVENT EXPOSING SENSITIVE INFORMATION.
ServiceMonitor.C
Class Library Contains all definitions related to database storage
ore
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 2/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
ServiceMonitor.A
Web API Contains Web API Controllers to read and write information about monitoring
PI
Console
ServiceMonitor Contains process to monitoring all services
Application
ServiceMonitor.Core
This project contains all definitions for entities and database access, so we need to add the following packages for project:
This project contains three layers: Business Logic, Database Access and Entities; please take a look at the article EF Core for
Entreprise to get a better understanding about this project and layers.
using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ServiceMonitor.Core.BusinessLayer.Contracts;
using ServiceMonitor.Core.BusinessLayer.Responses;
using ServiceMonitor.Core.DataLayer;
using ServiceMonitor.Core.DataLayer.DataContracts;
using ServiceMonitor.Core.EntityLayer;
namespace ServiceMonitor.Core.BusinessLayer
{
public class DashboardService : Service, IDashboardService
{
public DashboardService(ILogger<DashboardService> logger, ServiceMonitorDbContext
dbContext)
: base(logger, dbContext)
{
}
try
{
response.Model = await DbContext.GetActiveServiceWatcherItems().ToListAsync();
return response;
}
try
{
var user = await DbContext.GetUserAsync(userName);
if (user == null)
{
Logger?.LogInformation("There isn't data for user '{0}'", userName);
return response;
}
try
{
response.Model = await DbContext.GetServiceEnvironmentStatusAsync(entity);
}
catch (Exception ex)
{
response.SetError(Logger, nameof(GetServiceStatusAsync), ex);
}
return response;
}
}
}
ServiceMonitor.Common
Contracts
IWatcher
IWatchResponse
ISerializer
IWatcher interface code:
using System.Threading.Tasks;
namespace ServiceMonitor.Common.Contracts
{
public interface IWatcher
{
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 4/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
string ActionName { get; }
namespace ServiceMonitor.Common.Contracts
{
public interface IWatchResponse
{
bool Success { get; set; }
namespace ServiceMonitor.Common.Contracts
{
public interface ISerializer
{
string Serialize<T>(T obj);
T Deserialze<T>(string source);
}
}
Watchers
These are the implementations:
DatabaseWatcher
HttpRequestWatcher
PingWatcher
DatabaseWatcher class code:
using System;
using System.Data.SqlClient;
using System.Threading.Tasks;
using ServiceMonitor.Common.Contracts;
namespace ServiceMonitor.Common
{
public class DatabaseWatcher : IWatcher
{
public string ActionName
=> "OpenDatabaseConnection";
response.Success = true;
}
catch (Exception ex)
{
response.Success = false;
response.Message = ex.Message;
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 5/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
response.StackTrace = ex.ToString();
}
}
return response;
}
}
}
using System;
using System.Threading.Tasks;
using ServiceMonitor.Common.Contracts;
namespace ServiceMonitor.Common
{
public class HttpRequestWatcher : IWatcher
{
public string ActionName
=> "HttpRequest";
try
{
var restClient = new RestClient();
await restClient.GetAsync(parameter.Values["Url"]);
response.Success = true;
}
catch (Exception ex)
{
response.Success = false;
response.Message = ex.Message;
response.StackTrace = ex.ToString();
}
return response;
}
}
}
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using ServiceMonitor.Common.Contracts;
namespace ServiceMonitor.Common
{
public class PingWatcher : IWatcher
{
public string ActionName
=> "Ping";
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 6/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
ServiceMonitor.API
This project represents RESTful API for service monitor, so we'll have two controllers: DashboardController and
AdministrationController. Dashboard has all operations related to end user results and Administration contains all
operations related to save information (create, edit and delete).
Dashboard
DashboardController class code:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using ServiceMonitor.API.Responses;
using ServiceMonitor.Core.BusinessLayer.Contracts;
namespace ServiceMonitor.API.Controllers
{
[Route("api/v1/[controller]")]
public class DashboardController : Controller
{
protected ILogger Logger;
protected IDashboardService Service;
base.Dispose(disposing);
}
// GET: api/v1/Dashboard/ServiceWatcherItem
[HttpGet("ServiceWatcherItem")]
public async Task<IActionResult> GetServiceWatcherItemsAsync()
{
Logger?.LogDebug("'{0}' has been invoked", nameof(GetServiceWatcherItemsAsync));
return response.ToHttpResponse();
}
// GET: api/v1/Dashboard/ServiceStatusDetail/{id}
[HttpGet("ServiceStatusDetail/{id}")]
public async Task<IActionResult> GetServiceStatusDetailsAsync(string id)
{
Logger?.LogDebug("'{0}' has been invoked", nameof(GetServiceStatusDetailsAsync));
return response.ToHttpResponse();
}
}
}
Administration
AdministrationController class code:
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 7/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using ServiceMonitor.API.Requests;
using ServiceMonitor.API.Responses;
using ServiceMonitor.Core.BusinessLayer.Contracts;
namespace ServiceMonitor.API.Controllers
{
[Route("api/v1/[controller]")]
public class AdministrationController : Controller
{
protected ILogger Logger;
protected IAdministrationService Service;
base.Dispose(disposing);
}
// POST: api/v1/Dashboard/ServiceStatusLog
[HttpPost("ServiceEnvironmentStatusLog")]
public async Task<IActionResult>
PostServiceStatusLogAsync([FromBody]ServiceEnvironmentStatusLogRequest value)
{
Logger?.LogDebug("'{0}' has been invoked", nameof(PostServiceStatusLogAsync));
return response.ToHttpResponse();
}
}
}
ServiceMonitor
This project contains all objects for Service Monitor Client, in this project, we have added the package Newtonsoft.Json for
JSON serialization, in ServiceMonitor.Common there is an interface with name ISerializer and that's because I
don't want to force to use a specific serializer, you can change that at this level. :)
using Newtonsoft.Json;
using ServiceMonitor.Common.Contracts;
namespace ServiceMonitor
{
public class ServiceMonitorSerializer : ISerializer
{
public string Serialize<T>(T obj)
=> JsonConvert.SerializeObject(obj);
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 8/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
Next, we'll be working on MonitorController class, in this class, we'll perform all watching operations and save all results
in database throught AdministrationController in Service Monitor API.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ServiceMonitor.Common;
using ServiceMonitor.Common.Contracts;
using ServiceMonitor.Models;
namespace ServiceMonitor
{
public class MonitorController
{
public MonitorController(AppSettings appSettings, ILogger logger, IWatcher watcher,
RestClient restClient)
{
AppSettings = appSettings;
Logger = logger;
Watcher = watcher;
RestClient = restClient;
}
if (watchResponse.Success)
Logger?.LogInformation(" Success watch for '{0}' in '{1}' environment",
item.ServiceName, item.Environment);
else
Logger?.LogError(" Failed watch for '{0}' in '{1}' environment",
item.ServiceName, item.Environment);
try
{
await RestClient.PostJsonAsync(AppSettings.ServiceStatusLogUrl,
watchLog);
}
catch (Exception ex)
{
Logger?.LogError(" Error on saving watch response ({0}): '{1}'",
item.ServiceName, ex.Message);
}
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 9/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
}
catch (Exception ex)
{
Logger?.LogError(" Error watching service: '{0}': '{1}'", item.ServiceName,
ex.Message);
}
Thread.Sleep(item.Interval ?? AppSettings.DelayTime);
}
}
}
}
{
"message":null,
"didError":false,
"errorMessage":null,
"model":[
{
"serviceID":1,
"serviceEnvironmentID":1,
"environment":"Development",
"serviceName":"Northwind Database",
"interval":15000,
"url":null,
"address":null,
"connectionString":"server=(local);database=Northwind;user
id=johnd;password=SqlServer2017$",
"typeName":"ServiceMonitor.Common.DatabaseWatcher, ServiceMonitor.Common,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
{
"serviceID":2,
"serviceEnvironmentID":3,
"environment":"Development",
"serviceName":"DNS",
"interval":3000,
"url":null,
"address":"192.168.1.1",
"connectionString":null,
"typeName":"ServiceMonitor.Common.PingWatcher, ServiceMonitor.Common, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null"
},
{
"serviceID":3,
"serviceEnvironmentID":4,
"environment":"Development",
"serviceName":"Sample API",
"interval":5000,
"url":"http://localhost:5612/api/values",
"address":null,
"connectionString":null,
"typeName":"ServiceMonitor.Common.HttpWebRequestWatcher, ServiceMonitor.Common,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
}
]
}
As we can see, API returns all services for DefaultUser, please remember the concept about one user can subscribe more
than one service to watch, obviously in this sample, our default user is suscribed to all services but we can change this link in
ServiceUser table.
Program class code:
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 10/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using ServiceMonitor.Common;
using ServiceMonitor.Common.Contracts;
namespace ServiceMonitor
{
class Program
{
private static ILogger logger;
private static readonly AppSettings appSettings;
static Program()
{
logger = LoggingHelper.GetLogger<Program>();
Console.ReadLine();
}
try
{
await initializer.LoadResponseAsync();
}
catch (Exception ex)
{
logger.LogError("Error on retrieve watch items: {0}", ex);
return;
}
try
{
initializer.DeserializeResponse();
}
catch (Exception ex)
{
logger.LogError("Error on deserializing object: {0}", ex);
return;
}
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 11/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
await controller.ProcessAsync(item);
});
}
}
}
}
Once we have checked the previous aspects, now we proceed to turn console application, console output is this:
dbug: ServiceMonitor.Program[0]
Starting application
sr trce: ServiceMonitor.Program[0]
06/20/2017 23:09:30 - Watching 'Sample API' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:30 - Watching 'Northwind Database' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:30 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:35 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:37 - Watching 'Sample API' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:39 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:42 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:43 - Watching 'Sample API' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:45 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:47 - Watching 'Northwind Database' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:48 - Watching 'Sample API' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:48 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:51 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:53 - Watching 'Sample API' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:54 - Watching 'DNS' for 'Development' environment
trce: ServiceMonitor.Program[0]
06/20/2017 23:09:57 - Watching 'DNS' for 'Development' environment
Now we proceed to check the saved data in database, please check ServiceEnvironmentStatus table, you'll get a
result like this:
(3 row(s) affected)
How it works all together? Console application takes all services to watch from API and then starts one task per watch item in an
infinite way inside of MonitorController, there is a delay time for each task, that interval is set in Service definition, but if
there isn't a defined value for Interval, the interval is taken from AppSettings; so after of perform of Watch action, the result
is saved on database through API and the process repeats itself. If you want to perform a watch operation for other types, you
can create your own Watcher class.
Points of Interest
DatabaseWatcher works with SQL Server, so how you connect to MySQL, PostgreSQL, Oracle and others DBMS?
Create your Watcher class for specific DBMS and implements the interface IWatcher and write the code to connect
for target database.
Can we host service monitor in non Windows platforms? Yes, since .NET Core is cross platform We can host this project on
Windows, Mac OS and Linux.
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 12/13
26/11/2018 Creating Service Monitor Application with .NET Core - CodeProject
As I know, there isn't native support for ASMX in .NET Core but we can monitor both kind of services, simply adding the
rows in Service table, the ASMX ends with .asmx.
Why console client and API aren't one single project? To prevent common issues on publishing, I think it's better to have two
different projects because in that case We can run service monitor in one server and host API in another server.
In this initial version, there isn't any configuration about security because it's better you add that implementation according to
your scenario; you can make work this project with Windows Authentication, custom Authentication or add external service
for authentication, that makes sense?
Code Improvements
Add UI project to show in a pretty way the status of services for end users, using some front-end frameworks such as
AngularJS or ReactJS
Add notifications for administrators on critical errors during services watching (email, sms, etc.)
I think it's better to have TypeName in ServiceCategory instead of ServiceWatcher
Add security for API
History
17th January, 2017: Initial version
20th June, 2017: Addition of environment for services
19th October, 2017: Update for Services (Business Layer)
15th July, 2018: Update for .NET Core 2
22th November, 2018: Removing repository pattern
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile Article Copyright 2017 by HHerzl
Web02 | 2.8.181124.1 | Last Updated 26 Nov 2018 Everything else Copyright © CodeProject, 1999-2018
https://www.codeproject.com/Articles/1165961/Creating-Service-Monitor-Application-with-NET-Core?display=Print 13/13