Global statistics, features, etc.
fixes #10116
Now pass the basic auth information to curl and send a GET request to the API:
- $ curl -u root:icinga -k -s 'https://nbmif.int.netways.de:5665/v1'
+ $ curl -u root:icinga -k -s 'https://localhost:5665/v1'
-In case you will get `Unauthorized` make sure to check the API user credentials.
+In case you will get an `Unauthorized` error message make sure to
+check the API user credentials.
### <a id="icinga2-api-permissions"></a> Permissions
/v1/actions | Endpoint for running specific [API actions](9-icinga2-api.md#icinga2-api-actions).
/v1/config | Endpoint for [managing configuration modules](9-icinga2-api.md#icinga2-api-config-management).
/v1/events | Endpoint for subscribing to [API events](9-icinga2-api.md#icinga2-api-actions).
- /v1/types | Endpoint for listing Icinga 2 configuration object types and their attributes.
+ /v1/status | Endpoint for receiving icinga2 [status and statistics](9-icinga2-api.md#icinga2-api-status).
+ /v1/types | Endpoint for listing Icinga 2 configuration object types and their attributes.
Additionally there are endpoints for each [config object type](6-object-types.md#object-types):
**TODO** Update
Url Endpoints | Description
- ----------------------|----------------------------------------------------
- /v1/hosts | Endpoint for retreiving and updating [Host](6-object-types.md#objecttype-host) objects.
+ ------------------|----------------------------------------------------
+ /v1/hosts | Endpoint for retreiving and updating [Host](6-object-types.md#objecttype-host) objects.
/v1/services | Endpoint for retreiving and updating [Service](6-object-types.md#objecttype-service) objects.
/v1/notifications | Endpoint for retreiving and updating [Notification](6-object-types.md#objecttype-notification) objects.
/v1/dependencies | Endpoint for retreiving and updating [Dependency](6-object-types.md#objecttype-dependency) objects.
- /v1/users | Endpoint for retreiving and updating [User](6-object-types.md#objecttype-user) objects.
+ /v1/users | Endpoint for retreiving and updating [User](6-object-types.md#objecttype-user) objects.
/v1/checkcommands | Endpoint for retreiving and updating [CheckCommand](6-object-types.md#objecttype-checkcommand) objects.
/v1/eventcommands | Endpoint for retreiving and updating [EventCommand](6-object-types.md#objecttype-eventcommand) objects.
/v1/notificationcommands | Endpoint for retreiving and updating [NotificationCommand](6-object-types.md#objecttype-notificationcommand) objects.
/v1/hostgroups | Endpoint for retreiving and updating [HostGroup](6-object-types.md#objecttype-hostgroup) objects.
/v1/servicegroups | Endpoint for retreiving and updating [ServiceGroup](6-object-types.md#objecttype-servicegroup) objects.
/v1/usergroups | Endpoint for retreiving and updating [UserGroup](6-object-types.md#objecttype-usergroup) objects.
- /v1/zones | Endpoint for retreiving and updating [Zone](6-object-types.md#objecttype-zone) objects.
+ /v1/zones | Endpoint for retreiving and updating [Zone](6-object-types.md#objecttype-zone) objects.
/v1/endpoints | Endpoint for retreiving and updating [Endpoint](6-object-types.md#objecttype-endpoint) objects.
/v1/timeperiods | Endpoint for retreiving and updating [TimePeriod](6-object-types.md#objecttype-timeperiod) objects.
**TODO** https://dev.icinga.org/issues/9078
+## <a id="icinga2-api-status"></a> Status and Statistics
+
+Contains a list of sub url endpoints which provide the status and statistics
+of available and enabled features. Any filters are ignored.
+
+Example for the main url endpoint `/v1/status`:
+
+ $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status' | python -m json.tool
+ {
+ "results": [
+ {
+ "name": "ApiListener"
+ },
+ ...
+ {
+ "name": "Collection"
+ },
+ ...
+ ]
+ }
+
+`/v1/status/Collection` is always available as virtual status url endpoint.
+It provides all feature status information into a collected overview.
+
+Example for the icinga application url endpoint `/v1/status/IcingaApplication`:
+
+ $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status/IcingaApplication' | python -m json.tool
+ {
+ "results": [
+ {
+ "perfdata": [],
+ "status": {
+ "icingaapplication": {
+ "app": {
+ "enable_event_handlers": true,
+ "enable_flapping": true,
+ "enable_host_checks": true,
+ "enable_notifications": true,
+ "enable_perfdata": true,
+ "enable_service_checks": true,
+ "node_name": "mbmif.int.netways.de",
+ "pid": 59819.0,
+ "program_start": 1443019345.093372,
+ "version": "v2.3.0-573-g380a131"
+ }
+ }
+ }
+ }
+ ]
+ }
## <a id="icinga2-api-objects"></a> API Objects
REGISTER_TYPE(FileLogger);
-REGISTER_STATSFUNCTION(FileLoggerStats, &FileLogger::StatsFunc);
+REGISTER_STATSFUNCTION(FileLogger, &FileLogger::StatsFunc);
void FileLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(SyslogLogger);
-REGISTER_STATSFUNCTION(SyslogLoggerStats, &SyslogLogger::StatsFunc);
+REGISTER_STATSFUNCTION(SyslogLogger, &SyslogLogger::StatsFunc);
void SyslogLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(CheckerComponent);
-REGISTER_STATSFUNCTION(CheckerComponentStats, &CheckerComponent::StatsFunc);
+REGISTER_STATSFUNCTION(CheckerComponent, &CheckerComponent::StatsFunc);
void CheckerComponent::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
{
REGISTER_TYPE(CheckResultReader);
-REGISTER_STATSFUNCTION(CheckResultReaderStats, &CheckResultReader::StatsFunc);
+REGISTER_STATSFUNCTION(CheckResultReader, &CheckResultReader::StatsFunc);
void CheckResultReader::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(CompatLogger);
-REGISTER_STATSFUNCTION(CompatLoggerStats, &CompatLogger::StatsFunc);
+REGISTER_STATSFUNCTION(CompatLogger, &CompatLogger::StatsFunc);
void CompatLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(ExternalCommandListener);
-REGISTER_STATSFUNCTION(ExternalCommandListenerStats, &ExternalCommandListener::StatsFunc);
+REGISTER_STATSFUNCTION(ExternalCommandListener, &ExternalCommandListener::StatsFunc);
void ExternalCommandListener::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(StatusDataWriter);
-REGISTER_STATSFUNCTION(StatusDataWriterStats, &StatusDataWriter::StatsFunc);
+REGISTER_STATSFUNCTION(StatusDataWriter, &StatusDataWriter::StatsFunc);
void StatusDataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
using namespace icinga;
REGISTER_TYPE(IdoMysqlConnection);
-REGISTER_STATSFUNCTION(IdoMysqlConnectionStats, &IdoMysqlConnection::StatsFunc);
+REGISTER_STATSFUNCTION(IdoMysqlConnection, &IdoMysqlConnection::StatsFunc);
IdoMysqlConnection::IdoMysqlConnection(void)
: m_QueryQueue(500000)
REGISTER_TYPE(IdoPgsqlConnection);
-REGISTER_STATSFUNCTION(IdoPgsqlConnectionStats, &IdoPgsqlConnection::StatsFunc);
+REGISTER_STATSFUNCTION(IdoPgsqlConnection, &IdoPgsqlConnection::StatsFunc);
IdoPgsqlConnection::IdoPgsqlConnection(void)
: m_QueryQueue(500000)
#include "icinga/cib.hpp"
#include "icinga/host.hpp"
#include "icinga/service.hpp"
+#include "icinga/perfdatavalue.hpp"
#include "base/objectlock.hpp"
#include "base/utility.hpp"
#include "base/configtype.hpp"
return std::make_pair(status, perfdata);
}
+REGISTER_STATSFUNCTION(CIB, &CIB::StatsFunc);
+
+void CIB::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata) {
+ double interval = Utility::GetTime() - Application::GetStartTime();
+
+ if (interval > 60)
+ interval = 60;
+
+ status->Set("active_host_checks", GetActiveHostChecksStatistics(interval) / interval);
+ status->Set("passive_host_checks", GetPassiveHostChecksStatistics(interval) / interval);
+ status->Set("active_host_checks_1min", GetActiveHostChecksStatistics(60));
+ status->Set("passive_host_checks_1min", GetPassiveHostChecksStatistics(60));
+ status->Set("active_host_checks_5min", GetActiveHostChecksStatistics(60 * 5));
+ status->Set("passive_host_checks_5min", GetPassiveHostChecksStatistics(60 * 5));
+ status->Set("active_host_checks_15min", GetActiveHostChecksStatistics(60 * 15));
+ status->Set("passive_host_checks_15min", GetPassiveHostChecksStatistics(60 * 15));
+
+ status->Set("active_service_checks", GetActiveServiceChecksStatistics(interval) / interval);
+ status->Set("passive_service_checks", GetPassiveServiceChecksStatistics(interval) / interval);
+ status->Set("active_service_checks_1min", GetActiveServiceChecksStatistics(60));
+ status->Set("passive_service_checks_1min", GetPassiveServiceChecksStatistics(60));
+ status->Set("active_service_checks_5min", GetActiveServiceChecksStatistics(60 * 5));
+ status->Set("passive_service_checks_5min", GetPassiveServiceChecksStatistics(60 * 5));
+ status->Set("active_service_checks_15min", GetActiveServiceChecksStatistics(60 * 15));
+ status->Set("passive_service_checks_15min", GetPassiveServiceChecksStatistics(60 * 15));
+
+ CheckableCheckStatistics scs = CalculateServiceCheckStats();
+
+ status->Set("min_latency", scs.min_latency);
+ status->Set("max_latency", scs.max_latency);
+ status->Set("avg_latency", scs.avg_latency);
+ status->Set("min_execution_time", scs.min_latency);
+ status->Set("max_execution_time", scs.max_latency);
+ status->Set("avg_execution_time", scs.avg_execution_time);
+
+ ServiceStatistics ss = CalculateServiceStats();
+
+ status->Set("num_services_ok", ss.services_ok);
+ status->Set("num_services_warning", ss.services_warning);
+ status->Set("num_services_critical", ss.services_critical);
+ status->Set("num_services_unknown", ss.services_unknown);
+ status->Set("num_services_pending", ss.services_pending);
+ status->Set("num_services_unreachable", ss.services_unreachable);
+ status->Set("num_services_flapping", ss.services_flapping);
+ status->Set("num_services_in_downtime", ss.services_in_downtime);
+ status->Set("num_services_acknowledged", ss.services_acknowledged);
+
+ double uptime = Utility::GetTime() - Application::GetStartTime();
+ status->Set("uptime", uptime);
+
+ HostStatistics hs = CalculateHostStats();
+
+ status->Set("num_hosts_up", hs.hosts_up);
+ status->Set("num_hosts_down", hs.hosts_down);
+ status->Set("num_hosts_unreachable", hs.hosts_unreachable);
+ status->Set("num_hosts_flapping", hs.hosts_flapping);
+ status->Set("num_hosts_in_downtime", hs.hosts_in_downtime);
+ status->Set("num_hosts_acknowledged", hs.hosts_acknowledged);
+}
static std::pair<Dictionary::Ptr, Array::Ptr> GetFeatureStats(void);
+ static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
+
private:
CIB(void);
ScriptGlobal::Set("ApplicationType", "IcingaApplication");
}
-REGISTER_STATSFUNCTION(IcingaApplicationStats, &IcingaApplication::StatsFunc);
+REGISTER_STATSFUNCTION(IcingaApplication, &IcingaApplication::StatsFunc);
void IcingaApplication::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
{
REGISTER_TYPE(IcingaStatusWriter);
-REGISTER_STATSFUNCTION(IcingaStatusWriterStats, &IcingaStatusWriter::StatsFunc);
+REGISTER_STATSFUNCTION(IcingaStatusWriter, &IcingaStatusWriter::StatsFunc);
void IcingaStatusWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
{
static int l_Connections = 0;
static boost::mutex l_ComponentMutex;
-REGISTER_STATSFUNCTION(LivestatusListenerStats, &LivestatusListener::StatsFunc);
+REGISTER_STATSFUNCTION(LivestatusListener, &LivestatusListener::StatsFunc);
void LivestatusListener::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
{
REGISTER_TYPE(NotificationComponent);
-REGISTER_STATSFUNCTION(NotificationComponentStats, &NotificationComponent::StatsFunc);
+REGISTER_STATSFUNCTION(NotificationComponent, &NotificationComponent::StatsFunc);
void NotificationComponent::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(GraphiteWriter);
-REGISTER_STATSFUNCTION(GraphiteWriterStats, &GraphiteWriter::StatsFunc);
+REGISTER_STATSFUNCTION(GraphiteWriter, &GraphiteWriter::StatsFunc);
void GraphiteWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(OpenTsdbWriter);
-REGISTER_STATSFUNCTION(OpenTsdbWriterStats, &OpenTsdbWriter::StatsFunc);
+REGISTER_STATSFUNCTION(OpenTsdbWriter, &OpenTsdbWriter::StatsFunc);
void OpenTsdbWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
REGISTER_TYPE(PerfdataWriter);
-REGISTER_STATSFUNCTION(PerfdataWriterStats, &PerfdataWriter::StatsFunc);
+REGISTER_STATSFUNCTION(PerfdataWriter, &PerfdataWriter::StatsFunc);
void PerfdataWriter::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
endpoint.cpp endpoint.thpp filterutility.cpp
httpchunkedencoding.cpp httpclientconnection.cpp httpserverconnection.cpp httphandler.cpp httprequest.cpp httpresponse.cpp
httputility.cpp jsonrpc.cpp jsonrpcconnection.cpp jsonrpcconnection-heartbeat.cpp
- messageorigin.cpp modifyobjecthandler.cpp statusqueryhandler.cpp typequeryhandler.cpp
+ messageorigin.cpp modifyobjecthandler.cpp statushandler.cpp statusqueryhandler.cpp typequeryhandler.cpp
url.cpp zone.cpp zone.thpp
)
boost::signals2::signal<void(bool)> ApiListener::OnMasterChanged;
-REGISTER_STATSFUNCTION(ApiListenerStats, &ApiListener::StatsFunc);
+REGISTER_STATSFUNCTION(ApiListener, &ApiListener::StatsFunc);
REGISTER_APIFUNCTION(Hello, icinga, &ApiListener::HelloAPIHandler);
void ApiListener::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
{
- Dictionary::Ptr nodes = new Dictionary();
std::pair<Dictionary::Ptr, Dictionary::Ptr> stats;
ApiListener::Ptr listener = ApiListener::GetInstance();
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "remote/statushandler.hpp"
+#include "remote/httputility.hpp"
+#include "base/serializer.hpp"
+#include "base/statsfunction.hpp"
+
+using namespace icinga;
+
+REGISTER_URLHANDLER("/v1/status", StatusHandler);
+
+bool StatusHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response)
+{
+ Dictionary::Ptr result = new Dictionary();
+
+ if (request.RequestMethod != "GET") {
+ response.SetStatus(400, "Bad request");
+ result->Set("info", "Request must be type GET");
+ HttpUtility::SendJsonBody(response, result);
+ return true;
+ }
+
+ if (request.RequestUrl->GetPath().size() < 2) {
+ response.SetStatus(400, "Bad request");
+ HttpUtility::SendJsonBody(response, result);
+ return true;
+ }
+
+ Array::Ptr results = new Array();
+ Dictionary::Ptr resultInner = new Dictionary();
+
+ if (request.RequestUrl->GetPath().size() > 2) {
+
+ StatsFunction::Ptr funcptr = StatsFunctionRegistry::GetInstance()->GetItem(request.RequestUrl->GetPath()[2]);
+ resultInner = new Dictionary();
+
+ if (!funcptr)
+ return false;
+
+ results->Add(resultInner);
+
+ Dictionary::Ptr status = new Dictionary();
+ Array::Ptr perfdata = new Array();
+ funcptr->Invoke(status, perfdata);
+
+ resultInner->Set("status", status);
+ resultInner->Set("perfdata", perfdata);
+ } else {
+ typedef std::pair<String, StatsFunction::Ptr> kv_pair;
+ BOOST_FOREACH(const kv_pair& kv, StatsFunctionRegistry::GetInstance()->GetItems()) {
+ resultInner = new Dictionary();
+ resultInner->Set("name", kv.first);
+ results->Add(resultInner);
+ }
+ }
+
+ result->Set("results", results);
+
+ response.SetStatus(200, "OK");
+ HttpUtility::SendJsonBody(response, result);
+
+ return true;
+}
+
+REGISTER_STATSFUNCTION(Collection, &StatusHandler::StatsFunc);
+
+void StatusHandler::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata)
+{
+ typedef std::pair<String, StatsFunction::Ptr> kv_pair;
+ BOOST_FOREACH(const kv_pair& kv, StatsFunctionRegistry::GetInstance()->GetItems()) {
+ if (kv.first == "Collection") //TODO Find a better name
+ continue;
+
+ Dictionary::Ptr funcStatus = new Dictionary();
+ Array::Ptr funcPData = new Array();
+ kv.second->Invoke(funcStatus, funcPData);
+
+ Dictionary::Ptr result = new Dictionary();
+ result->Set("status", funcStatus);
+ result->Set("perfdata", funcPData);
+ status->Set(kv.first, result);
+ }
+}
+
--- /dev/null
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#ifndef STATUSHANDLER_H
+#define STATUSHANDLER_H
+
+#include "remote/httphandler.hpp"
+
+namespace icinga
+{
+
+class I2_REMOTE_API StatusHandler : public HttpHandler
+{
+public:
+ DECLARE_PTR_TYPEDEFS(StatusHandler);
+
+ virtual bool HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) override;
+ static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
+};
+
+}
+
+#endif /* STATUSHANDLER_H */