From f23550ce118fcd71bb72b0ea7e163377c9dcbd70 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Sat, 8 Jun 2024 18:39:45 -0700 Subject: [PATCH 1/6] wip --- devenv/main.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/devenv/main.py b/devenv/main.py index 32db0da5..959e433e 100644 --- a/devenv/main.py +++ b/devenv/main.py @@ -75,7 +75,24 @@ def devenv(argv: Sequence[str], config_path: str) -> ExitCode: def main() -> ExitCode: + import os import sys + + script_logfile = os.environ.get("SCRIPT") + + if not script_logfile: + import tempfile + + _, fp = tempfile.mkstemp() + # script runs the subcommand with a tty, and tees the output to a file + # available on macos + linux + # the -F is important since otherwise some output isn't flushed by the time + # we send a sentry event, as this is a reexec wrapper and not a shell script + # this way we can very easily capture all output from devenv and send it + # to sentry as an attachment if an error occurs + cmd = ("/usr/bin/script", "-qeF", fp, *sys.argv) + os.execv(cmd[0], cmd) + import sentry_sdk sentry_sdk.init( @@ -85,6 +102,12 @@ def main() -> ExitCode: enable_tracing=True, ) + with sentry_sdk.configure_scope() as scope: + scope.add_attachment(path=script_logfile) + + # the only way this is going to work is for script to exit, then send the event + # i guess i could do that in python land still, just with subprocess + return devenv(sys.argv, f"{home}/.config/sentry-devenv/config.ini") From 0428de244c1a97a87457f627501700babfd5cb91 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Sat, 8 Jun 2024 19:25:23 -0700 Subject: [PATCH 2/6] it works but leaves mroe to be desired --- devenv/main.py | 64 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/devenv/main.py b/devenv/main.py index 959e433e..90455fc0 100644 --- a/devenv/main.py +++ b/devenv/main.py @@ -2,6 +2,8 @@ import argparse import os +import subprocess +import sys from collections.abc import Sequence from devenv import bootstrap @@ -75,40 +77,60 @@ def devenv(argv: Sequence[str], config_path: str) -> ExitCode: def main() -> ExitCode: - import os - import sys - + # this is also used to see if we're the child process script_logfile = os.environ.get("SCRIPT") - if not script_logfile: - import tempfile + if script_logfile: + return devenv(sys.argv, f"{home}/.config/sentry-devenv/config.ini") + + import tempfile + + _, fp = tempfile.mkstemp() + # script (macos/linux) runs the subcommand with a tty, and tees the output to a file. + # this way we can very easily capture all output from devenv and send it + # to sentry as an attachment if an error occurs. + cmd = ("/usr/bin/script", "-qe", fp, *sys.argv) + + # the reason we're subprocessing instead of os.execv(cmd[0], cmd) + # is that script must exit (so that the complete log file is committed to disk) + # before sentry sends the event. + rc = subprocess.call(cmd) - _, fp = tempfile.mkstemp() - # script runs the subcommand with a tty, and tees the output to a file - # available on macos + linux - # the -F is important since otherwise some output isn't flushed by the time - # we send a sentry event, as this is a reexec wrapper and not a shell script - # this way we can very easily capture all output from devenv and send it - # to sentry as an attachment if an error occurs - cmd = ("/usr/bin/script", "-qeF", fp, *sys.argv) - os.execv(cmd[0], cmd) + if rc == 0: + return rc + # we're just using sentry-sdk to send the contents of an attachment + # i'd love to be able to set it up in the child and retrieve the event id + # then upload the attachment to that event id in the parent process import sentry_sdk + from sentry_sdk.scope import Scope + import getpass sentry_sdk.init( # https://sentry.sentry.io/settings/projects/sentry-dev-env/keys/ dsn="https://9bdb053cb8274ea69231834d1edeec4c@o1.ingest.sentry.io/5723503", - # enable performance monitoring - enable_tracing=True, + # disable performance monitoring + enable_tracing=False, ) - with sentry_sdk.configure_scope() as scope: - scope.add_attachment(path=script_logfile) + scope = Scope.get_current_scope() + + # would really like to be able to set filename to the python exception title + # because seeing KeyboardInterrupt vs CalledProcessError is more helpful than + # "tmp29387ldf", but see above comment on event id + scope.add_attachment(path=fp) + + client = Scope.get_client() + + user = getpass.getuser() + computer = client.options.get("server_name", "unknown") + + # events are grouped under user@computer + scope.fingerprint = [f"{user}@{computer}"] - # the only way this is going to work is for script to exit, then send the event - # i guess i could do that in python land still, just with subprocess + sentry_sdk.capture_message(f"{user}@{computer}") - return devenv(sys.argv, f"{home}/.config/sentry-devenv/config.ini") + return rc if __name__ == "__main__": From 06ee013a0d1d59efe2d30c4780530938df479c90 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Sat, 8 Jun 2024 19:50:19 -0700 Subject: [PATCH 3/6] better comment --- devenv/main.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/devenv/main.py b/devenv/main.py index 90455fc0..50775726 100644 --- a/devenv/main.py +++ b/devenv/main.py @@ -93,15 +93,17 @@ def main() -> ExitCode: # the reason we're subprocessing instead of os.execv(cmd[0], cmd) # is that script must exit (so that the complete log file is committed to disk) - # before sentry sends the event. + # before sentry sends the event... rc = subprocess.call(cmd) if rc == 0: return rc - # we're just using sentry-sdk to send the contents of an attachment - # i'd love to be able to set it up in the child and retrieve the event id - # then upload the attachment to that event id in the parent process + # i'd love to be able to send a full event in the child then + # upload the attachment to that event id in the parent, but unfortunately there's + # no easy way to add an attachment to an existing event, + # so we have to give up getting a python stacktrace, + # and can only use sentry-sdk to send an attachment. import sentry_sdk from sentry_sdk.scope import Scope import getpass @@ -117,7 +119,7 @@ def main() -> ExitCode: # would really like to be able to set filename to the python exception title # because seeing KeyboardInterrupt vs CalledProcessError is more helpful than - # "tmp29387ldf", but see above comment on event id + # "tmp29387ldf", but see above comment scope.add_attachment(path=fp) client = Scope.get_client() From a6c524bf79fd311057015f049b14fd154fbbe700 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Tue, 18 Jun 2024 10:18:58 -0700 Subject: [PATCH 4/6] new approach --- devenv/main.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/devenv/main.py b/devenv/main.py index 50775726..1f83dfad 100644 --- a/devenv/main.py +++ b/devenv/main.py @@ -91,22 +91,8 @@ def main() -> ExitCode: # to sentry as an attachment if an error occurs. cmd = ("/usr/bin/script", "-qe", fp, *sys.argv) - # the reason we're subprocessing instead of os.execv(cmd[0], cmd) - # is that script must exit (so that the complete log file is committed to disk) - # before sentry sends the event... - rc = subprocess.call(cmd) - - if rc == 0: - return rc - - # i'd love to be able to send a full event in the child then - # upload the attachment to that event id in the parent, but unfortunately there's - # no easy way to add an attachment to an existing event, - # so we have to give up getting a python stacktrace, - # and can only use sentry-sdk to send an attachment. import sentry_sdk from sentry_sdk.scope import Scope - import getpass sentry_sdk.init( # https://sentry.sentry.io/settings/projects/sentry-dev-env/keys/ @@ -116,6 +102,18 @@ def main() -> ExitCode: ) scope = Scope.get_current_scope() + parent_transaction = scope.start_transaction() + + # the reason we're subprocessing instead of os.execv(cmd[0], cmd) + # is that script must exit (so that the complete log file is committed to disk) + # before sentry sends the event... + with scope.start_span(): + rc = subprocess.call(cmd) + + if rc == 0: + return rc + + import getpass # would really like to be able to set filename to the python exception title # because seeing KeyboardInterrupt vs CalledProcessError is more helpful than @@ -130,7 +128,7 @@ def main() -> ExitCode: # events are grouped under user@computer scope.fingerprint = [f"{user}@{computer}"] - sentry_sdk.capture_message(f"{user}@{computer}") + parent_transaction.finish() return rc From 1a9e478b2d6ba1e616e53097083108f503e3ae84 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Tue, 18 Jun 2024 12:27:35 -0700 Subject: [PATCH 5/6] [skip ci] hmm --- devenv/main.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/devenv/main.py b/devenv/main.py index 1f83dfad..e22eba0b 100644 --- a/devenv/main.py +++ b/devenv/main.py @@ -102,13 +102,17 @@ def main() -> ExitCode: ) scope = Scope.get_current_scope() - parent_transaction = scope.start_transaction() + root_transaction = scope.start_transaction() # the reason we're subprocessing instead of os.execv(cmd[0], cmd) # is that script must exit (so that the complete log file is committed to disk) # before sentry sends the event... - with scope.start_span(): - rc = subprocess.call(cmd) + span = root_transaction.start_child() + rc = subprocess.call(cmd) + # breakpoint() + span.finish() + + # hmm at this point root_transaction doesn't have anything in self._span_recorder... if rc == 0: return rc @@ -128,7 +132,7 @@ def main() -> ExitCode: # events are grouped under user@computer scope.fingerprint = [f"{user}@{computer}"] - parent_transaction.finish() + root_transaction.finish() return rc From d17dfc95454988f0d849244ad36493230e1dfbd5 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Tue, 18 Jun 2024 13:04:58 -0700 Subject: [PATCH 6/6] [skip ci] wip --- devenv/main.py | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/devenv/main.py b/devenv/main.py index e22eba0b..c136ae8d 100644 --- a/devenv/main.py +++ b/devenv/main.py @@ -97,8 +97,7 @@ def main() -> ExitCode: sentry_sdk.init( # https://sentry.sentry.io/settings/projects/sentry-dev-env/keys/ dsn="https://9bdb053cb8274ea69231834d1edeec4c@o1.ingest.sentry.io/5723503", - # disable performance monitoring - enable_tracing=False, + enable_tracing=True, ) scope = Scope.get_current_scope() @@ -107,32 +106,46 @@ def main() -> ExitCode: # the reason we're subprocessing instead of os.execv(cmd[0], cmd) # is that script must exit (so that the complete log file is committed to disk) # before sentry sends the event... - span = root_transaction.start_child() - rc = subprocess.call(cmd) - # breakpoint() - span.finish() - - # hmm at this point root_transaction doesn't have anything in self._span_recorder... + with root_transaction.start_child(): + rc = subprocess.call(cmd) if rc == 0: return rc - import getpass + #import getpass # would really like to be able to set filename to the python exception title # because seeing KeyboardInterrupt vs CalledProcessError is more helpful than # "tmp29387ldf", but see above comment - scope.add_attachment(path=fp) + #scope.add_attachment(path=fp) + #print(fp) - client = Scope.get_client() +# client = Scope.get_client() - user = getpass.getuser() - computer = client.options.get("server_name", "unknown") + #user = getpass.getuser() +# computer = client.options.get("server_name", "unknown") # events are grouped under user@computer - scope.fingerprint = [f"{user}@{computer}"] + #scope.fingerprint = [f"{user}@test"] + + breakpoint() + event_id = root_transaction.finish() + + # trace + # https://sentry.sentry.io/performance/trace/d86e9d23141f41e2b335fc219e82d3e0 + + # event id feb696d0c83a44a1a73c69f31f10635e + # cant find this anywhere though + # this page doesnt load + # https://sentry.sentry.io/issues/5504551756/events/feb696d0c83a44a1a73c69f31f10635e/?project=5723503 + + # https://sentry.sentry.io/traces/?project=5723503&query=project%3Asentry-dev-env&statsPeriod=24h + # trace overview + + # so i dont think an issue is being created, despite an event being created - root_transaction.finish() + print("trace id: ", root_transaction.trace_id) + print(event_id) return rc