mongo/buildscripts/tracing_profiler/profile_mongod.py

125 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import json
import signal
import subprocess
import sys
from threading import Event
from profilerlib import CallMetrics
def get_profiler_stats(args):
command = [
"mongosh",
"--quiet",
"--eval",
"print(EJSON.stringify(db.runCommand({serverStatus: 1}).tracing_profiler))",
]
if args.username:
command.extend(["--username", args.username])
if args.password:
command.extend(["--password", args.password])
if args.host:
command.extend(["--host", args.host])
if args.port:
command.extend(["--port", args.port])
if args.tls:
command.append("--tls")
if args.tlsAllowInvalidCertificates:
command.append("--tlsAllowInvalidCertificates")
if args.tlsAllowInvalidHostnames:
command.append("--tlsAllowInvalidHostnames")
r = subprocess.check_output(command)
return json.loads(r)
def get_call_metrics(args):
return CallMetrics.from_json(get_profiler_stats(args))
def main():
stop_event = Event()
signal.signal(signal.SIGINT, lambda *_: stop_event.set())
parser = argparse.ArgumentParser(
usage="usage: %(prog)s [options]",
description="Collects a profiler data from mongod",
formatter_class=argparse.RawTextHelpFormatter,
epilog="Press CTRL-C to stop profiling",
)
parser.add_argument(
"-s",
"--sleep",
dest="sleep",
type=int,
help="profiles for given number of seconds, or indefinitely if not",
)
# The following are args that get passed through to mongosh
# See https://github.com/mongodb-js/mongosh?tab=readme-ov-file#cli-usage
parser.add_argument(
"-u",
"--username",
dest="username",
help="Username for authentication",
)
parser.add_argument(
"-p",
"--password",
dest="password",
help="Password for authentication",
)
parser.add_argument(
"--host",
dest="host",
help="Server to connect to",
)
parser.add_argument(
"--port",
dest="port",
help="Port to connect to",
)
parser.add_argument(
"--tls", dest="tls", action="store_true", help="Use TLS for all connections"
)
parser.add_argument(
"--tlsAllowInvalidCertificates",
dest="tlsAllowInvalidCertificates",
action="store_true",
help="Allow connections to servers with invalid certificates",
)
parser.add_argument(
"--tlsAllowInvalidHostnames",
dest="tlsAllowInvalidHostnames",
action="store_true",
help="Allow connections to servers with non-matching hostnames",
)
args = parser.parse_args()
before_metrics = get_call_metrics(args)
sleep_sec = None
if args.sleep is not None:
sleep_sec = args.sleep
if sleep_sec is None:
print("Profiling indefinitely until interrupted...", file=sys.stderr)
else:
print(f"Profiling for {sleep_sec} seconds...", file=sys.stderr)
print("Press CTRL-C to stop profiling", file=sys.stderr)
stop_event.wait(sleep_sec)
after_metrics = get_call_metrics(args)
after_metrics.subtract(before_metrics)
print(after_metrics.to_json())
if __name__ == "__main__":
main()