getsentry / sentry-python

The official Python SDK for Sentry.io

Home Page:https://sentry.io/for/python/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Alternative initialization methods for CLI tools

n1ngu opened this issue · comments

Rationale

Unlike WSGI applications, CLI tools usually offer no mechanism to be consistently monkeypatched, thus hampering any call to sentrysdk.init(). If the tool configuration was a python file or the shell script was fully wrapped in an importable main function, one could still hack a way to initialize sentry. But this is not always a possibility.

Still, tools can usually be told to use a particular file configuration for the standard logging system.

Proposal

I'd love that sentry provided a mechanism to initialize itself on this kind of tooling, specially for scripts that are meant to be run as daemons in some frameworks.

This as a follow-up for a naive implementation that was proposed as part of the Tryton Server Framework Sentry integration #548

The implementation can be reduced to

class SentryInitHandler(logging.NullHandler):
    def __init__(self, dsn):
        super(SentryInitHandler, self).__init__()
        sentry_sdk.init(dsn)

There is no need to inherit sentry_sdk.integrations.logging.EventHandler because sentry_sdk.init will already install the default sentry_sdk.integrations.logging.LoggingIntegration that will already patch any logger.error call. Then, to use it, this handler must be configured once in an arbitrary logger

[loggers]
keys = root

[handlers]
keys = console, sentry

[formatters]
keys =

[logger_root]
level = INFO
handlers = console, sentry

[handler_console]
class = StreamHandler
args = (sys.stdout,)

[handler_sentry]
class=sentry_sdk.integrations.?????.SentryInitHandler
args = ( 'https://key@sentry.io/project')

As can be seen in the former PR discussion and this commit discussion,
@untitaker was legitimately concerned about this implementation being tailored for a simplistic usage of the SentrySDK.

Accepting this implementation as-is would be controversial since it would be arbitrarily unusable for advanced sentry configurations, so this issue is opened in the hope that this idea can be improved and merged into this repo.

Edit: link to former discussion

Alternatively, this could be addressed with a sentry-sdk CLI that wrapped other CLI tooling, like

sentry-init --dsn=https://example.com --whatnot -- my-tool

but I believe this path is much harder. For executable python modules (__main__.py) this could be addressed safely, but again this is not always a possibility.

There is no need to inherit sentry_sdk.integrations.logging.EventHandler because sentry_sdk.init will already install the default sentry_sdk.integrations.logging.LoggingIntegration that will already patch any logger.error call.

I believe the integration should generally function regardless of whether other integrations are enabled. There's no real harm in reporting errors twice, the core SDK will deduplicate them based on object ID if they are reported consecutively from within the same thread.

I believe the integration should generally function regardless of whether other integrations are enabled.

I have updated the link to our former discussion, github was cutting it to a silent commit. The point is: this is NOT an integration. Maybe the problem is depicting this handler in the integrations submodule.

The purpose of this handler is not capturing logging events. The purpose is to abuse the logging system to inject a sentry_sdk.init call in CLI tools that refuse to be monkeypatched!

It should be orthogonal to the existing sentry_sdk.integrations.logging usage, whether it is the default logging integration or a carefully crafted EventHandler & BreadcrumbHandler tree.

For example: if someone needs this initialization method but also wants not to capture any log events into sentry, this is only possible if this handler inherits logging.NullHandler and not sentry's EventHandler! Then, if someone did want to capture logging events... they could simply rely on the default LoggingIntegration or work out their Breadcrumb/EventHandler config.

I think the real challenge is how to unleash the full sentry configurability with this kind of approach. One solution could be to simply forward any arbitrary args and kwargs from the logging configuration into the sentry_sdk.init call like

class SentryInitHandler(logging.NullHandler):
    def __init__(self, *args, **kwargs):
        super(SentryInitHandler, self).__init__()
        sentry_sdk.init(*args, **kwargs)

and then use it with

[handler_initsentry]
class=sentry_sdk.?????.SentryInitHandler
args = ('https://examplePublicKey@o0.ingest.sentry.io/0' , )
kwargs = {
 'max_breadcrumbs': 50,
 'debug': False,
 'default_integrations': True,
 'with_locals': False,
 'whatnot': None}

which would already leverage all "primitive" parametrization of the sdk. Yet, options requiring references to functions or classes like integrations and hooks would still be limited, since the eval context of the logging fileConfig is also limited (thankfully).

Would this be an acceptable trade-off? Otherwise this could be addressed if sentry_sdk.init accepted full import paths for functions and classes for those options? But this would better be another discussion.

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

Hello @n1ngu
Thanks for the proposal and sorry for the late reply.
This sounds interesting and I think it could be useful for a lot of python scripts out there.
I have not yet had time to really wrap my head around using the logging infrastructure to sneak in a sdk init. From the gut feeling it is a little bit hackish, but maybe its a brilliant idea and just need some quiet time to think it through.

Anyways. Could you create sort of an very minimal proof of concept project that we could use for further discussions? This would be great!

Hi @antonpirker

See the example proof of concept in this minirepo https://github.com/n1ngu/sentry-init-handler

Indeed, hackish is the word. It is working and is stable in my setup, but shipping it within sentry_sdk... I think a big challenge would be documenting this so that no one confuses it with the other useful logging handlers that sentry_sdk already provides, and also so that target users that could benefit from it would easily find the documentation while keeping away all the other use cases that should NOT use such technique.

Thanks for the minirepo @n1ngu! Amazing!
Basically this would be something like a CLI integration. (no code changes needed)

I have now put this on the internal backlog at low priority. (So please be patient, we have always a lot on our plates)

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