{"id":390,"date":"2021-01-12T20:56:07","date_gmt":"2021-01-12T20:56:07","guid":{"rendered":"https:\/\/new1.blog.oqtacore.com\/?p=390"},"modified":"2022-11-23T12:14:48","modified_gmt":"2022-11-23T12:14:48","slug":"effective-it-monitoring-for-a-large-enterprise","status":"publish","type":"post","link":"https:\/\/oqtacore.com\/blog\/effective-it-monitoring-for-a-large-enterprise\/","title":{"rendered":"Effective IT monitoring for a large enterprise (5000+ users)"},"content":{"rendered":"<p>Effective IT monitoring resources.<\/p>\n<p><strong> <img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-391 size-full\" src=\"http:\/\/blog.oqtacore.com\/wp-content\/uploads\/2021\/01\/2021-01-12_23-35-47.png\" alt=\"telegram logo, zabbix logo, c# logo\" width=\"640\" height=\"217\" srcset=\"https:\/\/oqtacore.com\/blog\/wp-content\/uploads\/2021\/01\/2021-01-12_23-35-47.png 640w, https:\/\/oqtacore.com\/blog\/wp-content\/uploads\/2021\/01\/2021-01-12_23-35-47-300x102.png 300w, https:\/\/oqtacore.com\/blog\/wp-content\/uploads\/2021\/01\/2021-01-12_23-35-47-180x61.png 180w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/strong><\/p>\n<p>IT employees in any large company are familiar with the times when all phones just go off. After all, strategically important software does not work and the business process has stopped! System administrators eagerly study the logs and try to figure out what happened. Time passes, passions heat up, reputation falls &#8230; Is it possible to somehow avoid such situations? Unfortunately not. But, you can minimize it. In this article, we will consider several tools that help monitor the health of all automated systems in a company.<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Installing_Zabbix_monitoring_system\"><\/span><strong>Installing Zabbix <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">monitoring system<\/span><\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">A Zabbix-based monitoring system in its simplest form requires one server, which in 99% of cases runs on Linux.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">For example, we will take Ubuntu Linux on which we will install Apache, MySQL and PHP.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\">To do this, run a series of commands in the terminal:<\/span><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sudo apt-get update<br \/>\nsudo apt-get install apache2 libapache2-mod-php<br \/>\nsudo apt-get install mysql-server<br \/>\nsudo apt-get install php php-mbstring php-gd php-xml php-bcmath php-ldap php-mysql<\/code><\/p>\n<p>&nbsp;<\/p>\n<p>We connect to the Zabbix repository (example for Ubuntu 18.04):<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"minimal\">wget https:\/\/repo.zabbix.com\/zabbix\/4.0\/ubuntu\/pool\/main\/z\/zabbix-release\/zabbix-release_4.0-3+bionic_all.deb<br \/>\nsudo dpkg -i zabbix-release_4.0-3+bionic_all.deb<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">Our system is now ready to install the Zabbix backend.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">We start the installation process:<\/span><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">sudo apt-get update<br \/>\nsudo apt-get install zabbix-server-mysql zabbix-frontend-php zabbix-agent<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p>After successfully completing the installation process, we need to create a database to work:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">mysql -u root -p<\/code><\/p>\n<p>mysql&gt; CREATE DATABASE zabbixdb character set utf8 collate utf8_bin;<\/p>\n<p>mysql&gt; CREATE USER &#8216;zabbix&#8217;@&#8217;localhost&#8217; IDENTIFIED BY &#8216;password&#8217;;<\/p>\n<p>mysql&gt; GRANT ALL PRIVILEGES ON zabbixdb.* TO &#8216;zabbix&#8217;@&#8217;localhost&#8217; WITH GRANT OPTION;<\/p>\n<p>mysql&gt; FLUSH PRIVILEGES;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Let&#8217;s load the database schema into the newly created database:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">cd \/usr\/share\/doc\/zabbix-server-mysql<br \/>\nzcat create.sql.gz | mysql -u zabbix -p zabbixdb<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p>The final step will be editing the configuration file \/etc\/zabbix\/zabbix_server.conf<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">DBHost=localhost<br \/>\nDBName=zabbixdb<br \/>\nDBUser=zabbix<br \/>\nDBPassword=password<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p>We completely reboot the server and try to access it from a remote computer at the following address:<\/p>\n<p><a href=\"http:\/\/host_name\/zabbix\/\"><strong>http<\/strong><strong>:\/\/<\/strong><strong>host<\/strong><strong>_<\/strong><strong>name<\/strong><strong>\/<\/strong><strong>zabbix<\/strong><strong>\/<\/strong><\/a> &#8211; <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">where host_name is the name or ip address of your Zabbix server.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">If everything was done correctly, then we will be greeted by the Zabbix Server Configuration Wizard.<\/span><\/p>\n<p>After repeatedly clicking on the <strong>Next step<\/strong> button, we will complete the installation process and successfully enter the monitoring system under the Administrator.<\/p>\n<p>This article does not claim to be a detailed description of the Zabbix system installation process. If you have any questions &#8211; feel free to go to your favorite search engine and find the answers. We have clearly shown that deploying Zabbix is \u200b\u200bnot difficult.<\/p>\n<p>Zabbix is \u200b\u200bable to monitor the state of a remote computer \/ server using an agent, and check the availability and response of standard services such as SMTP or HTTP without installing any software. But, we can find out the full picture of the state only with the help of a cross-platform Zabbix agent. It is banal to install it on all servers, even though it is installed quickly. But, it is mandatory to install on strategically important hosts. After all, then we have the opportunity to display information about the processor \/ memory \/ disk load, the state of all running processes and much more in real time.<\/p>\n<p>To install the agent on a Debian system, execute the following commands in sequence:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">wget https:\/\/repo.zabbix.com\/zabbix\/4.0\/debian\/pool\/main\/z\/zabbix-release\/zabbix-release_4.0-2+stretch_all.deb<br \/>\ndpkg -i zabbix-release_4.0-2+stretch_all.deb<br \/>\napt update<br \/>\napt install zabbix-agent<br \/>\nservice zabbix-agent start<\/code><\/p>\n<p>&nbsp;<\/p>\n<p>For other operating systems, all commands are described in the Zabbix documentation on the official project site.<\/p>\n<p>The best part about IT monitoring systems is that they can notify you of problems. If the router stops responding, the http protocol is not available, or the disk space of the mail server is 95% full, then you will immediately receive a signal. A signal to help you fix a problem before end users find it. Situations in which to sound the alarm are determined by the system administrator in the ways of creating trigers. Triggers are created by writing intuitive expressions:<\/p>\n<p><code><code><\/code><\/code><strong>{SRV-FS:vfs.fs.size[C:,pfree].last(0)}&lt;1<\/strong> \u2013 SRV-FS has less than 1% free space on the C drive.<\/p>\n<p><code><code><\/code><\/code><strong>{Srv-GDLite:icmpping.max(#3)}=0<\/strong> \u2013 the Srv-GDLite server did not respond to ping 3 times in a row<\/p>\n<p><code><code><\/code><\/code><strong>{<\/strong><code><code><\/code><\/code><strong>FCP:<\/strong><code><code><\/code><\/code><strong>proc.<\/strong><code><code><\/code><\/code><strong>num[<\/strong><code><code><\/code><\/code><strong>chrome.<\/strong><code><code><\/code><\/code><strong>exe, <\/strong><code><code><\/code><\/code><strong>Administrator].<\/strong><code><code><\/code><\/code><strong>last(#1)}=1<\/strong><code> <\/code>\u2013 1 instance of the chrome.exe process is running on the FCP computer as Administrator<\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">A huge number of triggers are included in the system out of the box.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">The administrator can only choose the methods of notification.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\">What types of notification does Zabbix offer?<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"3\">Visually shows on the monitor, it is possible to send a letter to the mail, or connect an external script that rings a bell or sends an SMS.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"4\">There are many options.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Writing_a_Telegram_bot_for_IT_monitoring_system\"><\/span><b>Writing a Telegram bot for IT m<span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">onitoring system<\/span><\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">Learning to send Zabbix letters is quite simple.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">But writing on Telegram is more interesting.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\">Let&#8217;s write a simple bot that will check mail and forward all messages from Zabbix to Telegram.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"3\">I chose C # as the programming language, the development environment is Visual Studio.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"4\">The application is console, we do not need any graphical interface.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"5\">To accomplish this task, we need the following NuGet packages:<\/span><\/p>\n<ul>\n<li><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\"><strong>AE.NET.Mail<\/strong> &#8211; for working with mail.<\/span><\/li>\n<li><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\"><strong>Newtonsoft.JSON<\/strong> &#8211; JSON parsing for Telegram.<\/span><\/li>\n<li><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"4\"><strong>RestSharp<\/strong> &#8211; a simple REST and HTTP API client.<\/span><\/li>\n<\/ul>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"6\">Let&#8217;s implement a simple Telegram API for receiving \/ sending messages.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">using RestSharp;\r\n\r\n\r\n\r\n\r\nnamespace BotZabbix\r\n\r\n{\r\n\r\nclass TelegramAPI\r\n\r\n{\r\n\r\nconst string API_URL = \"https:\/\/api.telegram.org\/bot\" + AppSettings.BotToken + \"\/\";\r\n\r\n\r\n\r\n\r\npublic string sendAPIRequest(string _apiMethod, string _params)\r\n\r\n{\r\n\r\nRestClient RC = new RestClient();\r\n\r\nvar Url = API_URL + _apiMethod + \"?\" + _params;\r\n\r\nvar Request = new RestRequest(Url);\r\n\r\nvar Response = RC.Get(Request);\r\n\r\n\r\n\r\n\r\nreturn Response.Content;\r\n\r\n}\r\n\r\n}\r\n\r\n\r\n\r\n\r\npublic class APIResult\r\n\r\n{\r\n\r\npublic Update[] Result { get; set; }\r\n\r\n}\r\n\r\n\r\n\r\n\r\npublic class Update\r\n\r\n{\r\n\r\npublic int update_id { get; set; }\r\n\r\npublic Message message { get; set; }\r\n\r\n}\r\n\r\n\r\n\r\n\r\npublic class Message\r\n\r\n{\r\n\r\npublic Chat chat { get; set; }\r\n\r\npublic string text { get; set; }\r\n\r\n}\r\n\r\n\r\n\r\n\r\npublic class Chat\r\n\r\n{\r\n\r\npublic int id { get; set; }\r\n\r\npublic string first_name { get; set; }\r\n\r\npublic string last_name { get; set; }\r\n\r\n}\r\n\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">Here <strong>AppSettings.BotToken<\/strong> is the token that Telegram issues when creating a bot.<\/span><\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\">If you call the sendAPIRequest method with the following parameters:<\/span><\/p>\n<p><strong>sendAPIRequest(&#8220;sendMessage&#8221;, $&#8221;chat_id={_idChat}&amp;text={BotHelpers.CheckText(_text)}&#8221;)<\/strong><\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">then we will send a message to the user with id = _idChat and the text stored in the _text variable.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">To receive messages, you need to call the above method as follows:<\/span><\/p>\n<p><strong>sendAPIRequest(&#8220;getUpdates&#8221;, $&#8221;offset={lastUpdateId}&#8221;)<\/strong><\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">where lastUpdateId is the id of the last received message.<\/span><\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\">To implement the process of receiving email, we will write the following class:<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><code>using System;<\/code><\/p>\n<p><code>using System.Collections.Generic;<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><code>namespace BotZabbix<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>class Email<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>public List&lt;string&gt; GetMail()<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>int MailCount = 0;<\/code><\/p>\n<p><code>List&lt;string&gt; Mails = new List&lt;string&gt;();<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><code>try<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>using (AE.Net.Mail.ImapClient ic = new \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0AE.Net.Mail.ImapClient(AppSettings.MailServer,<\/code><\/p>\n<p><code>AppSettings.MailUser,<\/code><\/p>\n<p><code>AppSettings.MailPassword, AE.Net.Mail.AuthMethods.Login,<\/code><\/p>\n<p><code>AppSettings.MailServerPort, true))<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>ic.SelectMailbox(\"INBOX\");<\/code><\/p>\n<p><code>AE.Net.Mail.MailMessage[] mm = ic.GetMessages(0, 50, false);<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><code>foreach (AE.Net.Mail.MailMessage m in mm)<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>MailCount++;<\/code><\/p>\n<p><code>if (m.From.ToString().Contains(\"Zabbix\"))<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>Mails.Add(m.Body);<\/code><\/p>\n<p><code>ic.DeleteMessage(m);<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>else<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>Logger.Log(m.From.ToString());<\/code><\/p>\n<p><code>Logger.Log(m.Body.ToString());<\/code><\/p>\n<p><code>ic.DeleteMessage(m);<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>Logger.Log($\"::: {DateTime.Now} Mail count: {MailCount}\");<\/code><\/p>\n<p><code>ic.Dispose();<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>catch (Exception _ex)<\/code><\/p>\n<p><code>{<\/code><\/p>\n<p><code>Logger.Log($\"::: {DateTime.Now} Error: \" + _ex.Message);<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><code>return Mails;<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p><code>}<\/code><\/p>\n<p>&nbsp;<\/p>\n<p>As you can see from the code, the GetMail () method connects to a specific mailbox, searches the Inbox folder for messages from the sender &#8220;Zabbix&#8221;, returns them as a result of its work and deletes them from the mailbox. The body of the bot receives letters in the Mails variable and sends them to everyone interested in Telegram.<\/p>\n<p>Only the flight of thought and imagination decides what functionality to give the bot. In my case, the bot lets it in only with a password, logs all its activities, and can receive the ping command for a detailed analysis of the network state.<\/p>\n<p>The full version of the bot can be viewed on github: https:\/\/github.com\/ishmuratov\/ZabbixBot.<\/p>\n<p>&nbsp;<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Writing_a_ping_tool_for_IT_monitoring_system\"><\/span><strong>Writing a ping tool <\/strong><b>for IT m<span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">onitoring system<\/span><\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>What do we end up with? An IT monitoring system that controls all the most important parameters of the company&#8217;s servers and a notification system by email and Telegram. But what if the Zabbix server itself fails? He himself will not be able to write a letter about his death &#8230; C # comes to our aid again. We arm ourselves with Visual Studio and write a small utility called PingTool, which can poll hosts according to the list cyclically. If someone does not answer for some time, then a letter is sent on behalf of Zabbix, which is immediately duplicated in Telegram by the above bot.<\/p>\n<p>To implement this task, we need to write a method for sending a letter to e&#8217;mail and program an analogue of the ping command.<\/p>\n<p>&nbsp;<\/p>\n<p>using System.Net.NetworkInformation;<\/p>\n<p>class Pinger<\/p>\n<p>{<\/p>\n<p>public static bool PingHost(string nameOrAddress)<\/p>\n<p>{<\/p>\n<p>bool pingable = false;<\/p>\n<p>Ping pinger = null;<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>pinger = new Ping();<\/p>\n<p>PingReply reply = pinger.Send(nameOrAddress);<\/p>\n<p>pingable = reply.Status == IPStatus.Success;<\/p>\n<p>}<\/p>\n<p>catch (PingException)<\/p>\n<p>{<\/p>\n<p>return false;<\/p>\n<p>}<\/p>\n<p>finally<\/p>\n<p>{<\/p>\n<p>if (pinger != null)<\/p>\n<p>{<\/p>\n<p>pinger.Dispose();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>return pingable;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">If host <strong>nameOrAddress<\/strong> responds, then the result of the PingHost method of the Pinger class will be <strong>true<\/strong>.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">Otherwise, <strong>false<\/strong>.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"2\">If for a certain period of time (for example, 10 seconds) some address does not respond, then it is marked as inaccessible, which is the reason for sending a letter.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>class MailSender<\/p>\n<p>{<\/p>\n<p>public MailSend(string _fromAddress, string _fromPassword, string _toAddress, Letter _letter)<\/p>\n<p>{<\/p>\n<p>var fromMail = new MailAddress(_fromAddress, &#8220;Zabbix&#8221;);<\/p>\n<p>var toMail = new MailAddress(_toAddress, string.Empty);<\/p>\n<p>var smtp = new SmtpClient<\/p>\n<p>{<\/p>\n<p>Host = &#8220;smtp.gmail.com&#8221;,<\/p>\n<p>Port = 587,<\/p>\n<p>EnableSsl = true,<\/p>\n<p>DeliveryMethod = SmtpDeliveryMethod.Network,<\/p>\n<p>UseDefaultCredentials = false,<\/p>\n<p>Credentials = new NetworkCredential(fromMail.Address, _fromPassword)<\/p>\n<p>};<\/p>\n<p>using (var message = new MailMessage(fromMail, toMail)<\/p>\n<p>{<\/p>\n<p>Subject = _letter.Subject,<\/p>\n<p>Body = _letter.Body<\/p>\n<p>})<\/p>\n<p>{<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>smtp.Send(message);<\/p>\n<p>}<\/p>\n<p>catch (Exception ex)<\/p>\n<p>{<\/p>\n<p>Logger.Log($&#8221;::: {DateTime.Now} Error: &#8221; + _ex.Message);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p><span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"0\">The <strong>MailSend ()<\/strong> method sends an email from the <strong>_fromAdress<\/strong> address to the <strong>_toAdress<\/strong> address.<\/span> <span class=\"JLqJ4b ChMk0b\" data-language-for-alternatives=\"en\" data-language-to-translate-into=\"auto\" data-phrase-index=\"1\">The method was written for Gmail, but it is easy to rewrite it for another mail service by changing the appropriate settings of the SmtpClient instance.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>class Letter<\/p>\n<p>{<\/p>\n<p>public string Subject { get; set; }<\/p>\n<p>public string Body { get; set; }<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>The Letter class contains only 2 text properties Subject and Body, which store the subject and body of the letter, respectively.<\/p>\n<p>The full version of the program can be viewed on github: https:\/\/github.com\/ishmuratov\/PingTool.<\/p>\n<p>After lengthy trials, <a href=\"http:\/\/blog.oqtacore.com\/tag\/case-study\/\">our company<\/a> came to the following solution: deploy a Zabbix server in a cloud data center that guarantees 99% uptime and has access to all the company&#8217;s servers. The Telegram bot is located in the Google cloud, which guarantees 99.9% uptime and Internet access. The PingTool utility has been launched at the head office and is capable of sending letters via the 3G communication channel of the country&#8217;s largest cellular operator. Thanks to the IT monitoring system, we were able to significantly increase the fault tolerance of all critical nodes and provide business with high efficiency due to the continuous operation of equipment and software.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Effective IT monitoring resources. IT employees in any large company are familiar with the times when all phones just go off. After all, strategically important software does not work and the business process has stopped! System administrators eagerly study the logs and try to figure out what happened. Time passes, passions heat up, reputation falls [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_mo_disable_npp":"","yasr_overall_rating":0,"yasr_post_is_review":"","yasr_auto_insert_disabled":"","yasr_review_type":"","footnotes":""},"categories":[1],"tags":[13,14],"class_list":["post-390","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-business","tag-technologies"],"acf":{"image":398},"yasr_visitor_votes":{"number_of_votes":0,"sum_votes":0,"stars_attributes":{"read_only":false,"span_bottom":false}},"_links":{"self":[{"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/posts\/390","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/comments?post=390"}],"version-history":[{"count":17,"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/posts\/390\/revisions"}],"predecessor-version":[{"id":957,"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/posts\/390\/revisions\/957"}],"wp:attachment":[{"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/media?parent=390"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/categories?post=390"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oqtacore.com\/blog\/wp-json\/wp\/v2\/tags?post=390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}