]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #!/usr/bin/env python |
2 | # coding: utf-8 | |
3 | # | |
4 | # Ceph - scalable distributed file system | |
5 | # | |
6 | # Copyright (C) 2017 OVH | |
7 | # | |
8 | # This is free software; you can redistribute it and/or | |
9 | # modify it under the terms of the GNU General Public | |
10 | # License version 2, as published by the Free Software | |
11 | # Foundation. See file COPYING. | |
12 | # | |
13 | ||
14 | import json | |
15 | import subprocess | |
16 | import time | |
17 | import os | |
18 | import argparse | |
19 | ||
20 | ||
21 | def shorten(val): | |
22 | if isinstance(val, str): | |
23 | return val | |
24 | for u in ((3, ''), (6, 'k'), (9, 'M'), (12, 'G'), (15, 'T')): | |
25 | if val < 10**u[0]: | |
26 | return "{}{}".format(int(val / (10 ** (u[0]-3))), u[1]) | |
27 | return val | |
28 | ||
29 | ||
30 | def print_histogram(asok, logger, counter, last): | |
31 | ||
32 | try: | |
33 | out = subprocess.check_output( | |
34 | "ceph --admin-daemon {} perf histogram dump".format(asok), | |
35 | shell=True) | |
36 | j = json.loads(out.decode('utf-8')) | |
37 | except Exception as e: | |
38 | return (last, | |
39 | "Couldn't connect to admin socket, result: \n{}".format(e)) | |
40 | ||
41 | current = j['osd'][counter]['values'] | |
42 | axes = j['osd'][counter]['axes'] | |
43 | content = "" | |
44 | ||
45 | content += "{}:\n".format(axes[1]['name']) | |
46 | for r in axes[1]['ranges']: | |
47 | content += "{0: >4} ".format( | |
48 | shorten(r['min']) if 'min' in r else '') | |
49 | content += "\n" | |
50 | for r in axes[1]['ranges']: | |
51 | content += "{0: >4} ".format( | |
52 | shorten(r['max']) if 'max' in r else '') | |
53 | content += "\n" | |
54 | ||
55 | content += ("{0: >"+str(len(axes[1]['ranges'])*5+14)+"}:\n").format( | |
56 | axes[0]['name']) | |
57 | ||
58 | for i in range(len(current)): | |
59 | for j in range(len(current[i])): | |
60 | try: | |
61 | diff = current[i][j] - last[i][j] | |
62 | except IndexError: | |
63 | diff = '-' | |
64 | content += "{0: >4} ".format(shorten(diff)) | |
65 | ||
66 | r = axes[0]['ranges'][i] | |
67 | content += "{0: >6} : {1}\n".format( | |
68 | shorten(r['min']) if 'min' in r else '', | |
69 | shorten(r['max']) if 'max' in r else '') | |
70 | return (current, content) | |
71 | ||
72 | ||
73 | def loop_print(asok, logger, counter): | |
74 | last = [] | |
75 | while True: | |
76 | ||
77 | last, content = print_histogram(asok, logger, counter, last) | |
78 | print("{}{}".format("\n"*100, content)) | |
79 | time.sleep(1) | |
80 | ||
81 | ||
82 | def main(): | |
83 | parser = argparse.ArgumentParser( | |
84 | description='Continuously display ceph performance histogram') | |
85 | parser.add_argument( | |
86 | '--asok', | |
87 | type=str, | |
88 | default='/var/run/ceph/*.asok', | |
89 | help='Path to asok file, can use wildcards') | |
90 | parser.add_argument( | |
91 | '--logger', | |
92 | type=str, | |
93 | default='osd') | |
94 | parser.add_argument( | |
95 | '--counter', | |
96 | type=str, | |
97 | default='op_w_latency_in_bytes_histogram') | |
98 | args = parser.parse_args() | |
99 | ||
100 | loop_print(args.asok, args.logger, args.counter) | |
101 | ||
102 | ||
103 | if __name__ == '__main__': | |
104 | main() |