xref: /aosp_15_r20/external/bcc/tools/dbstat.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# dbstat        Display a histogram of MySQL and PostgreSQL query latencies.
4*387f9dfdSAndroid Build Coastguard Worker#
5*387f9dfdSAndroid Build Coastguard Worker# USAGE: dbstat [-v] [-p PID [PID ...]] [-m THRESHOLD] [-u]
6*387f9dfdSAndroid Build Coastguard Worker#               [-i INTERVAL] {mysql,postgres}
7*387f9dfdSAndroid Build Coastguard Worker#
8*387f9dfdSAndroid Build Coastguard Worker# This tool uses USDT probes, which means it needs MySQL and PostgreSQL built
9*387f9dfdSAndroid Build Coastguard Worker# with USDT (DTrace) support.
10*387f9dfdSAndroid Build Coastguard Worker#
11*387f9dfdSAndroid Build Coastguard Worker# Copyright 2017, Sasha Goldshtein
12*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0
13*387f9dfdSAndroid Build Coastguard Worker#
14*387f9dfdSAndroid Build Coastguard Worker# 15-Feb-2017   Sasha Goldshtein   Created this.
15*387f9dfdSAndroid Build Coastguard Worker
16*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT
17*387f9dfdSAndroid Build Coastguard Workerimport argparse
18*387f9dfdSAndroid Build Coastguard Workerimport subprocess
19*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Workerexamples = """
22*387f9dfdSAndroid Build Coastguard Worker    dbstat postgres     # display a histogram of PostgreSQL query latencies
23*387f9dfdSAndroid Build Coastguard Worker    dbstat mysql -v     # display MySQL latencies and print the BPF program
24*387f9dfdSAndroid Build Coastguard Worker    dbstat mysql -u     # display query latencies in microseconds (default: ms)
25*387f9dfdSAndroid Build Coastguard Worker    dbstat mysql -m 5   # trace only queries slower than 5ms
26*387f9dfdSAndroid Build Coastguard Worker    dbstat mysql -p 408 # trace queries in a specific process
27*387f9dfdSAndroid Build Coastguard Worker"""
28*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
29*387f9dfdSAndroid Build Coastguard Worker    description="",
30*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
31*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
32*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-v", "--verbose", action="store_true",
33*387f9dfdSAndroid Build Coastguard Worker    help="print the BPF program")
34*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("db", choices=["mysql", "postgres"],
35*387f9dfdSAndroid Build Coastguard Worker    help="the database engine to use")
36*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", type=int, nargs='*',
37*387f9dfdSAndroid Build Coastguard Worker    dest="pids", metavar="PID", help="the pid(s) to trace")
38*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-m", "--threshold", type=int, default=0,
39*387f9dfdSAndroid Build Coastguard Worker    help="trace queries slower than this threshold (ms)")
40*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-u", "--microseconds", action="store_true",
41*387f9dfdSAndroid Build Coastguard Worker    help="display query latencies in microseconds (default: milliseconds)")
42*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-i", "--interval", type=int, default=99999999,
43*387f9dfdSAndroid Build Coastguard Worker    help="print summary at this interval (seconds)")
44*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
45*387f9dfdSAndroid Build Coastguard Worker
46*387f9dfdSAndroid Build Coastguard Workerif not args.pids or len(args.pids) == 0:
47*387f9dfdSAndroid Build Coastguard Worker    if args.db == "mysql":
48*387f9dfdSAndroid Build Coastguard Worker        args.pids = map(int, subprocess.check_output(
49*387f9dfdSAndroid Build Coastguard Worker                                        "pidof mysqld".split()).split())
50*387f9dfdSAndroid Build Coastguard Worker    elif args.db == "postgres":
51*387f9dfdSAndroid Build Coastguard Worker        args.pids = map(int, subprocess.check_output(
52*387f9dfdSAndroid Build Coastguard Worker                                        "pidof postgres".split()).split())
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Workerprogram = """
55*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(temp, u64, u64);
58*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(latency);
59*387f9dfdSAndroid Build Coastguard Worker
60*387f9dfdSAndroid Build Coastguard Workerint probe_start(struct pt_regs *ctx) {
61*387f9dfdSAndroid Build Coastguard Worker    u64 timestamp = bpf_ktime_get_ns();
62*387f9dfdSAndroid Build Coastguard Worker    u64 pid = bpf_get_current_pid_tgid();
63*387f9dfdSAndroid Build Coastguard Worker    temp.update(&pid, &timestamp);
64*387f9dfdSAndroid Build Coastguard Worker    return 0;
65*387f9dfdSAndroid Build Coastguard Worker}
66*387f9dfdSAndroid Build Coastguard Worker
67*387f9dfdSAndroid Build Coastguard Workerint probe_end(struct pt_regs *ctx) {
68*387f9dfdSAndroid Build Coastguard Worker    u64 *timestampp;
69*387f9dfdSAndroid Build Coastguard Worker    u64 pid = bpf_get_current_pid_tgid();
70*387f9dfdSAndroid Build Coastguard Worker    timestampp = temp.lookup(&pid);
71*387f9dfdSAndroid Build Coastguard Worker    if (!timestampp)
72*387f9dfdSAndroid Build Coastguard Worker        return 0;
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Worker    u64 delta = bpf_ktime_get_ns() - *timestampp;
75*387f9dfdSAndroid Build Coastguard Worker    FILTER
76*387f9dfdSAndroid Build Coastguard Worker    delta /= SCALE;
77*387f9dfdSAndroid Build Coastguard Worker    latency.atomic_increment(bpf_log2l(delta));
78*387f9dfdSAndroid Build Coastguard Worker    temp.delete(&pid);
79*387f9dfdSAndroid Build Coastguard Worker    return 0;
80*387f9dfdSAndroid Build Coastguard Worker}
81*387f9dfdSAndroid Build Coastguard Worker"""
82*387f9dfdSAndroid Build Coastguard Workerprogram = program.replace("SCALE", str(1000 if args.microseconds else 1000000))
83*387f9dfdSAndroid Build Coastguard Workerprogram = program.replace("FILTER", "" if args.threshold == 0 else
84*387f9dfdSAndroid Build Coastguard Worker        "if (delta / 1000000 < %d) { return 0; }" % args.threshold)
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Workerusdts = list(map(lambda pid: USDT(pid=pid), args.pids))
87*387f9dfdSAndroid Build Coastguard Workerfor usdt in usdts:
88*387f9dfdSAndroid Build Coastguard Worker    usdt.enable_probe("query__start", "probe_start")
89*387f9dfdSAndroid Build Coastguard Worker    usdt.enable_probe("query__done", "probe_end")
90*387f9dfdSAndroid Build Coastguard Worker
91*387f9dfdSAndroid Build Coastguard Workerif args.verbose:
92*387f9dfdSAndroid Build Coastguard Worker    print('\n'.join(map(lambda u: u.get_text(), usdts)))
93*387f9dfdSAndroid Build Coastguard Worker    print(program)
94*387f9dfdSAndroid Build Coastguard Worker
95*387f9dfdSAndroid Build Coastguard Workerbpf = BPF(text=program, usdt_contexts=usdts)
96*387f9dfdSAndroid Build Coastguard Worker
97*387f9dfdSAndroid Build Coastguard Workerprint("Tracing database queries for pids %s slower than %d ms..." %
98*387f9dfdSAndroid Build Coastguard Worker      (', '.join(map(str, args.pids)), args.threshold))
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Workerlatencies = bpf["latency"]
101*387f9dfdSAndroid Build Coastguard Worker
102*387f9dfdSAndroid Build Coastguard Workerdef print_hist():
103*387f9dfdSAndroid Build Coastguard Worker    print("[%s]" % strftime("%H:%M:%S"))
104*387f9dfdSAndroid Build Coastguard Worker    latencies.print_log2_hist("query latency (%s)" %
105*387f9dfdSAndroid Build Coastguard Worker                              ("us" if args.microseconds else "ms"))
106*387f9dfdSAndroid Build Coastguard Worker    print("")
107*387f9dfdSAndroid Build Coastguard Worker    latencies.clear()
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard Workerwhile True:
110*387f9dfdSAndroid Build Coastguard Worker    try:
111*387f9dfdSAndroid Build Coastguard Worker        sleep(args.interval)
112*387f9dfdSAndroid Build Coastguard Worker        print_hist()
113*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
114*387f9dfdSAndroid Build Coastguard Worker        print_hist()
115*387f9dfdSAndroid Build Coastguard Worker        break
116