initial code repo
[stor4nfv.git] / src / ceph / src / tools / histogram_dump.py
diff --git a/src/ceph/src/tools/histogram_dump.py b/src/ceph/src/tools/histogram_dump.py
new file mode 100755 (executable)
index 0000000..bafc24b
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+# coding: utf-8
+#
+# Ceph - scalable distributed file system
+#
+# Copyright (C) 2017 OVH
+#
+# This is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public
+# License version 2, as published by the Free Software
+# Foundation.  See file COPYING.
+#
+
+import json
+import subprocess
+import time
+import os
+import argparse
+
+
+def shorten(val):
+    if isinstance(val, str):
+        return val
+    for u in ((3, ''), (6, 'k'), (9, 'M'), (12, 'G'), (15, 'T')):
+        if val < 10**u[0]:
+            return "{}{}".format(int(val / (10 ** (u[0]-3))), u[1])
+    return val
+
+
+def print_histogram(asok, logger, counter, last):
+
+    try:
+        out = subprocess.check_output(
+            "ceph --admin-daemon {} perf histogram dump".format(asok),
+            shell=True)
+        j = json.loads(out.decode('utf-8'))
+    except Exception as e:
+        return (last,
+                "Couldn't connect to admin socket, result: \n{}".format(e))
+
+    current = j['osd'][counter]['values']
+    axes = j['osd'][counter]['axes']
+    content = ""
+
+    content += "{}:\n".format(axes[1]['name'])
+    for r in axes[1]['ranges']:
+        content += "{0: >4} ".format(
+            shorten(r['min']) if 'min' in r else '')
+    content += "\n"
+    for r in axes[1]['ranges']:
+        content += "{0: >4} ".format(
+            shorten(r['max']) if 'max' in r else '')
+    content += "\n"
+
+    content += ("{0: >"+str(len(axes[1]['ranges'])*5+14)+"}:\n").format(
+        axes[0]['name'])
+
+    for i in range(len(current)):
+        for j in range(len(current[i])):
+            try:
+                diff = current[i][j] - last[i][j]
+            except IndexError:
+                diff = '-'
+            content += "{0: >4} ".format(shorten(diff))
+
+        r = axes[0]['ranges'][i]
+        content += "{0: >6} : {1}\n".format(
+            shorten(r['min']) if 'min' in r else '',
+            shorten(r['max']) if 'max' in r else '')
+    return (current, content)
+
+
+def loop_print(asok, logger, counter):
+    last = []
+    while True:
+
+        last, content = print_histogram(asok, logger, counter, last)
+        print("{}{}".format("\n"*100, content))
+        time.sleep(1)
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description='Continuously display ceph performance histogram')
+    parser.add_argument(
+        '--asok',
+        type=str,
+        default='/var/run/ceph/*.asok',
+        help='Path to asok file, can use wildcards')
+    parser.add_argument(
+        '--logger',
+        type=str,
+        default='osd')
+    parser.add_argument(
+        '--counter',
+        type=str,
+        default='op_w_latency_in_bytes_histogram')
+    args = parser.parse_args()
+
+    loop_print(args.asok, args.logger, args.counter)
+
+
+if __name__ == '__main__':
+    main()