Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Global Error Handler #1080

Merged
merged 34 commits into from
Sep 30, 2020
Merged

Add Global Error Handler #1080

merged 34 commits into from
Sep 30, 2020

Conversation

ocelotl
Copy link
Contributor

@ocelotl ocelotl commented Sep 8, 2020

Description

Add a global error handler. This object allows users to pass exceptions to pre-registered error handlers.

Fixes #1079

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Added unit tests.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

@ocelotl ocelotl requested a review from a team as a code owner September 8, 2020 00:42
@ocelotl ocelotl self-assigned this Sep 8, 2020
@lzchen lzchen added release:required-for-ga To be resolved before GA release sdk Affects the SDK package. labels Sep 10, 2020
@ffe4
Copy link
Contributor

ffe4 commented Sep 10, 2020

After taking a closer look, I think the examples I had in mind during the SIG can probably all be solved by either directly raising or re-raising the exception somewhere. E.g.:

try:
    do_stuff(arg)
except InvalidArg:
    with GlobalErrorHandler():
        raise InvalidArg
    do_something_else()

However, maybe having a .raise(Error) method on the handler would be more intuitive?

@codeboten codeboten added this to In Progress in GA Burndown Sep 14, 2020
@ocelotl
Copy link
Contributor Author

ocelotl commented Sep 14, 2020

After taking a closer look, I think the examples I had in mind during the SIG can probably all be solved by either directly raising or re-raising the exception somewhere. E.g.:

try:
    do_stuff(arg)
except InvalidArg:
    with GlobalErrorHandler():
        raise InvalidArg
    do_something_else()

However, maybe having a .raise(Error) method on the handler would be more intuitive?

🤔 What is the purpose of do_something_else? Can that code be added to the handler for InvalidArg?

@ffe4
Copy link
Contributor

ffe4 commented Sep 14, 2020

🤔 What is the purpose of do_something_else? Can that code be added to the handler for InvalidArg?

do_something_else() is supposed to be error handling done by the SDK, so we want the error to be handled by the default handler. Let's just say do_stuff() had a return value that we wanted and now we have to get it another way.

As a general question, since I am not quite sure what the intention behind the spec was, could you maybe share your understanding of what kinds of errors a user should be able to register handlers for? The spec only mentions relevant errors, so I'm not quite sure where we would make use of these error handlers in the first place.

@ocelotl
Copy link
Contributor Author

ocelotl commented Sep 14, 2020

thinking What is the purpose of do_something_else? Can that code be added to the handler for InvalidArg?

do_something_else() is supposed to be error handling done by the SDK, so we want the error to be handled by the default handler. Let's just say do_stuff() had a return value that we wanted and now we have to get it another way.

Just for the record, here is more context related to relevant errors. I can think about a way of getting the return value of error handlers using the context manager, let me write something down...

@ffe4
Copy link
Contributor

ffe4 commented Sep 15, 2020

I can think about a way of getting the return value of error handlers using the context manager, let me write something down...

The example is supposed to be SDK internal. If we put all error handling code for relevant internal errors into error handlers, our code will become more fragmented. IMO the above example is better than one where we have to jump to another class to see what happens if we encounter an error. I also don't know if we want to give users the ability, or the obligation, to supply return values that get used in case of an error. At least the spec only talks about enabling strict error handling, so I think we should keep it simple.

@ocelotl
Copy link
Contributor Author

ocelotl commented Sep 15, 2020

I can think about a way of getting the return value of error handlers using the context manager, let me write something down...

The example is supposed to be SDK internal. If we put all error handling code for relevant internal errors into error handlers, our code will become more fragmented. IMO the above example is better than one where we have to jump to another class to see what happens if we encounter an error. I also don't know if we want to give users the ability, or the obligation, to supply return values that get used in case of an error. At least the spec only talks about enabling strict error handling, so I think we should keep it simple.

I can think about a way of getting the return value of error handlers using the context manager, let me write something down...

The example is supposed to be SDK internal. If we put all error handling code for relevant internal errors into error handlers, our code will become more fragmented. IMO the above example is better than one where we have to jump to another class to see what happens if we encounter an error. I also don't know if we want to give users the ability, or the obligation, to supply return values that get used in case of an error. At least the spec only talks about enabling strict error handling, so I think we should keep it simple.

