mirror of
				https://github.com/Icinga/icinga2.git
				synced 2025-10-31 11:14:10 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			183 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
 | |
| 
 | |
| #include "db_ido/idochecktask.hpp"
 | |
| #include "icinga/host.hpp"
 | |
| #include "icinga/checkcommand.hpp"
 | |
| #include "icinga/macroprocessor.hpp"
 | |
| #include "remote/apilistener.hpp"
 | |
| #include "remote/endpoint.hpp"
 | |
| #include "remote/zone.hpp"
 | |
| #include "base/function.hpp"
 | |
| #include "base/utility.hpp"
 | |
| #include "base/perfdatavalue.hpp"
 | |
| #include "base/configtype.hpp"
 | |
| #include "base/convert.hpp"
 | |
| 
 | |
| using namespace icinga;
 | |
| 
 | |
| REGISTER_FUNCTION_NONCONST(Internal, IdoCheck, &IdoCheckTask::ScriptFunc, "checkable:cr:resolvedMacros:useResolvedMacros");
 | |
| 
 | |
| void IdoCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr,
 | |
| 	const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
 | |
| {
 | |
| 	CheckCommand::Ptr commandObj = checkable->GetCheckCommand();
 | |
| 	Value raw_command = commandObj->GetCommandLine();
 | |
| 
 | |
| 	Host::Ptr host;
 | |
| 	Service::Ptr service;
 | |
| 	tie(host, service) = GetHostService(checkable);
 | |
| 
 | |
| 	MacroProcessor::ResolverList resolvers;
 | |
| 	if (service)
 | |
| 		resolvers.emplace_back("service", service);
 | |
| 	resolvers.emplace_back("host", host);
 | |
| 	resolvers.emplace_back("command", commandObj);
 | |
| 	resolvers.emplace_back("icinga", IcingaApplication::GetInstance());
 | |
| 
 | |
| 	String idoType = MacroProcessor::ResolveMacros("$ido_type$", resolvers, checkable->GetLastCheckResult(),
 | |
| 		nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
 | |
| 
 | |
| 	String idoName = MacroProcessor::ResolveMacros("$ido_name$", resolvers, checkable->GetLastCheckResult(),
 | |
| 		nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
 | |
| 
 | |
| 	String missingQueriesWarning;
 | |
| 	String missingQueriesCritical;
 | |
| 	String missingPendingQueriesWarning;
 | |
| 	String missingPendingQueriesCritical;
 | |
| 
 | |
| 	double queriesWarning = MacroProcessor::ResolveMacros("$ido_queries_warning$", resolvers, checkable->GetLastCheckResult(),
 | |
| 	    &missingQueriesWarning, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
 | |
| 
 | |
| 	double queriesCritical = MacroProcessor::ResolveMacros("$ido_queries_critical$", resolvers, checkable->GetLastCheckResult(),
 | |
| 	    &missingQueriesCritical, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
 | |
| 
 | |
| 	double pendingQueriesWarning = MacroProcessor::ResolveMacros("$ido_pending_queries_warning$", resolvers, checkable->GetLastCheckResult(),
 | |
| 	    &missingPendingQueriesWarning, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
 | |
| 
 | |
| 	double pendingQueriesCritical = MacroProcessor::ResolveMacros("$ido_pending_queries_critical$", resolvers, checkable->GetLastCheckResult(),
 | |
| 	    &missingPendingQueriesCritical, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros);
 | |
| 
 | |
| 	if (resolvedMacros && !useResolvedMacros)
 | |
| 		return;
 | |
| 
 | |
| 	if (idoType.IsEmpty()) {
 | |
| 		cr->SetOutput("Attribute 'ido_type' must be set.");
 | |
| 		cr->SetState(ServiceUnknown);
 | |
| 		checkable->ProcessCheckResult(cr);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (idoName.IsEmpty()) {
 | |
| 		cr->SetOutput("Attribute 'ido_name' must be set.");
 | |
| 		cr->SetState(ServiceUnknown);
 | |
| 		checkable->ProcessCheckResult(cr);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	Type::Ptr type = Type::GetByName(idoType);
 | |
| 
 | |
| 	if (!type || !DbConnection::TypeInstance->IsAssignableFrom(type)) {
 | |
| 		cr->SetOutput("DB IDO type '" + idoType + "' is invalid.");
 | |
| 		cr->SetState(ServiceUnknown);
 | |
| 		checkable->ProcessCheckResult(cr);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	auto *dtype = dynamic_cast<ConfigType *>(type.get());
 | |
| 	VERIFY(dtype);
 | |
| 
 | |
| 	DbConnection::Ptr conn = static_pointer_cast<DbConnection>(dtype->GetObject(idoName));
 | |
| 
 | |
| 	if (!conn) {
 | |
| 		cr->SetOutput("DB IDO connection '" + idoName + "' does not exist.");
 | |
| 		cr->SetState(ServiceUnknown);
 | |
| 		checkable->ProcessCheckResult(cr);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	double qps = conn->GetQueryCount(60) / 60.0;
 | |
| 
 | |
| 	if (conn->IsPaused()) {
 | |
| 		cr->SetOutput("DB IDO connection is temporarily disabled on this cluster instance.");
 | |
| 		cr->SetState(ServiceOK);
 | |
| 		checkable->ProcessCheckResult(cr);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	double pendingQueries = conn->GetPendingQueryCount();
 | |
| 
 | |
| 	if (!conn->GetConnected()) {
 | |
| 		if (conn->GetShouldConnect()) {
 | |
| 			cr->SetOutput("Could not connect to the database server.");
 | |
| 			cr->SetState(ServiceCritical);
 | |
| 		} else {
 | |
| 			cr->SetOutput("Not currently enabled: Another cluster instance is responsible for the IDO database.");
 | |
| 			cr->SetState(ServiceOK);
 | |
| 		}
 | |
| 
 | |
| 		checkable->ProcessCheckResult(cr);
 | |
| 
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	/* Schema versions. */
 | |
| 	String schema_version = conn->GetSchemaVersion();
 | |
| 	std::ostringstream msgbuf;
 | |
| 
 | |
| 	if (Utility::CompareVersion(IDO_CURRENT_SCHEMA_VERSION, schema_version) < 0) {
 | |
| 		msgbuf << "Outdated schema version: '" << schema_version << "'. Latest version: '"
 | |
| 		    << IDO_CURRENT_SCHEMA_VERSION << "'."
 | |
| 		    << " Queries per second: " << std::fixed << std::setprecision(3) << qps
 | |
| 		    << " Pending queries: " << std::fixed << std::setprecision(3) << pendingQueries << ".";
 | |
| 
 | |
| 		cr->SetState(ServiceWarning);
 | |
| 	} else {
 | |
| 		msgbuf << "Connected to the database server (Schema version: '" << schema_version << "')."
 | |
| 		    << " Queries per second: " << std::fixed << std::setprecision(3) << qps
 | |
| 		    << " Pending queries: " << std::fixed << std::setprecision(3) << pendingQueries << ".";
 | |
| 
 | |
| 		cr->SetState(ServiceOK);
 | |
| 	}
 | |
| 
 | |
| 	if (conn->GetEnableHa()) {
 | |
| 		double failoverTs = conn->GetLastFailover();
 | |
| 
 | |
| 		msgbuf << " Last failover: " << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", failoverTs) << ".";
 | |
| 	}
 | |
| 
 | |
| 	/* Check whether the thresholds have been defined and match. */
 | |
| 	if (missingQueriesCritical.IsEmpty() && qps < queriesCritical) {
 | |
| 		msgbuf << " " << qps << " queries/s lower than critical threshold (" << queriesCritical << " queries/s).";
 | |
| 
 | |
| 		cr->SetState(ServiceCritical);
 | |
| 	} else if (missingQueriesWarning.IsEmpty() && qps < queriesWarning) {
 | |
| 		msgbuf << " " << qps << " queries/s lower than warning threshold (" << queriesWarning << " queries/s).";
 | |
| 
 | |
| 		cr->SetState(ServiceWarning);
 | |
| 	}
 | |
| 
 | |
| 	if (missingPendingQueriesCritical.IsEmpty() && pendingQueries > pendingQueriesCritical) {
 | |
| 		msgbuf << " " << pendingQueries << " pending queries greater than critical threshold ("
 | |
| 		    << pendingQueriesCritical << " queries).";
 | |
| 
 | |
| 		cr->SetState(ServiceCritical);
 | |
| 	} else if (missingPendingQueriesWarning.IsEmpty() && pendingQueries > pendingQueriesWarning) {
 | |
| 		msgbuf << " " << pendingQueries << " pending queries greater than warning threshold ("
 | |
| 		    << pendingQueriesWarning << " queries).";
 | |
| 
 | |
| 		cr->SetState(ServiceWarning);
 | |
| 	}
 | |
| 
 | |
| 	cr->SetOutput(msgbuf.str());
 | |
| 
 | |
| 	cr->SetPerformanceData(new Array({
 | |
| 		{ new PerfdataValue("queries", qps, false, "", queriesWarning, queriesCritical) },
 | |
| 		{ new PerfdataValue("queries_1min", conn->GetQueryCount(60)) },
 | |
| 		{ new PerfdataValue("queries_5mins", conn->GetQueryCount(5 * 60)) },
 | |
| 		{ new PerfdataValue("queries_15mins", conn->GetQueryCount(15 * 60)) },
 | |
| 		{ new PerfdataValue("pending_queries", pendingQueries, false, "", pendingQueriesWarning, pendingQueriesCritical) }
 | |
| 	}));
 | |
| 
 | |
| 	checkable->ProcessCheckResult(cr);
 | |
| }
 |