Skip to content

Commit

Permalink
Percona Telemetry Component implemented.
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-holubicki committed Mar 21, 2024
1 parent 2f8eeab commit f12bca2
Show file tree
Hide file tree
Showing 42 changed files with 1,590 additions and 25 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,8 @@ IF(WITH_ENCRYPTION_UDF)
ADD_SUBDIRECTORY(extra/opensslpp)
ENDIF()

option(WITH_PERCONA_TELEMETRY "Build Percona Telemetry component" OFF)

# Utility target to build every executable tagged with ADD_TEST.
ADD_CUSTOM_TARGET(unittest_all)

Expand Down
50 changes: 50 additions & 0 deletions components/percona_telemetry/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (c) 2017, 2021, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# 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, version 2.0, 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

DISABLE_MISSING_PROFILE_WARNING()

IF(WITH_PERCONA_TELEMETRY)
message(STATUS "Building Percona Telemetry component")
ELSE()
message(STATUS "Not building Percona Telemetry component")
RETURN()
ENDIF()

MYSQL_ADD_COMPONENT(percona_telemetry
percona_telemetry_component.cc
config.cc
data_provider.cc
storage.cc
worker.cc
component.cc
logger.cc
MODULE_ONLY
TEST_ONLY
)

IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1)
TARGET_LINK_LIBRARIES(component_percona_telemetry stdc++fs)
ENDIF()

TARGET_INCLUDE_DIRECTORIES(component_percona_telemetry SYSTEM PRIVATE ${BOOST_PATCHES_DIR} ${BOOST_INCLUDE_DIR})

TARGET_LINK_LIBRARIES(component_percona_telemetry extra::rapidjson)
53 changes: 53 additions & 0 deletions components/percona_telemetry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
To compile and run:
1. configure project with cmake `-DWITH_PERCONA_TELEMETRY=ON``
2. compile the server and the component
3. start mysqld
4. Percona Telemetry component is enabled by default
5. To disable without server restart execute `UNINSTALL COMPONENT "file://component_percona_telemetry";``
6. To make disable changes permanent set `percona_telemetry_disable=1` in `my.cnf`
```
mysql> show variables like '%percona_telemetry%';
+-----------------------------------------+---------------------------------+
| Variable_name | Value |
+-----------------------------------------+---------------------------------+
| percona_telemetry.grace_interval | 86400 |
| percona_telemetry.history_keep_interval | 604800 |
| percona_telemetry.scrape_interval | 86400 |
| percona_telemetry.telemetry_root_dir | /usr/local/percona/telemetry/ps |
| percona_telemetry_disable | OFF |
+-----------------------------------------+---------------------------------+
```
Configurable in my.cnf:
```
percona_telemetry.grace_interval = 20
percona_telemetry.scrape_interval = 30
percona_telemetry.history_keep_interval = 70
percona_telemetry.telemetry_root_dir = /some/custom/dir
percona_telemetry_disable = ON/OFF
```
Note that `percona_telemetry.telemetry_root_dir` has to exist and be writable.

```
+-----------------------------------------+----------------------------------------------------------------------+
| Variable_name | Value |
+-----------------------------------------+----------------------------------------------------------------------+
| percona_telemetry.grace_interval | 20 |
| percona_telemetry.history_keep_interval | 70 |
| percona_telemetry.scrape_interval | 30 |
| percona_telemetry.telemetry_root_dir | /usr/local/percona/telemetry/ps |
| percona_telemetry_disable | OFF |
+-----------------------------------------+----------------------------------------------------------------------+
```
When the telemetry component is permanently disabled:
```
mysql> show variables like '%percona_telemetry%';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| percona_telemetry_disable | ON |
+---------------------------+-------+
1 row in set (0,00 sec)
```


9 changes: 9 additions & 0 deletions components/percona_telemetry/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef PERCONA_TELEMETRY_COMMON_H
#define PERCONA_TELEMETRY_COMMON_H

#include <boost/preprocessor/stringize.hpp>

