You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.6 KiB
105 lines
2.6 KiB
/*
|
|
* RecordMySQLQuery Record MySQL queries by probing the alloc_query() function
|
|
* in mysqld. For Linux, uses BCC, eBPF. Embedded C.
|
|
*
|
|
* Basic example of BCC and uprobes.
|
|
*
|
|
* Copyright (c) Facebook, Inc.
|
|
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include "BPF.h"
|
|
|
|
const std::string BPF_PROGRAM = R"(
|
|
#include <linux/ptrace.h>
|
|
|
|
struct query_probe_t {
|
|
uint64_t ts;
|
|
pid_t pid;
|
|
char query[100];
|
|
};
|
|
|
|
BPF_HASH(queries, struct query_probe_t, int);
|
|
|
|
int probe_mysql_query(struct pt_regs *ctx, void* thd, char* query, size_t len) {
|
|
if (query) {
|
|
struct query_probe_t key = {};
|
|
|
|
key.ts = bpf_ktime_get_ns();
|
|
key.pid = bpf_get_current_pid_tgid();
|
|
|
|
bpf_probe_read_str(&key.query, sizeof(key.query), query);
|
|
|
|
int one = 1;
|
|
queries.update(&key, &one);
|
|
}
|
|
return 0;
|
|
}
|
|
)";
|
|
const std::string ALLOC_QUERY_FUNC = "_Z11alloc_queryP3THDPKcj";
|
|
|
|
// Define the same struct to use in user space.
|
|
struct query_probe_t {
|
|
uint64_t ts;
|
|
pid_t pid;
|
|
char query[100];
|
|
};
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc < 2) {
|
|
std::cout << "USAGE: RecordMySQLQuery PATH_TO_MYSQLD [duration]"
|
|
<< std::endl;
|
|
exit(1);
|
|
}
|
|
|
|
std::string mysql_path(argv[1]);
|
|
std::cout << "Using mysqld path: " << mysql_path << std::endl;
|
|
|
|
ebpf::BPF bpf;
|
|
auto init_res = bpf.init(BPF_PROGRAM);
|
|
if (init_res.code() != 0) {
|
|
std::cerr << init_res.msg() << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
auto attach_res =
|
|
bpf.attach_uprobe(mysql_path, ALLOC_QUERY_FUNC, "probe_mysql_query");
|
|
if (attach_res.code() != 0) {
|
|
std::cerr << attach_res.msg() << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
int probe_time = 10;
|
|
if (argc >= 3)
|
|
probe_time = atoi(argv[2]);
|
|
std::cout << "Probing for " << probe_time << " seconds" << std::endl;
|
|
sleep(probe_time);
|
|
|
|
auto table_handle = bpf.get_hash_table<query_probe_t, int>("queries");
|
|
auto table = table_handle.get_table_offline();
|
|
std::sort(
|
|
table.begin(), table.end(),
|
|
[](std::pair<query_probe_t, int> a, std::pair<query_probe_t, int> b) {
|
|
return a.first.ts < b.first.ts;
|
|
});
|
|
std::cout << table.size() << " queries recorded:" << std::endl;
|
|
for (auto it : table) {
|
|
std::cout << "Time: " << it.first.ts << " PID: " << it.first.pid
|
|
<< " Query: " << it.first.query << std::endl;
|
|
}
|
|
|
|
auto detach_res = bpf.detach_uprobe(mysql_path, ALLOC_QUERY_FUNC);
|
|
if (detach_res.code() != 0) {
|
|
std::cerr << detach_res.msg() << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|