give HostStatus analyzer more info: details on ping success/failure and ping duration
[pingcheck] / src / host / hoststatus.cpp
CommitLineData
91fcc471
TJ
1/*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on this file might be covered by the GNU General Public License.
19*/
6c14bbee 20#include "host/hoststatus.h"
ddf41c89
GMF
21
22#include <iostream>
3f7c921f 23#include <logfunc.hpp>
ddf41c89 24
780b0bca 25#include "boost_assert_handler.h"
ddf41c89
GMF
26
27using namespace std;
3f7c921f 28using I2n::Logger::GlobalLogger;
ddf41c89
GMF
29
30//-----------------------------------------------------------------------------
6c14bbee 31// HostStatus
ddf41c89
GMF
32//-----------------------------------------------------------------------------
33
c01a6023 34/**
6c14bbee
GMF
35 * @param host_address The address of the host it has to analyze.
36 * @param ping_fail_percentage_limit The percentage threshold of pings that can
c01a6023 37 * fail.
6c14bbee 38 * @param link_analyzer The object used to notify the status of the host.
c01a6023 39 */
6c14bbee 40HostStatus::HostStatus(
ddf41c89 41 const string &host_address,
cd4048df 42 const int ping_fail_limit_percentage,
c6c54dfb 43 const LinkStatusItem link_analyzer
ddf41c89 44) :
c1fff16a 45 HostAddress( host_address ),
fb469ffa 46 LinkAnalyzer( link_analyzer ),
cd4048df 47 PingFailLimitPercentage( ping_fail_limit_percentage ),
ddf41c89
GMF
48 ResolvedIpCount( 0 ),
49 PingsPerformedCount( 0 ),
d8a91bd6 50 PingsFailedCount( 0 ),
a341119a 51 ExceededPingFailedLimit( false )
ddf41c89 52{
d4793cc9 53 BOOST_ASSERT( !HostAddress.empty() );
cd4048df 54 BOOST_ASSERT( ( 0 <= PingFailLimitPercentage ) && ( PingFailLimitPercentage <= 100 ) );
ddf41c89
GMF
55}
56
6c14bbee 57HostStatus::~HostStatus()
ddf41c89
GMF
58{
59}
60
c01a6023 61/**
6c14bbee 62 * @param resolved_ip_count The number of IPs resolved for the host.
c01a6023 63 */
6c14bbee 64void HostStatus::set_resolved_ip_count( const int resolved_ip_count )
ddf41c89 65{
838e0acf 66 BOOST_ASSERT( 0 <= resolved_ip_count );
ddf41c89 67
db625177
CH
68 if (resolved_ip_count != ResolvedIpCount)
69 { // assume that the target has changed --> reset counters
70 reset_ping_counters();
71 }
ddf41c89 72 ResolvedIpCount = resolved_ip_count;
3f7c921f 73
03c2a2c3 74 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f
CH
75 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
76 << ResolvedIpCount << " IPs: #IPs set";
ddf41c89
GMF
77}
78
c01a6023
GMF
79/**
80 * @return true if the amount of failed pings given to the host exceeded the
81 * limit.
82 */
6c14bbee 83bool HostStatus::exceeded_ping_failed_limit() const
d8a91bd6 84{
a341119a 85 return ExceededPingFailedLimit;
d8a91bd6
GMF
86}
87
c01a6023 88/**
96c4e7a4
CH
89 * Tells the status analyzer how the last ping went
90 *
91 * @param result: status of ping specifying success/failure and reason of fail
92 * @param ping_duration_us duration of ping in micro seconds
c01a6023 93 */
96c4e7a4
CH
94void HostStatus::update_ping_statistics( const PingStatus &result,
95 const long ping_duration_us )
ddf41c89 96{
96c4e7a4
CH
97 float ping_duration_ms = static_cast<float>(ping_duration_us) / 1000.;
98
03c2a2c3 99 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 100 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
96c4e7a4
CH
101 << ResolvedIpCount << " IPs: add ping with result "
102 << to_string(result) << " which took " << ping_duration_ms << " ms";
3f7c921f 103
ddf41c89
GMF
104 BOOST_ASSERT( 1 <= ResolvedIpCount );
105 BOOST_ASSERT( 0 <= PingsPerformedCount );
106 BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount );
107
c5e4bfa1 108 increase_ping_performed_count();
ddf41c89 109
96c4e7a4 110 if ( result != PingStatus_SuccessReply )
ddf41c89 111 {
c5e4bfa1 112 increase_ping_failed_count();
ddf41c89
GMF
113 }
114
2c10f87b
GMF
115 analyze_ping_failed_count();
116
c5e4bfa1
GMF
117 // after we tried all IPs resolved for this host, we can analyze how many
118 // failed
119 if ( tried_all_resolved_ip() )
ddf41c89 120 {
d8a91bd6 121 analyze_ping_statistics();
ddf41c89 122
c5e4bfa1 123 reset_ping_counters();
ddf41c89
GMF
124 }
125
126 BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount );
127}
128
c1d776ba 129
6c14bbee 130bool HostStatus::tried_all_resolved_ip() const
d8a91bd6 131{
2c10f87b 132 BOOST_ASSERT( ( 0 < PingsPerformedCount ) && ( PingsPerformedCount <= ResolvedIpCount ) );
d4793cc9
GMF
133
134 return ( PingsPerformedCount == ResolvedIpCount );
d8a91bd6
GMF
135}
136
6c14bbee 137void HostStatus::analyze_ping_statistics()
ddf41c89 138{
c1fff16a 139 BOOST_ASSERT( !HostAddress.empty() );
d4793cc9 140 BOOST_ASSERT( PingsPerformedCount == ResolvedIpCount );
ddf41c89 141
c1fff16a 142 // notify if the amount of pings that failed exceed the limit
a341119a 143 if ( exceeded_ping_failed_limit() )
ddf41c89 144 {
03c2a2c3 145 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f
CH
146 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
147 << ResolvedIpCount << " IPs: notify down";
fb469ffa 148 LinkAnalyzer->notify_host_down( HostAddress );
ddf41c89
GMF
149 }
150 else
151 {
03c2a2c3 152 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f
CH
153 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
154 << ResolvedIpCount << " IPs: notify up";
fb469ffa 155 LinkAnalyzer->notify_host_up( HostAddress );
ddf41c89 156 }
6fd0993e 157} //lint !e1762
ddf41c89 158
6c14bbee 159void HostStatus::reset_ping_counters()
c1fff16a
GMF
160{
161 PingsPerformedCount = 0;
162 PingsFailedCount = 0;
163}
164
6c14bbee 165void HostStatus::increase_ping_performed_count()
c5e4bfa1
GMF
166{
167 ++PingsPerformedCount;
c1fff16a 168
3f7c921f 169 BOOST_ASSERT( ( 0 < PingsPerformedCount ) && ( PingsPerformedCount <= ResolvedIpCount ) );
c5e4bfa1
GMF
170}
171
6c14bbee 172void HostStatus::increase_ping_failed_count()
c5e4bfa1
GMF
173{
174 ++PingsFailedCount;
c1fff16a
GMF
175
176 BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) );
c5e4bfa1
GMF
177}
178
6c14bbee 179void HostStatus::analyze_ping_failed_count()
ddf41c89 180{
cd4048df 181 BOOST_ASSERT( ( 0 <= PingFailLimitPercentage ) && ( PingFailLimitPercentage <= 100 ) );
c1fff16a
GMF
182 BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) );
183
cd4048df 184 int ping_fail_limit_count = ( ResolvedIpCount * PingFailLimitPercentage ) / 100;
c1fff16a 185
6827496c 186 // keep a boolean variable because the PingsFailedCount can be reseted
cd4048df 187 if ( PingsFailedCount > ping_fail_limit_count )
1d7d7cb2
GMF
188 {
189 ExceededPingFailedLimit = true;
3f7c921f 190
03c2a2c3 191 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f
CH
192 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
193 << ResolvedIpCount << " IPs: exceed limit=" << ping_fail_limit_count;
1d7d7cb2
GMF
194 }
195 else
196 {
197 ExceededPingFailedLimit = false;
3f7c921f 198
03c2a2c3 199 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f
CH
200 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
201 << ResolvedIpCount << " IPs: below limit=" << ping_fail_limit_count;
1d7d7cb2 202 }
c5e4bfa1 203}