ADD_SUBDIRECTORY(filesystem)
ADD_SUBDIRECTORY(hashing)
ADD_SUBDIRECTORY(logger)
-ADD_SUBDIRECTORY(numeric_monitoring)
ADD_SUBDIRECTORY(plugins)
ADD_SUBDIRECTORY(process)
ADD_SUBDIRECTORY(registry)
#include <osquery/events.h>
#include <osquery/filesystem/filesystem.h>
#include <osquery/flags.h>
-#include <osquery/numeric_monitoring.h>
#include <osquery/process/process.h>
#include <osquery/registry.h>
#include <osquery/utils/info/version.h>
DECLARE_string(config_plugin);
DECLARE_string(logger_plugin);
-DECLARE_string(numeric_monitoring_plugins);
DECLARE_bool(config_check);
DECLARE_bool(config_dump);
DECLARE_bool(database_dump);
DECLARE_bool(disable_database);
DECLARE_bool(disable_events);
DECLARE_bool(disable_logging);
-DECLARE_bool(enable_numeric_monitoring);
CLI_FLAG(bool, S, false, "Run as a shell process");
CLI_FLAG(bool, D, false, "Run as a daemon process");
initLogger(binary_);
}
- if (FLAGS_enable_numeric_monitoring) {
- initActivePlugin(monitoring::registryName(),
- FLAGS_numeric_monitoring_plugins);
- }
-
// Start event threads.
osquery::attachEvents();
EventFactory::delay();
#include <osquery/data_logger.h>
#include <osquery/database.h>
#include <osquery/flags.h>
-#include <osquery/numeric_monitoring.h>
#include <osquery/process/process.h>
#include <osquery/query.h>
#include <osquery/utils/system/time.h>
/// Used to bypass (optimize-out) the set-differential of query results.
DECLARE_bool(events_optimize);
-DECLARE_bool(enable_numeric_monitoring);
SQLInternal monitor(const std::string& name, const ScheduledQuery& query) {
- if (FLAGS_enable_numeric_monitoring) {
- return SQLInternal(query.query, true);
- } else {
- // Snapshot the performance and times for the worker before running.
- auto pid = std::to_string(PlatformProcess::getCurrentPid());
- auto r0 = SQL::selectFrom({"resident_size", "user_time", "system_time"},
- "processes",
- "pid",
- EQUALS,
- pid);
- auto t0 = getUnixTime();
- Config::get().recordQueryStart(name);
- SQLInternal sql(query.query, true);
- // Snapshot the performance after, and compare.
- auto t1 = getUnixTime();
- auto r1 = SQL::selectFrom({"resident_size", "user_time", "system_time"},
- "processes",
- "pid",
- EQUALS,
- pid);
- if (r0.size() > 0 && r1.size() > 0) {
- // Always called while processes table is working.
- Config::get().recordQueryPerformance(name, t1 - t0, r0[0], r1[0]);
- }
- return sql;
+ // Snapshot the performance and times for the worker before running.
+ auto pid = std::to_string(PlatformProcess::getCurrentPid());
+ auto r0 = SQL::selectFrom({"resident_size", "user_time", "system_time"},
+ "processes",
+ "pid",
+ EQUALS,
+ pid);
+ auto t0 = getUnixTime();
+ Config::get().recordQueryStart(name);
+ SQLInternal sql(query.query, true);
+ // Snapshot the performance after, and compare.
+ auto t1 = getUnixTime();
+ auto r1 = SQL::selectFrom({"resident_size", "user_time", "system_time"},
+ "processes",
+ "pid",
+ EQUALS,
+ pid);
+ if (r0.size() > 0 && r1.size() > 0) {
+ // Always called while processes table is working.
+ Config::get().recordQueryPerformance(name, t1 - t0, r0[0], r1[0]);
}
+ return sql;
}
Status launchQuery(const std::string& name, const ScheduledQuery& query) {
TablePlugin::kCacheInterval = query.splayed_interval;
TablePlugin::kCacheStep = i;
const auto status = launchQuery(name, query);
- monitoring::record(
- (boost::format("scheduler.query.%s.%s.status.%s") %
- query.pack_name % query.name %
- (status.ok() ? "success" : "failure"))
- .str(),
- 1,
- monitoring::PreAggregationType::Sum,
- true);
}
}));
// Configuration decorators run on 60 second intervals only.
#include <osquery/events.h>
#include <osquery/filesystem/filesystem.h>
#include <osquery/flags.h>
-#include <osquery/numeric_monitoring.h>
#include <osquery/plugins/logger.h>
#include <osquery/registry_factory.h>
#include <osquery/system.h>
+++ /dev/null
-# Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License
-
-ADD_OSQUERY_LIBRARY(osquery_numeric_monitoring numeric_monitoring.cpp
- plugin_interface.cpp
- pre_aggregation_cache.cpp)
-
-FILE(GLOB OSQUERY_NM_TESTS "tests/*.cpp")
-ADD_OSQUERY_TEST(${OSQUERY_NM_TESTS})
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <unordered_map>
-
-#include <boost/io/detail/quoted_manip.hpp>
-
-#include <osquery/dispatcher.h>
-#include <osquery/flags.h>
-#include <osquery/logger.h>
-#include <osquery/numeric_monitoring.h>
-#include <osquery/numeric_monitoring/plugin_interface.h>
-#include <osquery/numeric_monitoring/pre_aggregation_cache.h>
-#include <osquery/registry_factory.h>
-
-#include <osquery/utils/enum_class_hash.h>
-
-namespace osquery {
-
-FLAG(bool,
- enable_numeric_monitoring,
- false,
- "Enable numeric monitoring system");
-FLAG(string,
- numeric_monitoring_plugins,
- "filesystem",
- "Comma separated numeric monitoring plugins names");
-FLAG(uint64,
- numeric_monitoring_pre_aggregation_time,
- 60,
- "Time period in seconds for numeric monitoring pre-aggreagation buffer.");
-
-namespace {
-using monitoring::PreAggregationType;
-
-template <typename KeyType, typename ValueType, typename... Other>
-inline auto reverseMap(
- const std::unordered_map<KeyType, ValueType, Other...>& straight) {
- auto reversed = std::unordered_map<ValueType, KeyType>{};
- for (const auto& item : straight) {
- reversed.emplace(item.second, item.first);
- }
- return reversed;
-}
-
-const auto& getAggregationTypeToStringTable() {
- const auto static table =
- std::unordered_map<PreAggregationType, std::string, EnumClassHash>{
- {PreAggregationType::None, "none"},
- {PreAggregationType::Sum, "sum"},
- {PreAggregationType::Min, "min"},
- {PreAggregationType::Max, "max"},
- {PreAggregationType::Avg, "avg"},
- {PreAggregationType::Stddev, "stddev"},
- {PreAggregationType::P10, "p10"},
- {PreAggregationType::P50, "p50"},
- {PreAggregationType::P95, "p95"},
- {PreAggregationType::P99, "p99"}};
- return table;
-}
-
-const auto& getStringToAggregationTypeTable() {
- const auto static table = reverseMap(getAggregationTypeToStringTable());
- return table;
-}
-
-} // namespace
-
-template <>
-std::string to<std::string>(const monitoring::PreAggregationType& from) {
- auto it = getAggregationTypeToStringTable().find(from);
- if (it == getAggregationTypeToStringTable().end()) {
- LOG(ERROR) << "Unknown PreAggregationType "
- << static_cast<std::underlying_type<PreAggregationType>::type>(
- from)
- << " could not be converted to the string";
- return "";
- }
- return it->second;
-}
-
-template <>
-Expected<monitoring::PreAggregationType, ConversionError>
-tryTo<monitoring::PreAggregationType>(const std::string& from) {
- auto it = getStringToAggregationTypeTable().find(from);
- if (it == getStringToAggregationTypeTable().end()) {
- return createError(ConversionError::InvalidArgument)
- << "Wrong string representation of `PreAggregationType`: "
- << boost::io::quoted(from);
- }
- return it->second;
-}
-
-namespace monitoring {
-
-namespace {
-
-class FlusherIsScheduled {};
-FlusherIsScheduled schedule();
-
-class PreAggregationBuffer final {
- public:
- static PreAggregationBuffer& get() {
- static PreAggregationBuffer instance{};
- static auto const flusher_is_scheduled = schedule();
- boost::ignore_unused(flusher_is_scheduled);
- return instance;
- }
-
- void record(const std::string& path,
- const ValueType& value,
- const PreAggregationType& pre_aggregation,
- const bool sync,
- const TimePoint& time_point) {
- if (0 == FLAGS_numeric_monitoring_pre_aggregation_time || sync) {
- dispatchOne(path, value, pre_aggregation, sync, time_point);
- } else {
- std::lock_guard<std::mutex> lock(mutex_);
- cache_.addPoint(Point(path, value, pre_aggregation, time_point));
- }
- }
-
- void flush() {
- auto points = takeCachedPoints();
- for (const auto& pt : points) {
- dispatchOne(
- pt.path_, pt.value_, pt.pre_aggregation_type_, false, pt.time_point_);
- }
- }
-
- private:
- std::vector<Point> takeCachedPoints() {
- std::lock_guard<std::mutex> lock(mutex_);
- auto points = cache_.takePoints();
- return points;
- }
-
- void dispatchOne(const std::string& path,
- const ValueType& value,
- const PreAggregationType& pre_aggregation,
- const bool sync,
- const TimePoint& time_point) {
- auto status = Registry::call(
- registryName(),
- FLAGS_numeric_monitoring_plugins,
- {
- {recordKeys().path, path},
- {recordKeys().value, std::to_string(value)},
- {recordKeys().pre_aggregation, to<std::string>(pre_aggregation)},
- {recordKeys().timestamp,
- std::to_string(time_point.time_since_epoch().count())},
- {recordKeys().sync, sync ? "true" : "false"},
- });
- if (!status.ok()) {
- LOG(ERROR) << "Data loss. Numeric monitoring point dispatch failed: "
- << status.what();
- }
- }
-
- private:
- PreAggregationCache cache_;
- std::mutex mutex_;
-};
-
-class PreAggregationFlusher : public InternalRunnable {
- public:
- explicit PreAggregationFlusher()
- : InternalRunnable("numeric_monitoring_pre_aggregation_buffer_flusher") {}
-
- void start() override {
- while (!interrupted() &&
- 0 != FLAGS_numeric_monitoring_pre_aggregation_time) {
- pause(
- std::chrono::seconds(FLAGS_numeric_monitoring_pre_aggregation_time));
- PreAggregationBuffer::get().flush();
- }
- }
-};
-
-FlusherIsScheduled schedule() {
- Dispatcher::addService(std::make_shared<PreAggregationFlusher>());
- return FlusherIsScheduled{};
-}
-
-} // namespace
-
-void flush() {
- PreAggregationBuffer::get().flush();
-}
-
-void record(const std::string& path,
- ValueType value,
- PreAggregationType pre_aggregation,
- const bool sync,
- TimePoint time_point) {
- if (!FLAGS_enable_numeric_monitoring) {
- return;
- }
- PreAggregationBuffer::get().record(
- path, value, pre_aggregation, sync, std::move(time_point));
-}
-
-} // namespace monitoring
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <osquery/plugins/plugin.h>
-#include <osquery/registry_factory.h>
-
-#include "osquery/numeric_monitoring/plugin_interface.h"
-
-namespace osquery {
-
-CREATE_REGISTRY(NumericMonitoringPlugin, monitoring::registryName());
-
-namespace monitoring {
-
-const char* registryName() {
- static const auto name = "numeric_monitoring";
- return name;
-}
-
-namespace {
-
-RecordKeys createRecordKeys() {
- auto keys = RecordKeys{};
- keys.path = "path";
- keys.value = "value";
- keys.timestamp = "timestamp";
- keys.pre_aggregation = "pre_aggregation";
- keys.sync = "sync";
- return keys;
-};
-
-HostIdentifierKeys createHostIdentifierKeys() {
- auto keys = HostIdentifierKeys{};
- keys.name = "<DEVICE_NAME>";
- keys.scheme = "<DEVICE_HOSTNAME_SCHEME>";
- return keys;
-};
-
-} // namespace
-
-const RecordKeys& recordKeys() {
- static const auto keys = createRecordKeys();
- return keys;
-}
-
-const HostIdentifierKeys& hostIdentifierKeys() {
- static const auto keys = createHostIdentifierKeys();
- return keys;
-}
-
-} // namespace monitoring
-
-Status NumericMonitoringPlugin::call(const PluginRequest& request,
- PluginResponse& response) {
- // should be implemented in plugins
- return Status::success();
-}
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <chrono>
-#include <string>
-
-#include <osquery/core.h>
-#include <osquery/plugins/plugin.h>
-#include <osquery/query.h>
-#include <osquery/utils/expected/expected.h>
-
-#include <osquery/numeric_monitoring.h>
-
-namespace osquery {
-/**
- * @brief Interface class for numeric monitoring system plugins.
- * e.g. @see NumericMonitoringFilesystemPlugin from
- * osquery/numeric_monitoring/plugins/filesystem.h
- */
-class NumericMonitoringPlugin : public Plugin {
- public:
- Status call(const PluginRequest& request, PluginResponse& response) override;
-};
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <boost/io/detail/quoted_manip.hpp>
-
-#include <osquery/logger.h>
-#include "osquery/numeric_monitoring/pre_aggregation_cache.h"
-
-namespace osquery {
-
-namespace monitoring {
-
-Point::Point(std::string path,
- ValueType value,
- PreAggregationType pre_aggregation_type,
- TimePoint time_point)
- : path_(std::move(path)),
- value_(std::move(value)),
- pre_aggregation_type_(std::move(pre_aggregation_type)),
- time_point_(std::move(time_point)) {}
-
-bool Point::tryToAggregate(const Point& new_point) {
- if (path_ != new_point.path_) {
- LOG(WARNING) << "Pre-aggregation is not possible as point paths are not "
- "equal, previous path "
- << boost::io::quoted(path_) << ", new path "
- << boost::io::quoted(new_point.path_);
-
- return false;
- }
- if (pre_aggregation_type_ != new_point.pre_aggregation_type_) {
- LOG(WARNING) << "Pre-aggregation is not possible as PreAggregationType "
- "types are not equal, previous type is "
- << boost::io::quoted(to<std::string>(pre_aggregation_type_))
- << ", new one is "
- << boost::io::quoted(
- to<std::string>(new_point.pre_aggregation_type_));
- return false;
- }
- time_point_ = std::max(time_point_, new_point.time_point_);
- switch (pre_aggregation_type_) {
- case PreAggregationType::None:
- case PreAggregationType::Avg:
- case PreAggregationType::Stddev:
- case PreAggregationType::P10:
- case PreAggregationType::P50:
- case PreAggregationType::P95:
- case PreAggregationType::P99:
- return false;
- case PreAggregationType::Sum:
- value_ = value_ + new_point.value_;
- break;
- case PreAggregationType::Min:
- value_ = std::min(value_, new_point.value_);
- break;
- case PreAggregationType::Max:
- value_ = std::max(value_, new_point.value_);
- break;
- case PreAggregationType::InvalidTypeUpperLimit:
- // nothing to do, the type is invalid
- LOG(ERROR) << "Invalid Pre-aggregation type "
- << boost::io::quoted(to<std::string>(pre_aggregation_type_));
- return false;
- }
- return true;
-}
-
-void PreAggregationCache::addPoint(Point point) {
- auto previous_index = points_index_.find(point.path_);
- if (previous_index == points_index_.end()) {
- points_index_.emplace(point.path_, points_.size());
- points_.push_back(std::move(point));
- } else {
- auto& previous = points_[previous_index->second];
- if (!previous.tryToAggregate(point)) {
- points_index_[point.path_] = points_.size();
- points_.push_back(std::move(point));
- }
- }
-}
-
-std::vector<Point> PreAggregationCache::takePoints() {
- auto taken_points = std::vector<Point>{};
- std::swap(taken_points, points_);
- points_index_.clear();
- return taken_points;
-}
-
-} // namespace monitoring
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#pragma once
-
-#include <unordered_map>
-
-#include <osquery/numeric_monitoring.h>
-
-namespace osquery {
-
-namespace monitoring {
-
-/**
- * Monitoring system smallest unit
- * Consists of watched value itself, watching time, unique name for this set of
- * values and pre-aggregation type.
- * Performs pre-aggregation operations @see tryToAggregate.
- */
-class Point {
- public:
- /**
- * Constructor
- * Consists of watched value itself, watching time, unique name for this set
- * of values and pre-aggregation type.
- * @param path Path or in other words unique name for the sequence of
- * monitoring values
- * @param value Observed value
- * @param pre_aggregation_type Pre-aggregation type for the sequence
- * @param time_point Time point at which value was observed
- */
- explicit Point(std::string path,
- ValueType value,
- PreAggregationType pre_aggregation_type,
- TimePoint time_point);
-
- /**
- * Try to aggregate @param new_point into itself.
- * If `pre_aggregation_type` and `path` are the same in `new_point`, the value
- * of `new_point` will be aggregated with `value` from self and written to
- * self `value`. `true` will be returned in this case.
- * Otherwise nothing will be changed and `false` will be returned.
- */
- bool tryToAggregate(const Point& new_point);
-
- public:
- std::string path_;
- ValueType value_;
- PreAggregationType pre_aggregation_type_;
- TimePoint time_point_;
-};
-
-class PreAggregationCache {
- public:
- explicit PreAggregationCache() = default;
-
- void addPoint(Point point);
-
- std::vector<Point> takePoints();
-
- std::size_t size() const noexcept {
- return points_.size();
- }
-
- private:
- std::unordered_map<std::string, std::size_t> points_index_;
- std::vector<Point> points_;
-};
-
-} // namespace monitoring
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <gtest/gtest.h>
-
-#include <boost/filesystem.hpp>
-
-#include <osquery/database.h>
-#include <osquery/dispatcher.h>
-#include <osquery/flags.h>
-#include <osquery/numeric_monitoring.h>
-#include <osquery/registry_factory.h>
-#include <osquery/system.h>
-
-#include <osquery/utils/conversions/tryto.h>
-
-#include <osquery/numeric_monitoring/plugin_interface.h>
-
-namespace fs = boost::filesystem;
-
-namespace osquery {
-
-DECLARE_bool(disable_database);
-
-class NumericMonitoringTests : public testing::Test {
- public:
- void SetUp() override {
- Initializer::platformSetup();
- registryAndPluginInit();
- FLAGS_disable_database = true;
- DatabasePlugin::setAllowOpen(true);
- DatabasePlugin::initPlugin();
- }
-};
-
-namespace {
-void testAggrTypeToStringAndBack(const monitoring::PreAggregationType& aggrType,
- const std::string& aggrTypeStrRepr) {
- auto str = to<std::string>(aggrType);
- EXPECT_EQ(str, aggrTypeStrRepr);
-
- auto bRet = tryTo<monitoring::PreAggregationType>(str);
- EXPECT_FALSE(bRet.isError());
- EXPECT_EQ(bRet.get(), aggrType);
-}
-} // namespace
-
-TEST_F(NumericMonitoringTests, PreAggregationTypeToStringAndBack) {
- testAggrTypeToStringAndBack(monitoring::PreAggregationType::None, "none");
- testAggrTypeToStringAndBack(monitoring::PreAggregationType::Sum, "sum");
- testAggrTypeToStringAndBack(monitoring::PreAggregationType::Min, "min");
- testAggrTypeToStringAndBack(monitoring::PreAggregationType::Max, "max");
-}
-
-TEST_F(NumericMonitoringTests, PreAggregationTypeToStringRecall) {
- // let's make sure we have string representation for every PreAggregationType
- using UnderType = std::underlying_type<monitoring::PreAggregationType>::type;
- const auto upper_limit = static_cast<UnderType>(
- monitoring::PreAggregationType::InvalidTypeUpperLimit);
- for (auto i = UnderType{}; i < upper_limit; ++i) {
- auto e = static_cast<monitoring::PreAggregationType>(i);
- EXPECT_FALSE(to<std::string>(e).empty());
- }
-}
-
-DECLARE_bool(enable_numeric_monitoring);
-DECLARE_string(numeric_monitoring_plugins);
-DECLARE_uint64(numeric_monitoring_pre_aggregation_time);
-
-const auto kNameForTestPlugin =
- "test_plugin_osquery/numeric_monitoring/tests/numeric_monitoring_tests";
-
-class NumericMonitoringInMemoryTestPlugin : public NumericMonitoringPlugin {
- public:
- Status call(const PluginRequest& request, PluginResponse& response) override {
- NumericMonitoringInMemoryTestPlugin::points.push_back(request);
- return Status::success();
- }
-
- static std::vector<PluginRequest> points;
-};
-
-std::vector<PluginRequest> NumericMonitoringInMemoryTestPlugin::points;
-
-REGISTER(NumericMonitoringInMemoryTestPlugin,
- monitoring::registryName(),
- kNameForTestPlugin);
-
-TEST_F(NumericMonitoringTests, record_with_buffer) {
- const auto isEnabled = FLAGS_enable_numeric_monitoring;
- const auto plugins = FLAGS_numeric_monitoring_plugins;
- const auto pre_aggregation_time =
- FLAGS_numeric_monitoring_pre_aggregation_time;
-
- FLAGS_enable_numeric_monitoring = true;
- FLAGS_numeric_monitoring_plugins = kNameForTestPlugin;
- FLAGS_numeric_monitoring_pre_aggregation_time = 1;
-
- auto status = RegistryFactory::get().setActive(
- monitoring::registryName(), FLAGS_numeric_monitoring_plugins);
- ASSERT_TRUE(status.ok());
-
- monitoring::flush();
- NumericMonitoringInMemoryTestPlugin::points.clear();
-
- const auto monitoring_path = "some.path.to.heaven";
- monitoring::record(monitoring_path,
- monitoring::ValueType{83},
- monitoring::PreAggregationType::Sum,
- false);
- monitoring::record(monitoring_path,
- monitoring::ValueType{84},
- monitoring::PreAggregationType::Sum,
- true);
- monitoring::record(monitoring_path,
- monitoring::ValueType{88},
- monitoring::PreAggregationType::Sum);
- monitoring::record(monitoring_path,
- monitoring::ValueType{93},
- monitoring::PreAggregationType::Sum);
- monitoring::flush();
-
- EXPECT_EQ(2, NumericMonitoringInMemoryTestPlugin::points.size());
- EXPECT_EQ(monitoring_path,
- NumericMonitoringInMemoryTestPlugin::points.back().at(
- monitoring::recordKeys().path));
- auto valueInStr = NumericMonitoringInMemoryTestPlugin::points.back().at(
- monitoring::recordKeys().value);
- EXPECT_EQ(83 + 88 + 93, std::stoll(valueInStr));
-
- FLAGS_enable_numeric_monitoring = isEnabled;
- FLAGS_numeric_monitoring_plugins = plugins;
- FLAGS_numeric_monitoring_pre_aggregation_time = pre_aggregation_time;
-
- Dispatcher::stopServices();
- Dispatcher::joinServices();
-}
-
-TEST_F(NumericMonitoringTests, record_without_buffer) {
- const auto isEnabled = FLAGS_enable_numeric_monitoring;
- const auto plugins = FLAGS_numeric_monitoring_plugins;
- const auto pre_aggregation_time =
- FLAGS_numeric_monitoring_pre_aggregation_time;
-
- FLAGS_enable_numeric_monitoring = true;
- FLAGS_numeric_monitoring_plugins = kNameForTestPlugin;
- FLAGS_numeric_monitoring_pre_aggregation_time = 0;
-
- monitoring::flush();
- NumericMonitoringInMemoryTestPlugin::points.clear();
-
- auto status = RegistryFactory::get().setActive(
- monitoring::registryName(), FLAGS_numeric_monitoring_plugins);
- ASSERT_TRUE(status.ok());
- const auto monitoring_path = "some.path.to.heaven";
- monitoring::record(monitoring_path,
- monitoring::ValueType{146},
- monitoring::PreAggregationType::Sum);
- monitoring::record(monitoring_path,
- monitoring::ValueType{149},
- monitoring::PreAggregationType::Sum);
- monitoring::record(monitoring_path,
- monitoring::ValueType{152},
- monitoring::PreAggregationType::Sum);
-
- // pay attention there is no flush
-
- EXPECT_EQ(3, NumericMonitoringInMemoryTestPlugin::points.size());
- EXPECT_EQ(monitoring_path,
- NumericMonitoringInMemoryTestPlugin::points.back().at(
- monitoring::recordKeys().path));
- auto fristValueInStr = NumericMonitoringInMemoryTestPlugin::points.front().at(
- monitoring::recordKeys().value);
- EXPECT_EQ(146, std::stoll(fristValueInStr));
-
- auto lastValueInStr = NumericMonitoringInMemoryTestPlugin::points.back().at(
- monitoring::recordKeys().value);
- EXPECT_EQ(152, std::stoll(lastValueInStr));
-
- FLAGS_enable_numeric_monitoring = isEnabled;
- FLAGS_numeric_monitoring_plugins = plugins;
- FLAGS_numeric_monitoring_pre_aggregation_time = pre_aggregation_time;
-
- Dispatcher::stopServices();
- Dispatcher::joinServices();
-}
-
-} // namespace osquery
+++ /dev/null
-/**
- * Copyright (c) 2014-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed in accordance with the terms specified in
- * the LICENSE file found in the root directory of this source tree.
- */
-
-#include <chrono>
-#include <limits>
-#include <set>
-
-#include <gtest/gtest.h>
-
-#include <osquery/numeric_monitoring/pre_aggregation_cache.h>
-
-namespace osquery {
-
-GTEST_TEST(PreAggregationPoint, tryToUpdate_same_path_none) {
- const auto now = monitoring::Clock::now();
- const auto path = "test.path.to.nowhere/something";
- auto prev_pt =
- monitoring::Point(path, 1, monitoring::PreAggregationType::None, now);
- auto new_pt =
- monitoring::Point(path, 1, monitoring::PreAggregationType::None, now);
- ASSERT_FALSE(prev_pt.tryToAggregate(new_pt));
-}
-
-GTEST_TEST(PreAggregationPoint, tryToUpdate_same_path_different_types) {
- const std::set<monitoring::PreAggregationType> nonaggregatable = {
- monitoring::PreAggregationType::None,
- monitoring::PreAggregationType::Avg,
- monitoring::PreAggregationType::Stddev,
- monitoring::PreAggregationType::P10,
- monitoring::PreAggregationType::P50,
- monitoring::PreAggregationType::P95,
- monitoring::PreAggregationType::P99};
- const auto now = monitoring::Clock::now();
- const auto path = "test.path.to.nowhere/paranoid";
- using UnderType = std::underlying_type<monitoring::PreAggregationType>::type;
- const auto upper_limit = static_cast<UnderType>(
- monitoring::PreAggregationType::InvalidTypeUpperLimit);
- for (auto prev_ind = UnderType{}; prev_ind < upper_limit; ++prev_ind) {
- for (auto new_ind = UnderType{}; new_ind < upper_limit; ++new_ind) {
- auto prev_aggr = static_cast<monitoring::PreAggregationType>(prev_ind);
- auto prev_pt = monitoring::Point(path, 1, prev_aggr, now);
- auto new_aggr = static_cast<monitoring::PreAggregationType>(new_ind);
- auto new_pt = monitoring::Point(path, 1, new_aggr, now);
- if (new_aggr == prev_aggr &&
- nonaggregatable.find(new_aggr) == nonaggregatable.end()) {
- ASSERT_TRUE(prev_pt.tryToAggregate(new_pt));
- } else {
- ASSERT_FALSE(prev_pt.tryToAggregate(new_pt));
- }
- }
- }
-}
-
-GTEST_TEST(PreAggregationPoint, tryToUpdate_different_path_sum) {
- const auto now = monitoring::Clock::now();
- const auto prev_path = "test.path.to.nowhere/something";
- auto prev_pt =
- monitoring::Point(prev_path, 1, monitoring::PreAggregationType::Sum, now);
- const auto new_path = "test.path.to.nowhere/something.else";
- auto new_pt =
- monitoring::Point(new_path, 1, monitoring::PreAggregationType::Sum, now);
- ASSERT_FALSE(prev_pt.tryToAggregate(new_pt));
- ASSERT_FALSE(new_pt.tryToAggregate(prev_pt));
-}
-
-GTEST_TEST(PreAggregationPoint, tryToUpdate_sum) {
- const auto now = monitoring::Clock::now();
- const auto path = "test.path.to.nowhere";
- auto prev_pt =
- monitoring::Point(path, 399, monitoring::PreAggregationType::Sum, now);
- auto new_pt = monitoring::Point(path,
- -8,
- monitoring::PreAggregationType::Sum,
- now - std::chrono::seconds{2});
- ASSERT_TRUE(prev_pt.tryToAggregate(new_pt));
- EXPECT_EQ(now, prev_pt.time_point_);
- EXPECT_EQ(391, prev_pt.value_);
-}
-
-GTEST_TEST(PreAggregationPoint, tryToUpdate_min) {
- const auto now = monitoring::Clock::now();
- const auto path = "test.path.to.nowhere";
- auto prev_pt =
- monitoring::Point(path, 3, monitoring::PreAggregationType::Min, now);
- auto new_pt = monitoring::Point(path,
- 8,
- monitoring::PreAggregationType::Min,
- now - std::chrono::seconds{2});
- ASSERT_TRUE(prev_pt.tryToAggregate(new_pt));
- EXPECT_EQ(now, prev_pt.time_point_);
- EXPECT_EQ(3, prev_pt.value_);
-}
-
-GTEST_TEST(PreAggregationPoint, tryToUpdate_max) {
- const auto now = monitoring::Clock::now();
- const auto path = "test.path.to.nowhere";
- auto prev_pt =
- monitoring::Point(path, 3, monitoring::PreAggregationType::Max, now);
- auto new_pt = monitoring::Point(path,
- 42,
- monitoring::PreAggregationType::Max,
- now - std::chrono::hours{2});
- ASSERT_TRUE(prev_pt.tryToAggregate(new_pt));
- EXPECT_EQ(now, prev_pt.time_point_);
- EXPECT_EQ(42, prev_pt.value_);
-}
-
-GTEST_TEST(PreAggregationCache, life_cycle) {
- const auto now = monitoring::Clock::now();
- auto cache = monitoring::PreAggregationCache{};
- const auto none_path = "test.path.to.nowhere.none";
- ASSERT_EQ(0, cache.size());
- cache.addPoint(monitoring::Point(
- none_path, 1, monitoring::PreAggregationType::None, now));
- ASSERT_EQ(1, cache.size());
- cache.addPoint(monitoring::Point(
- none_path, 2, monitoring::PreAggregationType::None, now));
- ASSERT_EQ(2, cache.size());
-
- const auto sum_path = "test.path.to.nowhere.sum";
- cache.addPoint(monitoring::Point(sum_path,
- 3,
- monitoring::PreAggregationType::Sum,
- now - std::chrono::seconds(1)));
- ASSERT_EQ(3, cache.size());
- cache.addPoint(monitoring::Point(
- sum_path, -1, monitoring::PreAggregationType::Sum, now));
- ASSERT_EQ(3, cache.size());
-
- const auto min_path = "test.path.to.nowhere.min";
- cache.addPoint(monitoring::Point(min_path,
- 7,
- monitoring::PreAggregationType::Min,
- now - std::chrono::seconds(10)));
- ASSERT_EQ(4, cache.size());
- cache.addPoint(
- monitoring::Point(min_path,
- std::numeric_limits<monitoring::ValueType>::max(),
- monitoring::PreAggregationType::Min,
- now));
- ASSERT_EQ(4, cache.size());
- cache.addPoint(
- monitoring::Point(min_path,
- std::numeric_limits<monitoring::ValueType>::min(),
- monitoring::PreAggregationType::Min,
- now - std::chrono::seconds(1)));
- ASSERT_EQ(4, cache.size());
-
- const auto max_path = "test.path.to.nowhere.max";
- cache.addPoint(monitoring::Point(max_path,
- 7,
- monitoring::PreAggregationType::Max,
- now - std::chrono::seconds(99)));
- ASSERT_EQ(5, cache.size());
- cache.addPoint(
- monitoring::Point(max_path,
- std::numeric_limits<monitoring::ValueType>::max(),
- monitoring::PreAggregationType::Max,
- now - std::chrono::seconds(1)));
- ASSERT_EQ(5, cache.size());
- cache.addPoint(
- monitoring::Point(max_path,
- std::numeric_limits<monitoring::ValueType>::min(),
- monitoring::PreAggregationType::Max,
- now - std::chrono::seconds(2)));
- ASSERT_EQ(5, cache.size());
-
- cache.addPoint(monitoring::Point(
- none_path, 6, monitoring::PreAggregationType::None, now));
- ASSERT_EQ(6, cache.size());
-
- auto points = cache.takePoints();
- EXPECT_EQ(0, cache.size());
- ASSERT_EQ(6, points.size());
-
- cache.addPoint(
- monitoring::Point(sum_path, 9, monitoring::PreAggregationType::Sum, now));
- EXPECT_EQ(1, cache.size());
-
- auto counters = std::unordered_map<std::string, std::size_t>{
- {none_path, 0},
- {sum_path, 0},
- {min_path, 0},
- {max_path, 0},
- };
- for (const auto& p : points) {
- ++counters.at(p.path_);
- if (p.pre_aggregation_type_ == monitoring::PreAggregationType::Sum) {
- EXPECT_EQ(2, p.value_);
- EXPECT_EQ(now, p.time_point_);
- } else if (p.pre_aggregation_type_ == monitoring::PreAggregationType::Min) {
- EXPECT_EQ(std::numeric_limits<monitoring::ValueType>::min(), p.value_);
- EXPECT_EQ(now, p.time_point_);
- } else if (p.pre_aggregation_type_ == monitoring::PreAggregationType::Max) {
- EXPECT_EQ(std::numeric_limits<monitoring::ValueType>::max(), p.value_);
- EXPECT_EQ(now - std::chrono::seconds(1), p.time_point_);
- }
- }
- EXPECT_EQ(3, counters[none_path]);
- EXPECT_EQ(1, counters[sum_path]);
- EXPECT_EQ(1, counters[min_path]);
- EXPECT_EQ(1, counters[max_path]);
-}
-
-} // namespace osquery