BizTalk monitoring, PART 1: BTS services and configurations
For the monitoring of the BizTalk Server we’ve programmed a simple application that will send an email if a certain port or orchestration will be disabled… or even worse, when a BizTalk Service is stopped.
The configuration for the app is done in an external XML file.
Below is the code that is used to check the BTS status, the method will return a boolean that indicates if all is running or not.
1: /// <summary>
2: /// Checks the BizTalk Status for BTS Service, Orchestrations, Send Ports, Receive Locations
3: /// And send a mail on not running of any instance
4: /// </summary>
5: /// <returns>True if all is running</returns>
6: public Boolean CheckBTSStatus()
7: {
8: //Constant Values
9: String ErrorMessage = " {0} '{1}' is {2}!<BR>";
10: String ErrorServicesHeader = "<FONT color="#C11B17"><strong>CRITICAL ISSUE: BTS SERVICE IS STOPPED</strong></FONT><BR><BR>";
11: String ErrorReceiveLocationsHeader = "<BR><strong>WARNING: Receive Location issue(s)</strong><BR><BR>";
12: String ErrorSendportsHeader = "<BR><strong>WARNING: Send Port issue(s)</strong><BR><BR>";
13: String ErrorOrchestrationsHeader = "<BR><strong>WARNING: Orchestration issue(s)</strong><BR><BR>";
14: String MailSubject = "URGENT: BizTalk issue(s) on " + Dns.GetHostName();
15:
16: // separate ERROR StringBuilders
17: StringBuilder services = new StringBuilder();
18: StringBuilder sendports = new StringBuilder();
19: StringBuilder receiveLocations = new StringBuilder();
20: StringBuilder orchestrations = new StringBuilder();
21: Boolean allRunning = true;
22:
23: foreach (String service in BTSService)
24: {
25: ServiceController sc = new ServiceController(service);
26:
27: if (sc.Status != ServiceControllerStatus.Running && sc.Status != ServiceControllerStatus.StartPending)
28: {
29: services.AppendLine(String.Format(ErrorMessage, "Service", service, sc.Status));
30: allRunning = false;
31: }
32: }
33:
34: String connectionString = "Data Source=" + dBServer + ";Initial Catalog=" + dB + ";";
35: if (!String.IsNullOrEmpty(userName) && !String.IsNullOrEmpty(password))
36: connectionString += "User Id=" + userName + ";Password=" + password + ";";
37: else
38: connectionString += "Integrated Security=SSPI;";
39:
40: BtsCatalogExplorer catalog = new BtsCatalogExplorer();
41: catalog.ConnectionString = connectionString;
42:
43: foreach (Application app in catalog.Applications)
44: {
45: if (app.Status != Status.Started && app.Status != Status.NotApplicable)
46: {
47: foreach (SendPort send in app.SendPorts)
48: {
49: if (send.Status != PortStatus.Started)
50: {
51: sendports.AppendLine(String.Format(ErrorMessage, "Send Port", send.Name, send.Status == PortStatus.Bound ? "Unenlisted" : send.Status.ToString()));
52: allRunning = false;
53: }
54: }
55: foreach (ReceivePort receive in app.ReceivePorts)
56: {
57: foreach (ReceiveLocation location in receive.ReceiveLocations)
58: {
59: if (!location.Enable)
60: {
61: receiveLocations.AppendLine(String.Format(ErrorMessage, "Receive Location", location.Name, "Disabled"));
62: allRunning = false;
63: }
64: }
65: }
66: foreach (BtsOrchestration orch in app.Orchestrations)
67: {
68: if (orch.Status != OrchestrationStatus.Started)
69: {
70: orchestrations.AppendLine(String.Format(ErrorMessage, "Orchestration", orch.FullName, orch.Status));
71: allRunning = false;
72: }
73: }
74: }
75: }
76:
77: if(!allRunning)
78: {
79: if(!String.IsNullOrEmpty(services.ToString()))
80: services.Insert(0, ErrorServicesHeader);
81: if (!String.IsNullOrEmpty(sendports.ToString()))
82: sendports.Insert(0, ErrorSendportsHeader);
83: if (!String.IsNullOrEmpty(receiveLocations.ToString()))
84: receiveLocations.Insert(0, ErrorReceiveLocationsHeader);
85: if (!String.IsNullOrEmpty(orchestrations.ToString()))
86: orchestrations.Insert(0, ErrorOrchestrationsHeader);
87:
88: String body = services.ToString() + receiveLocations.ToString()
89: + sendports.ToString() + orchestrations.ToString();
90:
91: Helper.SendMail(body, MailSubject, sendMailAddress, receiveMailAddress, SMTP);
92: }
93: return allRunning;
94: }
the method to send an email is the following:
1: public static void SendMail(String body, String subject, String fromAddress, String toAddress, String SMTPAddress)
2: {
3: MailMessage msg = new MailMessage(fromAddress, toAddress);
4: msg.IsBodyHtml = true;
5: msg.Body = body;
6: //msg.From = new MailAddress(fromAddress);
7: msg.Subject = subject;
8:
9: System.Net.Mail.SmtpClient smtp = new SmtpClient(SMTPAddress);
10: smtp.Send(msg);
11: //SmtpMail.SmtpServer = SMTPAddress;
12: //SmtpMail.Send(msg);
13: }
to read the configuration out of the XML file, we’ve programmed following in the constructor (all is read to private class variables:
1: private string dBServer;
2: private string dB;
3: private string userName;
4: private string password;
5:
6: private List<string> BTSService;
7:
8: private string sendMailAddress;
9: private string receiveMailAddress;
10: private string SMTP;
11:
12: public Monitor()
13: {
14: XmlDocument config = new XmlDocument();
15: config.Load(System.IO.Directory.GetCurrentDirectory() + "/BTSMonitorConfiguration.xml");
16:
17: try
18: {
19: dBServer = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Server").InnerText;
20: dB = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/DB").InnerText;
21: userName = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/UserName") == null ?
22: "" : config.SelectSingleNode("CONFIGURATION/DBSETTINGS/UserName").InnerText;
23: password = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Password") == null ?
24: "" : config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Password").InnerText;
25:
26: BTSService = new List<string>();
27:
28: foreach(XmlNode service in config.SelectNodes("CONFIGURATION/BTSSETTINGS/BTSSERVICES/BTSServiceName"))
29: {
30: BTSService.Add(service.InnerText);
31: }
32:
33: sendMailAddress = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/From").InnerText;
34: receiveMailAddress = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/To").InnerText;
35: SMTP = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/SMTP").InnerText;
36: }
37: catch (Exception e)
38: {
39: StringBuilder error = new StringBuilder();
40: error.AppendLine("not all necessary data to perform the action is provided.");
41: error.AppendLine("Make sure these fields are correctly filled in in the XML File:");
42: error.AppendLine("tDBServer (server name)");
43: error.AppendLine("tDB (Database)");
44: error.AppendLine("tBTSServiceName (BTS Service Name)");
45: error.AppendLine("tFrom (sending mail address)");
46: error.AppendLine("tTo (receiveing mail address)");
47: error.AppendLine("tSMTP (SMTP host address)");
48: throw (new Exception(error.ToString()));
49: }
50: }
and finally the created XML file:
<?xml version="1.0" encoding="utf-8" ?>
<CONFIGURATION>
<DBSETTINGS>
<Server>.</Server> <!-- Server Name -->
<DB>BizTalkMgmtDb</DB> <!-- DataBase Name -->
<!--<UserName>user</UserName>--> <!-- optional -->
<!--<Password>password</Password>--> <!-- optional -->
</DBSETTINGS>
<BTSSETTINGS>
<BTSSERVICES>
<BTSServiceName>BizTalk Service BizTalk Group : BizTalkServerApplication</BTSServiceName> <!-- BTS Service Name -->
<BTSServiceName>BizTalk Service BizTalk Group : BizTalkServerApplication2</BTSServiceName>
<!-- BTS Service Name -->
</BTSSERVICES>
</BTSSETTINGS>
<MAILSETTINGS>
<From>from@company.com</From>
<To>to@company.com</To>
<SMTP>smtp.company.com</SMTP>
</MAILSETTINGS>
</CONFIGURATION>
Hope you enjoyed my post.
In my next blog I’ll show you how to monitor the BizTalk Queue to receive an email with the error message of all suspended instances.