mirror of https://github.com/Icinga/icinga2.git
Merge pull request #10015 from Icinga/malloc_info
/v1/debug/malloc_info: call malloc_info(3) if available
This commit is contained in:
commit
02ba5e4101
|
@ -365,6 +365,7 @@ check_function_exists(vfork HAVE_VFORK)
|
|||
check_function_exists(backtrace_symbols HAVE_BACKTRACE_SYMBOLS)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
check_function_exists(nice HAVE_NICE)
|
||||
check_function_exists(malloc_info HAVE_MALLOC_INFO)
|
||||
check_library_exists(dl dladdr "dlfcn.h" HAVE_DLADDR)
|
||||
check_library_exists(execinfo backtrace_symbols "" HAVE_LIBEXECINFO)
|
||||
check_include_file_cxx(cxxabi.h HAVE_CXXABI_H)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#cmakedefine HAVE_LIBEXECINFO
|
||||
#cmakedefine HAVE_CXXABI_H
|
||||
#cmakedefine HAVE_NICE
|
||||
#cmakedefine HAVE_MALLOC_INFO
|
||||
#cmakedefine HAVE_EDITLINE
|
||||
#cmakedefine HAVE_SYSTEMD
|
||||
|
||||
|
|
|
@ -288,6 +288,7 @@ Available permissions for specific URL endpoints:
|
|||
config/query | /v1/config | No | 1
|
||||
config/modify | /v1/config | No | 512
|
||||
console | /v1/console | No | 1
|
||||
debug | /v1/debug | No | 1
|
||||
events/<type> | /v1/events | No | 1
|
||||
objects/query/<type> | /v1/objects | Yes | 1
|
||||
objects/create/<type> | /v1/objects | No | 1
|
||||
|
@ -2528,6 +2529,72 @@ curl -k -s -S -i -u root:icinga -H 'Accept: application/json' \
|
|||
}
|
||||
```
|
||||
|
||||
## Memory Usage Analysis <a id="icinga2-api-memory"></a>
|
||||
|
||||
The GNU libc function `malloc_info(3)` provides memory allocation and usage
|
||||
statistics of Icinga 2 itself. You can call it directly by sending a `GET`
|
||||
request to the URL endpoint `/v1/debug/malloc_info`.
|
||||
|
||||
The [API permission](12-icinga2-api.md#icinga2-api-permissions) `debug` is required.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
curl -k -s -S -i -u root:icinga https://localhost:5665/v1/debug/malloc_info
|
||||
```
|
||||
|
||||
In contrast to other API endpoints, the response is not JSON,
|
||||
but the raw XML output from `malloc_info(3)`. See also the
|
||||
[glibc malloc(3) internals](https://sourceware.org/glibc/wiki/MallocInternals).
|
||||
|
||||
```xml
|
||||
<malloc version="1">
|
||||
<heap nr="0">
|
||||
<sizes>
|
||||
<size from="33" to="48" total="96" count="2"/>
|
||||
<size from="49" to="64" total="192" count="3"/>
|
||||
<size from="65" to="80" total="80" count="1"/>
|
||||
<unsorted from="84817" to="84817" total="84817" count="1"/>
|
||||
</sizes>
|
||||
<total type="fast" count="6" size="368"/>
|
||||
<total type="rest" count="2" size="859217"/>
|
||||
<system type="current" size="7409664"/>
|
||||
<system type="max" size="7409664"/>
|
||||
<aspace type="total" size="7409664"/>
|
||||
<aspace type="mprotect" size="7409664"/>
|
||||
</heap>
|
||||
<!-- ... -->
|
||||
<heap nr="30">
|
||||
<sizes>
|
||||
<size from="17" to="32" total="96" count="3"/>
|
||||
<size from="33" to="48" total="576" count="12"/>
|
||||
<size from="49" to="64" total="64" count="1"/>
|
||||
<size from="97" to="112" total="3584" count="32"/>
|
||||
<size from="49" to="49" total="98" count="2"/>
|
||||
<size from="81" to="81" total="810" count="10"/>
|
||||
<size from="257" to="257" total="2827" count="11"/>
|
||||
<size from="689" to="689" total="689" count="1"/>
|
||||
<size from="705" to="705" total="705" count="1"/>
|
||||
<unsorted from="81" to="81" total="81" count="1"/>
|
||||
</sizes>
|
||||
<total type="fast" count="48" size="4320"/>
|
||||
<total type="rest" count="27" size="118618"/>
|
||||
<system type="current" size="135168"/>
|
||||
<system type="max" size="135168"/>
|
||||
<aspace type="total" size="135168"/>
|
||||
<aspace type="mprotect" size="135168"/>
|
||||
<aspace type="subheaps" size="1"/>
|
||||
</heap>
|
||||
<total type="fast" count="938" size="79392"/>
|
||||
<total type="rest" count="700" size="4409469"/>
|
||||
<total type="mmap" count="0" size="0"/>
|
||||
<system type="current" size="15114240"/>
|
||||
<system type="max" size="15114240"/>
|
||||
<aspace type="total" size="15114240"/>
|
||||
<aspace type="mprotect" size="15114240"/>
|
||||
</malloc>
|
||||
```
|
||||
|
||||
## API Clients <a id="icinga2-api-clients"></a>
|
||||
|
||||
After its initial release in 2015, community members
|
||||
|
|
|
@ -32,6 +32,7 @@ set(remote_SOURCES
|
|||
infohandler.cpp infohandler.hpp
|
||||
jsonrpc.cpp jsonrpc.hpp
|
||||
jsonrpcconnection.cpp jsonrpcconnection.hpp jsonrpcconnection-heartbeat.cpp jsonrpcconnection-pki.cpp
|
||||
mallocinfohandler.cpp mallocinfohandler.hpp
|
||||
messageorigin.cpp messageorigin.hpp
|
||||
modifyobjecthandler.cpp modifyobjecthandler.hpp
|
||||
objectqueryhandler.cpp objectqueryhandler.hpp
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* Icinga 2 | (c) 2024 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "base/defer.hpp"
|
||||
#include "remote/filterutility.hpp"
|
||||
#include "remote/httputility.hpp"
|
||||
#include "remote/mallocinfohandler.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#ifdef HAVE_MALLOC_INFO
|
||||
# include <errno.h>
|
||||
# include <malloc.h>
|
||||
#endif /* HAVE_MALLOC_INFO */
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
REGISTER_URLHANDLER("/v1/debug/malloc_info", MallocInfoHandler);
|
||||
|
||||
bool MallocInfoHandler::HandleRequest(
|
||||
AsioTlsStream&,
|
||||
const ApiUser::Ptr& user,
|
||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
||||
const Url::Ptr& url,
|
||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
||||
const Dictionary::Ptr& params,
|
||||
boost::asio::yield_context&,
|
||||
HttpServerConnection&
|
||||
)
|
||||
{
|
||||
namespace http = boost::beast::http;
|
||||
|
||||
if (url->GetPath().size() != 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.method() != http::verb::get) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FilterUtility::CheckPermission(user, "debug");
|
||||
|
||||
#ifndef HAVE_MALLOC_INFO
|
||||
HttpUtility::SendJsonError(response, params, 501, "malloc_info(3) not available.");
|
||||
#else /* HAVE_MALLOC_INFO */
|
||||
char* buf = nullptr;
|
||||
size_t bufSize = 0;
|
||||
FILE* f = nullptr;
|
||||
|
||||
Defer release ([&f, &buf]() {
|
||||
if (f) {
|
||||
(void)fclose(f);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
});
|
||||
|
||||
f = open_memstream(&buf, &bufSize);
|
||||
|
||||
if (!f) {
|
||||
auto error (errno);
|
||||
|
||||
BOOST_THROW_EXCEPTION(posix_error()
|
||||
<< boost::errinfo_api_function("open_memstream")
|
||||
<< boost::errinfo_errno(error));
|
||||
}
|
||||
|
||||
if (malloc_info(0, f)) {
|
||||
auto error (errno);
|
||||
|
||||
BOOST_THROW_EXCEPTION(posix_error()
|
||||
<< boost::errinfo_api_function("malloc_info")
|
||||
<< boost::errinfo_errno(error));
|
||||
}
|
||||
|
||||
auto closeErr (fclose(f));
|
||||
f = nullptr;
|
||||
|
||||
if (closeErr) {
|
||||
auto error (errno);
|
||||
|
||||
BOOST_THROW_EXCEPTION(posix_error()
|
||||
<< boost::errinfo_api_function("fclose")
|
||||
<< boost::errinfo_errno(error));
|
||||
}
|
||||
|
||||
response.result(200);
|
||||
response.set(http::field::content_type, "application/xml");
|
||||
response.body() = std::string(buf, bufSize);
|
||||
response.content_length(response.body().size());
|
||||
#endif /* HAVE_MALLOC_INFO */
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* Icinga 2 | (c) 2024 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "remote/httphandler.hpp"
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class MallocInfoHandler final : public HttpHandler
|
||||
{
|
||||
public:
|
||||
DECLARE_PTR_TYPEDEFS(MallocInfoHandler);
|
||||
|
||||
bool HandleRequest(
|
||||
AsioTlsStream& stream,
|
||||
const ApiUser::Ptr& user,
|
||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
||||
const Url::Ptr& url,
|
||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
||||
const Dictionary::Ptr& params,
|
||||
boost::asio::yield_context& yc,
|
||||
HttpServerConnection& server
|
||||
) override;
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue