- Add CPULimits gia cgroups
- Set NETLINK_NO_ENOBUFS option for NETLINK
- Add hard limit on cache size for RawEventAccumulator
This commit is contained in:
Tad Glines 2020-06-10 13:09:59 -07:00
Родитель d6dd19b083
Коммит 310f831209
19 изменённых файлов: 464 добавлений и 24 удалений

121
CGroups.cpp Normal file
Просмотреть файл

@ -0,0 +1,121 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdexcept>
#include "CGroups.h"
#include "FileUtils.h"
#include "StringUtils.h"
#include <system_error>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define CGROUP_CPU_ROOT "/sys/fs/cgroup/cpu,cpuacct"
#define CGROUP_PROCS_FILE "cgroup.procs"
#define CGROUP_TASKS_FILE "tasks"
#define CGROUP_CPU_SHARES_FILE "cpu.shares"
#define CGROUP_CPU_QUOTA_US_FILE "cpu.cfs_quota_us"
#define CGROUP_CPU_PERIOD_US_FILE "cpu.cfs_period_us"
void AppendUint64(const std::string& path, uint64_t val) {
AppendFile(path, {{std::to_string(val)}});
}
uint64_t ReadUint64(const std::string& path) {
auto lines = ReadFile(path);
if (lines.empty()) {
throw std::runtime_error("Empty File");
}
auto line = trim_whitespace(lines[0]);
return stoll(line);
}
void CGroupCPU::AddSelf() {
AppendUint64(_dir + CGROUP_PROCS_FILE, 0);
}
void CGroupCPU::AddSelfThread() {
auto tid = syscall(SYS_gettid);
AppendUint64(_dir + CGROUP_TASKS_FILE, tid);
}
std::vector<uint64_t> CGroupCPU::GetProcs() {
auto lines = ReadFile(_dir + CGROUP_PROCS_FILE);
std::vector<uint64_t> pids;
pids.reserve(lines.size());
for (auto& line : lines) {
pids.emplace_back(stoll(line));
}
return pids;
}
std::vector<uint64_t> CGroupCPU::GetTasks() {
auto lines = ReadFile(_dir + CGROUP_TASKS_FILE);
std::vector<uint64_t> tids;
tids.reserve(lines.size());
for (auto& line : lines) {
tids.emplace_back(stoll(line));
}
return tids;
}
uint64_t CGroupCPU::GetShares() {
return ReadUint64(_dir + CGROUP_CPU_SHARES_FILE);
}
void CGroupCPU::SetShares(uint64_t val) {
AppendUint64(_dir + CGROUP_CPU_SHARES_FILE, val);
}
uint64_t CGroupCPU::GetCFSPeriodUS() {
return ReadUint64(_dir + CGROUP_CPU_PERIOD_US_FILE);
}
void CGroupCPU::SetCFSPeriodUS(uint64_t val) {
AppendUint64(_dir + CGROUP_CPU_PERIOD_US_FILE, val);
}
uint64_t CGroupCPU::GetCFSQuotaUS() {
return ReadUint64(_dir + CGROUP_CPU_QUOTA_US_FILE);
}
void CGroupCPU::SetCFSQuotaUS(uint64_t val) {
AppendUint64(_dir + CGROUP_CPU_QUOTA_US_FILE, val);
}
std::shared_ptr<CGroupCPU> CGroups::OpenCPU(const std::string& name) {
if (!PathExists(CGROUP_CPU_ROOT)) {
throw std::runtime_error(std::string("Cgroups mount is mising: ") + CGROUP_CPU_ROOT);
}
std::string path = CGROUP_CPU_ROOT;
if (!name.empty() && name != "/") {
path = std::string(CGROUP_CPU_ROOT) + "/" + path;
}
if (!PathExists(path)) {
if (mkdir(path.c_str(), 0755) != 0) {
throw std::system_error(errno, std::system_category(), "mkdir("+path+")");
}
}
return std::make_shared<CGroupCPU>(path);
}

52
CGroups.h Normal file
Просмотреть файл

@ -0,0 +1,52 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef AUOMS_CGROUPS_H
#define AUOMS_CGROUPS_H
#include <vector>
#include <memory>
class CGroupCPU {
public:
CGroupCPU(const std::string& path): _dir(path) {}
void AddSelf();
void AddSelfThread();
std::vector<uint64_t> GetProcs();
std::vector<uint64_t> GetTasks();
uint64_t GetShares();
void SetShares(uint64_t val);
uint64_t GetCFSPeriodUS();
void SetCFSPeriodUS(uint64_t val);
uint64_t GetCFSQuotaUS();
void SetCFSQuotaUS(uint64_t val);
private:
std::string _dir;
};
class CGroups {
public:
static std::shared_ptr<CGroupCPU> OpenCPU(const std::string& name);
};
#endif //AUOMS_CGROUPS_H

Просмотреть файл

@ -82,6 +82,9 @@ add_executable(auomscollect
ProcMetrics.cpp ProcMetrics.cpp
Cache.h Cache.h
LockFile.cpp LockFile.cpp
CGroups.cpp
CPULimits.cpp
SchedPriority.cpp
) )
# See https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html # See https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html
@ -169,6 +172,8 @@ add_executable(auoms
SystemMetrics.cpp SystemMetrics.cpp
PriorityQueue.cpp PriorityQueue.h PriorityQueue.cpp PriorityQueue.h
LockFile.cpp LockFile.cpp
CGroups.cpp
CPULimits.cpp
) )
# See https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html # See https://gcc.gnu.org/onlinedocs/libstdc++/manual/license.html

67
CPULimits.cpp Normal file
Просмотреть файл

@ -0,0 +1,67 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "CPULimits.h"
#define CG_NAME_CONFIG_NAME "cpu_cgroup_name"
#define HARD_LIMIT_NAME "cpu_per_core_limit"
#define SOFT_LIMIT_NAME "cpu_soft_limit"
std::shared_ptr<CGroupCPU> CPULimits::CGFromConfig(const Config& config, const std::string& default_cg_name) {
std::string cg_name = default_cg_name;
double hard_limit = MAX_PCT;
double soft_limit = MAX_PCT;
if (config.HasKey(HARD_LIMIT_NAME)) {
hard_limit = config.GetDouble(HARD_LIMIT_NAME);
}
if (hard_limit > MAX_PCT) {
hard_limit = MAX_PCT;
} else if (hard_limit < MIN_PCT) {
hard_limit = MIN_PCT;
}
if (config.HasKey(SOFT_LIMIT_NAME)) {
soft_limit = config.GetDouble(SOFT_LIMIT_NAME);
}
if (soft_limit > MAX_PCT) {
soft_limit = MAX_PCT;
} else if (soft_limit < MIN_PCT) {
soft_limit = MIN_PCT;
}
if (config.HasKey(CG_NAME_CONFIG_NAME)) {
cg_name = config.GetString(CG_NAME_CONFIG_NAME);
}
auto cg = CGroups::OpenCPU(cg_name);
if (hard_limit < MAX_PCT) {
uint64_t period = cg->GetCFSPeriodUS();
uint64_t quota = static_cast<uint64_t>(static_cast<double>(period)*(hard_limit/100));
cg->SetCFSQuotaUS(quota);
}
if (soft_limit < MAX_PCT) {
uint64_t shares = static_cast<uint64_t>(static_cast<double>(1024)*(soft_limit/100));
cg->SetShares(shares);
}
return cg;
}

32
CPULimits.h Normal file
Просмотреть файл

@ -0,0 +1,32 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef AUOMS_CPULIMITS_H
#define AUOMS_CPULIMITS_H
#include "Config.h"
#include "CGroups.h"
class CPULimits {
public:
static constexpr double MAX_PCT = 100.0;
static constexpr double MIN_PCT = 1.0;
static std::shared_ptr<CGroupCPU> CGFromConfig(const Config& config, const std::string& default_cg_name);
};
#endif //AUOMS_CPULIMITS_H

12
Cache.h
Просмотреть файл

@ -80,11 +80,11 @@ public:
return false; return false;
} }
bool on(const K& key, const std::function<CacheEntryOP(const std::chrono::steady_clock::time_point& last_touched, V& value)>& fn) { bool on(const K& key, const std::function<CacheEntryOP(size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, V& value)>& fn) {
auto itr = _entries.find(key); auto itr = _entries.find(key);
if (itr != _entries.end()) { if (itr != _entries.end()) {
auto entry = itr->second; auto entry = itr->second;
auto op = fn(entry->_last_touched, entry->_item); auto op = fn(_entries.size(), entry->_last_touched, entry->_item);
if (op == CacheEntryOP::TOUCH) { if (op == CacheEntryOP::TOUCH) {
touch(entry); touch(entry);
} else if (op == CacheEntryOP::REMOVE) { } else if (op == CacheEntryOP::REMOVE) {
@ -95,11 +95,11 @@ public:
return false; return false;
} }
void for_all_oldest_first(const std::function<CacheEntryOP(const std::chrono::steady_clock::time_point& last_touched, const K& key, V& value)>& fn) { void for_all_oldest_first(const std::function<CacheEntryOP(size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, const K& key, V& value)>& fn) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
while (_oldest._newer != &_newest) { while (_oldest._newer != &_newest) {
auto entry = _oldest._newer; auto entry = _oldest._newer;
auto op = fn(entry->_last_touched, entry->_key, entry->_item); auto op = fn(_entries.size(), entry->_last_touched, entry->_key, entry->_item);
switch (op) { switch (op) {
case CacheEntryOP::TOUCH: case CacheEntryOP::TOUCH:
touch(entry); touch(entry);
@ -113,11 +113,11 @@ public:
} }
} }
void for_all_newest_first(const std::function<CacheEntryOP(const std::chrono::steady_clock::time_point& last_touched, const K& key, V& value)>& fn) { void for_all_newest_first(const std::function<CacheEntryOP(size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, const K& key, V& value)>& fn) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
while (_newest._older != &_oldest) { while (_newest._older != &_oldest) {
auto entry = _newest._older; auto entry = _newest._older;
auto op = fn(entry->_last_touched, entry->_key, entry->_item); auto op = fn(_entries.size(), entry->_last_touched, entry->_key, entry->_item);
switch (op) { switch (op) {
case CacheEntryOP::TOUCH: case CacheEntryOP::TOUCH:
touch(entry); touch(entry);

Просмотреть файл

@ -92,6 +92,17 @@ void WriteFile(const std::string& path, const std::vector<std::string>& lines) {
out.close(); out.close();
} }
void AppendFile(const std::string& path, const std::vector<std::string>& lines) {
std::ofstream out(path, std::ios::binary);
if (!out.is_open()) {
throw std::runtime_error("Failed to open '" + path + "'");
}
for (auto& line: lines) {
out << line << std::endl;
}
out.close();
}
bool RemoveFile(const std::string& path, bool throw_on_error) { bool RemoveFile(const std::string& path, bool throw_on_error) {
auto ret = unlink(path.c_str()); auto ret = unlink(path.c_str());
if (ret != 0) { if (ret != 0) {

Просмотреть файл

@ -20,6 +20,8 @@ std::vector<std::string> ReadFile(const std::string& path);
void WriteFile(const std::string& path, const std::vector<std::string>& lines); void WriteFile(const std::string& path, const std::vector<std::string>& lines);
void AppendFile(const std::string& path, const std::vector<std::string>& lines);
// Return false if doesn't exist (or unlink fails and throw_on_error == false) // Return false if doesn't exist (or unlink fails and throw_on_error == false)
bool RemoveFile(const std::string& path, bool throw_on_error); bool RemoveFile(const std::string& path, bool throw_on_error);

Просмотреть файл

@ -1,6 +1,18 @@
// /*
// Created by tad on 3/19/19. microsoft-oms-auditd-plugin
//
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "KernelInfo.h" #include "KernelInfo.h"
#include "Version.h" #include "Version.h"

Просмотреть файл

@ -1,6 +1,18 @@
// /*
// Created by tad on 3/19/19. microsoft-oms-auditd-plugin
//
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef AUOMS_KERNELINFO_H #ifndef AUOMS_KERNELINFO_H
#define AUOMS_KERNELINFO_H #define AUOMS_KERNELINFO_H

Просмотреть файл

@ -46,6 +46,11 @@ int Netlink::Open(reply_fn_t&& default_msg_handler_fn) {
return -saved_errno; return -saved_errno;
} }
int on = 1;
if (setsockopt(fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(on)) != 0) {
Logger::Error("Cannot set NETLINK_NO_ENOBUFS option on audit NETLINK socket: %s", std::strerror(errno));
}
_fd = fd; _fd = fd;
_default_msg_handler_fn = std::move(default_msg_handler_fn); _default_msg_handler_fn = std::move(default_msg_handler_fn);

Просмотреть файл

@ -146,7 +146,7 @@ int RawEventAccumulator::AddRecord(std::unique_ptr<RawEventRecord> record) {
auto event_id = record->GetEventId(); auto event_id = record->GetEventId();
int ret = 0; int ret = 0;
auto found = _events.on(event_id, [this,&record,&ret](const std::chrono::steady_clock::time_point& last_touched, std::shared_ptr<RawEvent>& event) { auto found = _events.on(event_id, [this,&record,&ret](size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, std::shared_ptr<RawEvent>& event) {
if (event->AddRecord(std::move(record))) { if (event->AddRecord(std::move(record))) {
ret = event->AddEvent(*_builder); ret = event->AddEvent(*_builder);
return CacheEntryOP::REMOVE; return CacheEntryOP::REMOVE;
@ -163,6 +163,14 @@ int RawEventAccumulator::AddRecord(std::unique_ptr<RawEventRecord> record) {
_events.add(event_id, event); _events.add(event_id, event);
} }
} }
_events.for_all_oldest_first([this](size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, const EventId& key, std::shared_ptr<RawEvent>& event) {
if (entry_count > MAX_CACHE_ENTRY) {
event->AddEvent(*_builder);
_event_metric->Add(1.0);
return CacheEntryOP::REMOVE;
}
return CacheEntryOP::STOP;
});
return 1; return 1;
} }
@ -171,8 +179,8 @@ void RawEventAccumulator::Flush(long milliseconds) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_events.for_all_oldest_first([this,now,milliseconds](const std::chrono::steady_clock::time_point& last_touched, const EventId& key, std::shared_ptr<RawEvent>& event) { _events.for_all_oldest_first([this,now,milliseconds](size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, const EventId& key, std::shared_ptr<RawEvent>& event) {
if (std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()-last_touched.time_since_epoch()) > std::chrono::milliseconds(milliseconds)) { if (entry_count > MAX_CACHE_ENTRY || std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()-last_touched.time_since_epoch()) > std::chrono::milliseconds(milliseconds)) {
event->AddEvent(*_builder); event->AddEvent(*_builder);
_event_metric->Add(1.0); _event_metric->Add(1.0);
return CacheEntryOP::REMOVE; return CacheEntryOP::REMOVE;
@ -180,7 +188,7 @@ void RawEventAccumulator::Flush(long milliseconds) {
return CacheEntryOP::STOP; return CacheEntryOP::STOP;
}); });
} else { } else {
_events.for_all_oldest_first([this](const std::chrono::steady_clock::time_point& last_touched, const EventId& key, std::shared_ptr<RawEvent>& event) { _events.for_all_oldest_first([this](size_t entry_count, const std::chrono::steady_clock::time_point& last_touched, const EventId& key, std::shared_ptr<RawEvent>& event) {
event->AddEvent(*_builder); event->AddEvent(*_builder);
_event_metric->Add(1.0); _event_metric->Add(1.0);
return CacheEntryOP::REMOVE; return CacheEntryOP::REMOVE;

Просмотреть файл

@ -64,6 +64,7 @@ public:
void Flush(long milliseconds); void Flush(long milliseconds);
private: private:
static constexpr size_t MAX_CACHE_ENTRY = 256;
std::mutex _mutex; std::mutex _mutex;
std::shared_ptr<EventBuilder> _builder; std::shared_ptr<EventBuilder> _builder;
std::shared_ptr<Metrics> _metrics; std::shared_ptr<Metrics> _metrics;

26
SchedPriority.cpp Normal file
Просмотреть файл

@ -0,0 +1,26 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "SchedPriority.h"
#include <sys/resource.h>
#include <cerrno>
bool SetProcNice(int nice) {
errno = 0;
setpriority(PRIO_PROCESS, 0, nice);
return errno == 0;
}

22
SchedPriority.h Normal file
Просмотреть файл

@ -0,0 +1,22 @@
/*
microsoft-oms-auditd-plugin
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef AUOMS_SCHEDPRIORITY_H
#define AUOMS_SCHEDPRIORITY_H
bool SetProcNice(int nice);
#endif //AUOMS_SCHEDPRIORITY_H

Просмотреть файл

@ -37,6 +37,7 @@
#include "SystemMetrics.h" #include "SystemMetrics.h"
#include "ProcMetrics.h" #include "ProcMetrics.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "CPULimits.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -290,6 +291,15 @@ int main(int argc, char**argv) {
} }
Logger::Info("Acquire singleton lock"); Logger::Info("Acquire singleton lock");
std::shared_ptr<CGroupCPU> cgcpu;
try {
cgcpu = CPULimits::CGFromConfig(config, "auoms");
cgcpu->AddSelf();
} catch (std::runtime_error& ex) {
Logger::Error("Failed to configure cpu cgroup: %s", ex.what());
Logger::Warn("CPU Limits cannot be enforced");
}
// This will block signals like SIGINT and SIGTERM // This will block signals like SIGINT and SIGTERM
// They will be handled once Signals::Start() is called. // They will be handled once Signals::Start() is called.
Signals::Init(); Signals::Init();

Просмотреть файл

@ -32,6 +32,8 @@
#include "FileUtils.h" #include "FileUtils.h"
#include "Metrics.h" #include "Metrics.h"
#include "ProcMetrics.h" #include "ProcMetrics.h"
#include "CPULimits.h"
#include "SchedPriority.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -49,6 +51,7 @@
#include "env_config.h" #include "env_config.h"
#include "LockFile.h" #include "LockFile.h"
#include "EventPrioritizer.h" #include "EventPrioritizer.h"
#include "CPULimits.h"
void usage() void usage()
{ {
@ -426,6 +429,11 @@ int main(int argc, char**argv) {
virt_limit = config.GetUint64("virt_limit"); virt_limit = config.GetUint64("virt_limit");
} }
int cpu_nice = -20;
if (config.HasKey("cpu_nice")) {
cpu_nice = config.GetInt64("cpu_nice");
}
bool use_syslog = true; bool use_syslog = true;
if (config.HasKey("use_syslog")) { if (config.HasKey("use_syslog")) {
use_syslog = config.GetBool("use_syslog"); use_syslog = config.GetBool("use_syslog");
@ -457,6 +465,21 @@ int main(int argc, char**argv) {
} }
Logger::Info("Acquire singleton lock"); Logger::Info("Acquire singleton lock");
std::shared_ptr<CGroupCPU> cgcpu_root;
std::shared_ptr<CGroupCPU> cgcpu;
try {
cgcpu_root = CGroups::OpenCPU("");
cgcpu = CPULimits::CGFromConfig(config, "auomscollect");
cgcpu->AddSelf();
} catch (std::runtime_error& ex) {
Logger::Error("Failed to configure cpu cgroup: %s", ex.what());
Logger::Warn("CPU Limits cannot be enforced");
}
if (!SetProcNice(cpu_nice)) {
Logger::Warn("Failed to set CPU nice value to %d: %s", cpu_nice, std::strerror(errno));
}
// This will block signals like SIGINT and SIGTERM // This will block signals like SIGINT and SIGTERM
// They will be handled once Signals::Start() is called. // They will be handled once Signals::Start() is called.
Signals::Init(); Signals::Init();
@ -529,14 +552,22 @@ int main(int argc, char**argv) {
Signals::Start(); Signals::Start();
output.Start(); output.Start();
if (netlink_mode) { // The ingest tasks needs to run outside cgroup limits
bool restart; std::thread ingest_thread([&]() {
do { // Move this thread back to the root cgroup (thus outside the auomscollect specific cgroup
restart = DoNetlinkCollection(raw_queue, ingest_bytes_metric, ingest_records_metric, lost_bytes_metric, lost_segments_metric); cgcpu_root->AddSelfThread();
} while (restart); if (netlink_mode) {
} else { bool restart;
DoStdinCollection(raw_queue, ingest_bytes_metric, ingest_records_metric, lost_bytes_metric, lost_segments_metric); do {
} restart = DoNetlinkCollection(raw_queue, ingest_bytes_metric, ingest_records_metric, lost_bytes_metric,
lost_segments_metric);
} while (restart);
} else {
DoStdinCollection(raw_queue, ingest_bytes_metric, ingest_records_metric, lost_bytes_metric,
lost_segments_metric);
}
});
ingest_thread.join();
Logger::Info("Exiting"); Logger::Info("Exiting");

Просмотреть файл

@ -65,6 +65,16 @@
# #
allowed_output_socket_dirs = /var/run/auoms:/var/opt/microsoft/omsagent:/var/run/mdsd allowed_output_socket_dirs = /var/run/auoms:/var/opt/microsoft/omsagent:/var/run/mdsd
# CPU per core hard limit
# A value between 1 and 100, controls the max percent CPU that can be consumed per CPU core present on the system.
# Even if there is no other process competing for CPU, auoms will not exceed this limit.
cpu_per_core_limit = 40
# CPU soft limit
# A value between 1 and 100, controls the percent CPU that auoms will get when competing with other processes
# If there are no other processes competing for CPU, then auoms will exceed this limit.
cpu_soft_limit = 10
# Controls logging to syslog # Controls logging to syslog
# #
#use_syslog = true #use_syslog = true

Просмотреть файл

@ -34,6 +34,19 @@
#min_fs_free_pct = 5 #min_fs_free_pct = 5
#save_delay = 250 #save_delay = 250
# CPU per core hard limit
# A value between 1 and 100, controls the max percent CPU that can be consumed per CPU core present on the system.
# Even if there is no other process competing for CPU, auoms will not exceed this limit.
cpu_per_core_limit = 40
# CPU soft limit
# A value between 1 and 100, controls the percent CPU that auoms will get when competing with other processes
# If there are no other processes competing for CPU, then auoms will exceed this limit.
cpu_soft_limit = 10
# CPU nice value
#cpu_nice = -20
# Controls logging to syslog # Controls logging to syslog
# #
#use_syslog = true #use_syslog = true