1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# mysqld_qslower MySQL server queries slower than a threshold. 4*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, BPF. Embedded C. 5*387f9dfdSAndroid Build Coastguard Worker# 6*387f9dfdSAndroid Build Coastguard Worker# USAGE: mysqld_qslower PID [min_ms] 7*387f9dfdSAndroid Build Coastguard Worker# 8*387f9dfdSAndroid Build Coastguard Worker# By default, a threshold of 1.0 ms is used. Set this to 0 ms to trace all 9*387f9dfdSAndroid Build Coastguard Worker# queries (verbose). 10*387f9dfdSAndroid Build Coastguard Worker# 11*387f9dfdSAndroid Build Coastguard Worker# This uses USDT probes, and needs a MySQL server with -DENABLE_DTRACE=1. 12*387f9dfdSAndroid Build Coastguard Worker# 13*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc. 14*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 15*387f9dfdSAndroid Build Coastguard Worker# 16*387f9dfdSAndroid Build Coastguard Worker# 30-Jul-2016 Brendan Gregg Created this. 17*387f9dfdSAndroid Build Coastguard Worker 18*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 19*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT 20*387f9dfdSAndroid Build Coastguard Workerimport sys 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker# arguments 23*387f9dfdSAndroid Build Coastguard Workerdef usage(): 24*387f9dfdSAndroid Build Coastguard Worker print("USAGE: mysqld_qslower PID [min_ms]") 25*387f9dfdSAndroid Build Coastguard Worker exit() 26*387f9dfdSAndroid Build Coastguard Workerif len(sys.argv) < 2: 27*387f9dfdSAndroid Build Coastguard Worker usage() 28*387f9dfdSAndroid Build Coastguard Workerif sys.argv[1][0:1] == "-": 29*387f9dfdSAndroid Build Coastguard Worker usage() 30*387f9dfdSAndroid Build Coastguard Workerpid = int(sys.argv[1]) 31*387f9dfdSAndroid Build Coastguard Workermin_ns = 1 * 1000000 32*387f9dfdSAndroid Build Coastguard Workermin_ms_text = 1 33*387f9dfdSAndroid Build Coastguard Workerif len(sys.argv) == 3: 34*387f9dfdSAndroid Build Coastguard Worker min_ns = float(sys.argv[2]) * 1000000 35*387f9dfdSAndroid Build Coastguard Worker min_ms_text = sys.argv[2] 36*387f9dfdSAndroid Build Coastguard Workerdebug = 0 37*387f9dfdSAndroid Build Coastguard WorkerQUERY_MAX = 128 38*387f9dfdSAndroid Build Coastguard Worker 39*387f9dfdSAndroid Build Coastguard Worker# load BPF program 40*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 41*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 42*387f9dfdSAndroid Build Coastguard Worker 43*387f9dfdSAndroid Build Coastguard Worker#define QUERY_MAX """ + str(QUERY_MAX) + """ 44*387f9dfdSAndroid Build Coastguard Worker 45*387f9dfdSAndroid Build Coastguard Workerstruct start_t { 46*387f9dfdSAndroid Build Coastguard Worker u64 ts; 47*387f9dfdSAndroid Build Coastguard Worker char *query; 48*387f9dfdSAndroid Build Coastguard Worker}; 49*387f9dfdSAndroid Build Coastguard Worker 50*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 51*387f9dfdSAndroid Build Coastguard Worker u32 pid; 52*387f9dfdSAndroid Build Coastguard Worker u64 ts; 53*387f9dfdSAndroid Build Coastguard Worker u64 delta; 54*387f9dfdSAndroid Build Coastguard Worker char query[QUERY_MAX]; 55*387f9dfdSAndroid Build Coastguard Worker}; 56*387f9dfdSAndroid Build Coastguard Worker 57*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start_tmp, u32, struct start_t); 58*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Workerint do_start(struct pt_regs *ctx) { 61*387f9dfdSAndroid Build Coastguard Worker u32 tid = bpf_get_current_pid_tgid(); 62*387f9dfdSAndroid Build Coastguard Worker struct start_t start = {}; 63*387f9dfdSAndroid Build Coastguard Worker start.ts = bpf_ktime_get_ns(); 64*387f9dfdSAndroid Build Coastguard Worker bpf_usdt_readarg(1, ctx, &start.query); 65*387f9dfdSAndroid Build Coastguard Worker start_tmp.update(&tid, &start); 66*387f9dfdSAndroid Build Coastguard Worker return 0; 67*387f9dfdSAndroid Build Coastguard Worker}; 68*387f9dfdSAndroid Build Coastguard Worker 69*387f9dfdSAndroid Build Coastguard Workerint do_done(struct pt_regs *ctx) { 70*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 71*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 72*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 73*387f9dfdSAndroid Build Coastguard Worker struct start_t *sp; 74*387f9dfdSAndroid Build Coastguard Worker 75*387f9dfdSAndroid Build Coastguard Worker sp = start_tmp.lookup(&tid); 76*387f9dfdSAndroid Build Coastguard Worker if (sp == 0) { 77*387f9dfdSAndroid Build Coastguard Worker // missed tracing start 78*387f9dfdSAndroid Build Coastguard Worker return 0; 79*387f9dfdSAndroid Build Coastguard Worker } 80*387f9dfdSAndroid Build Coastguard Worker 81*387f9dfdSAndroid Build Coastguard Worker // check if query exceeded our threshold 82*387f9dfdSAndroid Build Coastguard Worker u64 delta = bpf_ktime_get_ns() - sp->ts; 83*387f9dfdSAndroid Build Coastguard Worker if (delta >= """ + str(min_ns) + """) { 84*387f9dfdSAndroid Build Coastguard Worker // populate and emit data struct 85*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {.pid = pid, .ts = sp->ts, .delta = delta}; 86*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(&data.query, sizeof(data.query), (void *)sp->query); 87*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 88*387f9dfdSAndroid Build Coastguard Worker } 89*387f9dfdSAndroid Build Coastguard Worker 90*387f9dfdSAndroid Build Coastguard Worker start_tmp.delete(&tid); 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker return 0; 93*387f9dfdSAndroid Build Coastguard Worker}; 94*387f9dfdSAndroid Build Coastguard Worker 95*387f9dfdSAndroid Build Coastguard Worker""" 96*387f9dfdSAndroid Build Coastguard Worker 97*387f9dfdSAndroid Build Coastguard Worker# enable USDT probe from given PID 98*387f9dfdSAndroid Build Coastguard Workeru = USDT(pid=pid) 99*387f9dfdSAndroid Build Coastguard Workeru.enable_probe(probe="query__start", fn_name="do_start") 100*387f9dfdSAndroid Build Coastguard Workeru.enable_probe(probe="query__done", fn_name="do_done") 101*387f9dfdSAndroid Build Coastguard Workerif debug: 102*387f9dfdSAndroid Build Coastguard Worker print(u.get_text()) 103*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 104*387f9dfdSAndroid Build Coastguard Worker 105*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 106*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text, usdt_contexts=[u]) 107*387f9dfdSAndroid Build Coastguard Worker 108*387f9dfdSAndroid Build Coastguard Worker# header 109*387f9dfdSAndroid Build Coastguard Workerprint("Tracing MySQL server queries for PID %d slower than %s ms..." % (pid, 110*387f9dfdSAndroid Build Coastguard Worker min_ms_text)) 111*387f9dfdSAndroid Build Coastguard Workerprint("%-14s %-7s %8s %s" % ("TIME(s)", "PID", "MS", "QUERY")) 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Worker# process event 114*387f9dfdSAndroid Build Coastguard Workerstart = 0 115*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size): 116*387f9dfdSAndroid Build Coastguard Worker global start 117*387f9dfdSAndroid Build Coastguard Worker event = b["events"].event(data) 118*387f9dfdSAndroid Build Coastguard Worker if start == 0: 119*387f9dfdSAndroid Build Coastguard Worker start = event.ts 120*387f9dfdSAndroid Build Coastguard Worker print("%-14.6f %-7d %8.3f %s" % (float(event.ts - start) / 1000000000, 121*387f9dfdSAndroid Build Coastguard Worker event.pid, float(event.delta) / 1000000, event.query)) 122*387f9dfdSAndroid Build Coastguard Worker 123*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event 124*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event, page_cnt=64) 125*387f9dfdSAndroid Build Coastguard Workerwhile 1: 126*387f9dfdSAndroid Build Coastguard Worker try: 127*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 128*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 129*387f9dfdSAndroid Build Coastguard Worker exit() 130