A Simple MySQL Plugin to Retrieve System Metrics

栏目: IT技术 · 发布时间: 3年前

内容简介:So, I started a Proof of Concept for this.  My goal was to get metrics such as RAM (total, used, free), system load, CPU utilization, disk utilization for the file system containing the datadir, and more.  My objective was to do this as efficiently within

A Simple MySQL Plugin to Retrieve System Metrics Ever wanted to extend MySQL and add some feature you think it is missing?  With MySQL plugins, you can do exactly that.  One thing that has bothered me for several years is that you cannot easily retrieve system metrics from within MySQL.  Whether I am connecting via a remote connection or looking to add features to monitoring without the need for another interface with the server, I have wanted to retrieve system metrics without leaving the MySQL interface.

So, I started a Proof of Concept for this.  My goal was to get metrics such as RAM (total, used, free), system load, CPU utilization, disk utilization for the file system containing the datadir, and more.  My objective was to do this as efficiently within MySQL as possible.  For this, I chose to utilize standard C libraries in as few lines of code as possible without having to scrape system files or run commands to get the data.  The data is pulled on demand so as not to increase the load on the system.

The MySQL plugin architecture is one of the most underutilized features in MySQL in my opinion.  It provides so much power, and I feel the MySQL ecosystem would be so much more powerful if more people took advantage of it.  Below is an example of a basic plugin I created to pull some system metrics.

For this plugin, I chose to access the data via INFORMATION_SCHEMA.OS_METRICS.  This is defined in the plugin in the following:

static struct st_mysql_information_schema simple_table_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
 