#define CURRENT_COMPONENT_NAME percona_telemetry
#define CURRENT_COMPONENT_NAME_STR BOOST_PP_STRINGIZE(CURRENT_COMPONENT_NAME)

#endif /* PERCONA_TELEMETRY_COMMON_H */
99 changes: 99 additions & 0 deletions components/percona_telemetry/component.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include <mysql/components/component_implementation.h>
#include <mysql/components/my_service.h>
#include <mysql/components/services/component_sys_var_service.h>
#include <mysql/components/services/log_builtins.h>
#include <mysql/components/services/mysql_command_consumer.h>
#include <mysql/components/services/mysql_command_services.h>
#include <mysql/components/services/mysql_current_thread_reader.h>
#include <mysql/components/services/security_context.h>

#include "common.h"
#include "percona_telemetry_component.h"

REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_thd_security_context,
thd_security_context_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_thread, command_thread_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_factory, command_factory_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_options, command_options_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_query, command_query_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_query_result,
command_query_result_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_field_info,
command_field_info_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_command_error_info,
command_error_info_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(registry, registry_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(log_builtins, log_builtins_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(log_builtins_string, log_builtins_string_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(component_sys_variable_register,
component_sys_variable_register_srv);
REQUIRES_SERVICE_PLACEHOLDER_AS(component_sys_variable_unregister,
component_sys_variable_unregister_srv);

static std::unique_ptr<PerconaTelemetryComponent> percona_telemetry_component;

static mysql_service_status_t component_init() {
auto services = std::make_unique<PerconaTelemetryComponent::Services>();
services->thread_security_context_service = thd_security_context_srv;
services->command_thread_service = command_thread_srv;
services->command_factory_service = command_factory_srv;
services->command_options_service = command_options_srv;
services->command_query_service = command_query_srv;
services->command_query_result_service = command_query_result_srv;
services->command_field_info_service = command_field_info_srv;
services->command_error_info_service = command_error_info_srv;
services->log_builtins_service = log_builtins_srv;
services->log_builtins_string = log_builtins_string_srv;
services->var_register_service = component_sys_variable_register_srv;
services->var_unregister_service = component_sys_variable_unregister_srv;

percona_telemetry_component =
std::make_unique<PerconaTelemetryComponent>(std::move(services));

if (percona_telemetry_component->start()) {
return 1;
}

return 0;
}

static mysql_service_status_t component_deinit() {
if (percona_telemetry_component->stop()) {
return 1;
}

percona_telemetry_component.reset();
return 0;
}

BEGIN_COMPONENT_PROVIDES(CURRENT_COMPONENT_NAME)
END_COMPONENT_PROVIDES();

BEGIN_COMPONENT_REQUIRES(CURRENT_COMPONENT_NAME)
REQUIRES_SERVICE_AS(mysql_thd_security_context, thd_security_context_srv),
REQUIRES_SERVICE_AS(mysql_command_thread, command_thread_srv),
REQUIRES_SERVICE_AS(mysql_command_factory, command_factory_srv),
REQUIRES_SERVICE_AS(mysql_command_options, command_options_srv),
REQUIRES_SERVICE_AS(mysql_command_query, command_query_srv),
REQUIRES_SERVICE_AS(mysql_command_query_result, command_query_result_srv),
REQUIRES_SERVICE_AS(mysql_command_field_info, command_field_info_srv),
REQUIRES_SERVICE_AS(mysql_command_error_info, command_error_info_srv),
REQUIRES_SERVICE_AS(registry, registry_srv),
REQUIRES_SERVICE_AS(log_builtins, log_builtins_srv),
REQUIRES_SERVICE_AS(log_builtins_string, log_builtins_string_srv),
REQUIRES_SERVICE_AS(component_sys_variable_register,
component_sys_variable_register_srv),
REQUIRES_SERVICE_AS(component_sys_variable_unregister,
component_sys_variable_unregister_srv),
END_COMPONENT_REQUIRES();

BEGIN_COMPONENT_METADATA(CURRENT_COMPONENT_NAME)
METADATA("mysql.author", "Percona Corporation"),
METADATA("mysql.license", "GPL"), METADATA("mysql.version", "1"),
END_COMPONENT_METADATA();

DECLARE_COMPONENT(CURRENT_COMPONENT_NAME, CURRENT_COMPONENT_NAME_STR)
component_init, component_deinit END_DECLARE_COMPONENT();

DECLARE_LIBRARY_COMPONENTS &COMPONENT_REF(CURRENT_COMPONENT_NAME)
END_DECLARE_LIBRARY_COMPONENTS
124 changes: 124 additions & 0 deletions components/percona_telemetry/config.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include "config.h"
#include <assert.h>
#include "common.h"

static constexpr char VAR_TELEMETRY_ROOT_DIR[] = "telemetry_root_dir";
static constexpr char VAR_SCRAPE_INTERVAL[] = "scrape_interval";
static constexpr char VAR_GRACE_INTERVAL[] = "grace_interval";
static constexpr char VAR_HISTORY_KEEP_INTERVAL[] = "history_keep_interval";

static constexpr char TELEMETRY_ROOT_DIR_DEFAULT[] =
"/usr/local/percona/telemetry/ps";

static constexpr int SCRAPE_INTERVAL_DEFAULT = 60 * 60 * 24 * 1; // 1 day
static constexpr int SCRAPE_INTERVAL_MIN = 10;
static constexpr int SCRAPE_INTERVAL_MAX = 60 * 60 * 24 * 7; // 1 week

static constexpr int GRACE_INTERVAL_DEFAULT = 60 * 60 * 24 * 1; // 1 day
static constexpr int GRACE_INTERVAL_MIN = 20;
static constexpr int GRACE_INTERVAL_MAX = 60 * 60 * 24 * 2; // 2 days

static constexpr int HISTORY_KEEP_INTERVAL_DEFAULT =
60 * 60 * 24 * 7; // 7 days
static constexpr int HISTORY_KEEP_INTERVAL_MIN = 60;
static constexpr int HISTORY_KEEP_INTERVAL_MAX = HISTORY_KEEP_INTERVAL_DEFAULT;

Config::Config(SERVICE_TYPE(component_sys_variable_register) &
var_register_service,
SERVICE_TYPE(component_sys_variable_unregister) &
var_unregister_service)
: var_register_service_(var_register_service),
var_unregister_service_(var_unregister_service),
telemetry_root_dir_value_(nullptr) {}

bool Config::init() {
STR_CHECK_ARG(str) telemetry_root_dir_arg;
telemetry_root_dir_arg.def_val =
const_cast<char *>(TELEMETRY_ROOT_DIR_DEFAULT);
if (var_register_service_.register_variable(
CURRENT_COMPONENT_NAME_STR, VAR_TELEMETRY_ROOT_DIR,
PLUGIN_VAR_STR | PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY,
"Root path of the telemetry data for all mysqld servers", nullptr,
nullptr, &telemetry_root_dir_arg, &telemetry_root_dir_value_)) {
return true;
}

INTEGRAL_CHECK_ARG(uint)
scrape_interval_arg, grace_interval_arg, history_keep_interval_arg;
scrape_interval_arg.def_val = SCRAPE_INTERVAL_DEFAULT;
scrape_interval_arg.min_val = SCRAPE_INTERVAL_MIN;
scrape_interval_arg.max_val = SCRAPE_INTERVAL_MAX;
scrape_interval_arg.blk_sz = 0;
if (var_register_service_.register_variable(
CURRENT_COMPONENT_NAME_STR, VAR_SCRAPE_INTERVAL,
PLUGIN_VAR_INT | PLUGIN_VAR_READONLY, "Telemetry scrape interval",
nullptr, nullptr, &scrape_interval_arg, &scrape_interval_value_)) {
return true;
}

grace_interval_arg.def_val = GRACE_INTERVAL_DEFAULT;
grace_interval_arg.min_val = GRACE_INTERVAL_MIN;
grace_interval_arg.max_val = GRACE_INTERVAL_MAX;
grace_interval_arg.blk_sz = 0;
if (var_register_service_.register_variable(
CURRENT_COMPONENT_NAME_STR, VAR_GRACE_INTERVAL,
PLUGIN_VAR_INT | PLUGIN_VAR_READONLY, "Telemetry grace interval",
nullptr, nullptr, &grace_interval_arg, &grace_interval_value_)) {
return true;
}

history_keep_interval_arg.def_val = HISTORY_KEEP_INTERVAL_DEFAULT;
history_keep_interval_arg.min_val = HISTORY_KEEP_INTERVAL_MIN;
history_keep_interval_arg.max_val = HISTORY_KEEP_INTERVAL_MAX;
history_keep_interval_arg.blk_sz = 0;
if (var_register_service_.register_variable(
CURRENT_COMPONENT_NAME_STR, VAR_HISTORY_KEEP_INTERVAL,
PLUGIN_VAR_INT | PLUGIN_VAR_READONLY,
"Telemetry history keep interval", nullptr, nullptr,
&history_keep_interval_arg, &history_keep_interval_value_)) {
return true;
}

return false;
}

bool Config::deinit() {
bool res = false;
if (var_unregister_service_.unregister_variable(CURRENT_COMPONENT_NAME_STR,
VAR_TELEMETRY_ROOT_DIR)) {
res = true;
}
if (var_unregister_service_.unregister_variable(CURRENT_COMPONENT_NAME_STR,
VAR_SCRAPE_INTERVAL)) {
res = true;
}
if (var_unregister_service_.unregister_variable(CURRENT_COMPONENT_NAME_STR,
VAR_GRACE_INTERVAL)) {
res = true;
}
if (var_unregister_service_.unregister_variable(CURRENT_COMPONENT_NAME_STR,
VAR_HISTORY_KEEP_INTERVAL)) {
res = true;
}

return res;
}

const std::string &Config::telemetry_storage_dir_path() const noexcept {
assert(telemetry_root_dir_value_);
// it is read-only value
static std::string telemetry_root_dir_value_str(telemetry_root_dir_value_);
return telemetry_root_dir_value_str;
}

int Config::scrape_interval() const noexcept { return scrape_interval_value_; }

int Config::grace_interval() const noexcept { return grace_interval_value_; }

int Config::history_keep_interval() const noexcept {
return history_keep_interval_value_;
}

int Config::unconditional_history_cleanup_interval() const noexcept {
return HISTORY_KEEP_INTERVAL_MAX;
}
41 changes: 41 additions & 0 deletions components/percona_telemetry/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef PERCONA_TELEMETRY_CONFIG_H
#define PERCONA_TELEMETRY_CONFIG_H

#include <memory>
#include <string>

#include <mysql/components/component_implementation.h>
#include <mysql/components/services/component_sys_var_service.h>

class Config {
public:
Config(SERVICE_TYPE(component_sys_variable_register) & var_register_service,
SERVICE_TYPE(component_sys_variable_unregister) &
var_unregister_service);
~Config() = default;

Config(const Config &rhs) = delete;
Config(Config &&rhs) = delete;
Config &operator=(const Config &rhs) = delete;
Config &operator=(Config &&rhs) = delete;

bool init();
bool deinit();

const std::string &telemetry_storage_dir_path() const noexcept;
int scrape_interval() const noexcept;
int grace_interval() const noexcept;
int history_keep_interval() const noexcept;
int unconditional_history_cleanup_interval() const noexcept;

private:
SERVICE_TYPE(component_sys_variable_register) & var_register_service_;
SERVICE_TYPE(component_sys_variable_unregister) & var_unregister_service_;

const char *telemetry_root_dir_value_;
uint scrape_interval_value_;
uint grace_interval_value_;
uint history_keep_interval_value_;
};

#endif /* PERCONA_TELEMETRY_CONFIG_H */
Loading

0 comments on commit f12bca2

Please sign in to comment.