The spec requires to be possible for users to register their own error handlers, that's basically what is being implemented here. I agree that giving the users the return value of an error handler is outside of the scope of the requirement and probably self defeating also, since it would require the application code to act on the registered handlers themselves, breaking the separation between application code and error handlers. Because of this, I have removed the return of any value in the error handlers.

Copy link
Contributor

@codeboten codeboten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested this by walking through the doc, this looks great, just a few minor updates requested.

scripts/check_for_valid_readme.py Outdated Show resolved Hide resolved
scripts/check_for_valid_readme.py Outdated Show resolved Hide resolved
docs/examples/error_hander/error_handler_1/setup.cfg Outdated Show resolved Hide resolved
docs/examples/error_hander/error_handler_1/setup.cfg Outdated Show resolved Hide resolved
docs/examples/error_hander/error_handler_0/setup.cfg Outdated Show resolved Hide resolved
docs/examples/error_hander/error_handler_0/setup.cfg Outdated Show resolved Hide resolved
docs/examples/error_hander/error_handler_0/setup.cfg Outdated Show resolved Hide resolved
docs/examples/error_hander/error_handler_0/setup.cfg Outdated Show resolved Hide resolved
docs/examples/error_hander/README.rst Outdated Show resolved Hide resolved
ocelotl and others added 12 commits September 25, 2020 15:13
Co-authored-by: alrex <aboten@lightstep.com>
…/version.py

Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
Co-authored-by: alrex <aboten@lightstep.com>
…/version.py

Co-authored-by: alrex <aboten@lightstep.com>
Copy link
Contributor

@codeboten codeboten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for including my suggestions, this looks good to me.


In order for the error handlers to be registered, they need to create a class
that inherits from ``opentelemetry.sdk.error_handler.ErrorHandler`` and at
least one ``Exception``-type class. For example, this is an error handler that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for needing to inherit from an Exception type class? Is there a necessity that the behaviour of handle must rely on the type of the exception?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please read comment below.

"opentelemetry_error_handler"
):

error_handler_class = error_handler_entry_point.load()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I can see anything that enforces a specific handler to handle only certain types of errors (inheriting for an Error doesn't really enforce this). With that being said, this logic will run through all the handlers regardless of what kind of errors they are handling. Does this make sense if there are multiple handlers handling the same type of error already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine most implementations of the handlers having to deal with checking the exception type if this is not implemented somewhere else. It seems natural to me that handlers are made for specific exceptions, and they will not be interested in any other exception types, so I preferred to put this check in the global error handler. I am open to other design ideas, this is not something I consider definitive for this particular feature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine then. I think we can leave it up to the user's discretion to check exception type and handle them appropriately (if they have multiple handlers executing on the same error type then that is up to them). Is the order of execution of the handlers known somehow? Or does that depend on which iter point is loaded first?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would depend on the iter_points order. So, you prefer that the global error handler does not check exception type and all error handlers are called?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current implementation is fine.

@lzchen
Copy link
Contributor

lzchen commented Sep 29, 2020

Just curious, are we going to wrap our entire sdk in an global error handler context to catch unhandled exceptions?

@ocelotl
Copy link
Contributor Author

ocelotl commented Sep 29, 2020

Just curious, are we going to wrap our entire sdk in an global error handler context to catch unhandled exceptions?

I was not thinking about that when I was writing this error handler, I am also not sure how "doable" that is (I mean, how certainly can we guarantee that we can catch any SDK-related exception).

@lzchen
Copy link
Contributor

lzchen commented Sep 30, 2020

@ocelotl
Have a handler that just wraps the code in a giant try/catch and catch for generic exception. I'm just thinking of ideas, might not be feasible.

GA Burndown automation moved this from In Progress to Reviewer Approved Sep 30, 2020
@lzchen lzchen merged commit c68ce46 into open-telemetry:master Sep 30, 2020
GA Burndown automation moved this from Reviewer Approved to Done Sep 30, 2020
srikanthccv pushed a commit to srikanthccv/opentelemetry-python that referenced this pull request Nov 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release:required-for-ga To be resolved before GA release sdk Affects the SDK package.
Projects
No open projects
GA Burndown
  
Done
Development

Successfully merging this pull request may close these issues.

Add global error handler to the SDK
4 participants