static ST_FIELD_INFO simple_table_fields[]=
{
{"NAME", 15, MYSQL_TYPE_STRING, 0, 0, 0, 0},
{"VALUE", 6, MYSQL_TYPE_FLOAT, 0, MY_I_S_UNSIGNED, 0, 0},
{"COMMENT", 50, MYSQL_TYPE_STRING, 0, 0, 0, 0},
{0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
};
 
static int simple_fill_table(THD *thd, TABLE_LIST *tables, Item *cond)
{
struct sysinfo info;
TABLE *table= tables->table;

This defines the structure of the virtual table as having three columns: NAME, VALUE, and COMMENT.  NAME will be a string up to 15 characters long, followed by a float number for VALUE, and a text string for COMMENT up to 50 characters long.

By invoking the sysinfo() function in C, I am able to pull various metrics.  These metrics are returned in a structure.  These can then be passed into the OS_METRICS “table” with the following commands:

struct sysinfo info;
sysinfo(&info);
 
// Total usable main memory size
table->field[0]->store("TOTAL_RAM", 9, system_charset_info);
table->field[1]->store(info.totalram * info.mem_unit);
table->field[2]->store("Total usable main memory size", 29, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;

In the above case, I reference the element “totalram” from the sysinfo structure and store it in the table.  You can see where there is a line for each column of the table and the values are stored one by one.

Here is the most basic form of a plugin that only pulls RAM information and makes it available within INFORMATION_SCHEMA.OS_METRICS:

#include <sql_class.h>
#include <table.h>
#include <stdlib.h>
#include <ctype.h>
#include <mysql_version.h>
#include <mysql/plugin.h>
#include <my_global.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/sysinfo.h>
 
static struct st_mysql_information_schema simple_table_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
 
static ST_FIELD_INFO simple_table_fields[]=
{
{"NAME", 15, MYSQL_TYPE_STRING, 0, 0, 0, 0},
{"VALUE", 6, MYSQL_TYPE_FLOAT, 0, MY_I_S_UNSIGNED, 0, 0},
{"COMMENT", 50, MYSQL_TYPE_STRING, 0, 0, 0, 0},
{0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
};
 
static int simple_fill_table(THD *thd, TABLE_LIST *tables, Item *cond)
{
struct sysinfo info;
TABLE *table= tables->table;
 
sysinfo(&info);
 
// Total usable main memory size
table->field[0]->store("TOTAL_RAM", 9, system_charset_info);
table->field[1]->store(info.totalram * info.mem_unit);
table->field[2]->store("Total usable main memory size", 29, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
// Available memory size
table->field[0]->store("FREE_RAM", 8, system_charset_info);
table->field[1]->store(info.freeram * info.mem_unit);
table->field[2]->store("Available memory size", 21, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
// Used memory size
table->field[0]->store("USED_RAM", 8, system_charset_info);
table->field[1]->store((info.totalram - info.freeram) * info.mem_unit);
table->field[2]->store("Used memory size", 16, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
// Available memory (percentage)
table->field[0]->store("FREE_RAM_PCT", 12, system_charset_info);
table->field[1]->store((float) info.freeram / info.totalram * 100 * info.mem_unit);
table->field[2]->store("Available memory as a percentage", 32, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
// Used memory (percentage)
table->field[0]->store("USED_RAM_PCT", 12, system_charset_info);
table->field[1]->store((float) (info.totalram - info.freeram) / info.totalram * 100 * info.mem_unit);
table->field[2]->store("Free memory as a percentage", 27, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
// Amount of shared memory
table->field[0]->store("SHARED_RAM", 10, system_charset_info);
table->field[1]->store(info.sharedram * info.mem_unit);
table->field[2]->store("Amount of shared memory", 23, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
// Memory used by buffers
table->field[0]->store("BUFFER_RAM", 10, system_charset_info);
table->field[1]->store(info.bufferram * info.mem_unit);
table->field[2]->store("Memory used by buffers", 22, system_charset_info);
if (schema_table_store_record(thd, table)) return 1;
 
return 0;
}
 
static int simple_table_init(void *ptr)
{
ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE*)ptr;
schema_table->fields_info= simple_table_fields;
schema_table->fill_table= simple_fill_table;
return 0;
}
 
mysql_declare_plugin(os_metrics)
{
MYSQL_INFORMATION_SCHEMA_PLUGIN,
&simple_table_info, /* type-specific descriptor */
"OS_METRICS", /* table name */
"Michael Patrick", /* author */
"OS Metrics INFORMATION_SCHEMA table", /* description */
PLUGIN_LICENSE_GPL, /* license type */
simple_table_init, /* init function */
NULL,
0x0100, /* version = 1.0 */
NULL, /* no status variables */
NULL, /* no system variables */
NULL, /* no reserved information */
0 /* no flags */
}
mysql_declare_plugin_end;

You will need to have the MySQL source code available on a server along with the libraries needed to compile C code.  For me, I went with the most basic approach of manually compiling the plugin, although I need to update it with cmake so it is easier to compile.

I named my file, osmetricsplugin.cc.  Of course, in the example below, you will need to define the path for where your code lives where I have placed “{PATH_TO_YOUR_PLUGIN_CODE}”.

You can compile the plugin with a command such as the following:

SRCBASE="../percona-server-5.7.24-27"
g++ -DMYSQL_DYNAMIC_PLUGIN -Wall -fPIC -shared \
-I/usr/include/mysql -m64 \
-I${SRCBASE}/sql \
-I${SRCBASE}/include \
-I${SRCBASE}/libbinlogevents/export \
-I${SRCBASE}/libbinlogevents/include \
-I{PATH_TO_YOUR_PLUGIN_CODE} \
-o osmetricsplugin.so osmetricsplugin.cc

If you are interested in seeing more of what can be done with the above, check out the GitHub page for the plugin I wrote.

Once you compile it, you should get an osmetricsplugin.so file which can be copied to your MySQL plugin directory with a command such as:

cp osmetricsplugin.so /usr/lib64/mysql/plugin/

Once it is in place, you can tell MySQL to load the plugin with a command such as:

mysql> INSTALL PLUGIN OS_METRICS SONAME 'osmetricsplugin.so';

You can verify that the plugin is loaded correctly:

mysql> SELECT * FROM information_schema.PLUGINS WHERE PLUGIN_NAME LIKE "%OS%";;
+-------------+----------------+---------------+--------------------+---------------------+--------------------+------------------------+-----------------+-------------------------------------+----------------+-------------+
| PLUGIN_NAME | PLUGIN_VERSION | PLUGIN_STATUS | PLUGIN_TYPE        | PLUGIN_TYPE_VERSION | PLUGIN_LIBRARY     | PLUGIN_LIBRARY_VERSION | PLUGIN_AUTHOR   | PLUGIN_DESCRIPTION                  | PLUGIN_LICENSE | LOAD_OPTION |
+-------------+----------------+---------------+--------------------+---------------------+-------------------+------------------------+-----------------+-------------------------------------+----------------+-------------+
| OS_METRICS  | 1.0            | ACTIVE        | INFORMATION SCHEMA | 50724.0             | osmetricsplugin.so | 1.7                    | Michael Patrick | OS Metrics INFORMATION_SCHEMA table | GPL            | ON          |
+-------------+----------------+---------------+--------------------+---------------------+--------------------+------------------------+-----------------+-------------------------------------+----------------+-------------+
1 row in set (0.00 sec)

To query the data, execute a SQL command such as:

mysql> SELECT * FROM information_schema.OS_METRICS;
+------------------------+-------------------+-------------------------------------------------+
| NAME                   | VALUE             | COMMENT                                         |
+------------------------+-------------------+-------------------------------------------------+
| TOTAL_RAM              |        1039118336 | Total usable main memory size                   |
| FREE_RAM               |         341049344 | Available memory size                           |
| USED_RAM               |         698068992 | Used memory size                                |
| FREE_RAM_PCT           | 32.82102966308594 | Available memory as a percentage                |
| USED_RAM_PCT           | 67.17897033691406 | Free memory as a percentage                     |
| SHARED_RAM             |                 0 | Amount of shared memory                         |
| BUFFER_RAM             |           2158592 | Memory used by buffers                          |
+------------------------+-------------------+-------------------------------------------------+
7 rows in set (0.00 sec)

There is much more work to be done with the plugin and there is more that can be done to improve it.  I believe it is a very useful feature to be able to access system metrics from within MySQL, but am very interested to hear what others think.

If interested, please check out a more advanced version of the plugin , and here you can learn more about MySQL plugins .


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

小米之道

小米之道

(美)克莱•舍基 / 张琪 / 浙江人民出版社 / 2017-10-1 / 49.90元

共享经济、自媒体预言者,“互联网先知”克莱·舍基,继《认知盈余》《人人时代》后,聚焦风口上的小米。资深科技商业观察家金错刀、润米咨询创始人刘润作序推荐。附多篇雷军内部讲话,详细解读成功完成“筑底”后小米的全新商业模式 纵观中国互联网发展史,可以明显发现,本土互联网企业的崛起,几乎都是先引入国外商业模式,然后通过强化本土化特点来构筑自己的壁垒。在这种背景下,小米是名副其实的新物种,它走的是相反......一起来看看 《小米之道》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具