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

Improve circuit error messages #176

Merged
merged 6 commits into from
Jan 19, 2022
Merged

Conversation

julik
Copy link
Contributor

@julik julik commented Aug 2, 2021

When these happen it is useful to at least know which service has raised the error. This can be ever more relevant if a circuit breaker is initialised dynamically - for example, per host getting called.

@ghost
Copy link

ghost commented Aug 2, 2021

CLA assistant check
All CLA requirements met.

@@ -5,16 +5,16 @@ class ServiceFailureError < Circuitbox::Error
attr_reader :service, :original

def initialize(service, exception)
super()
super("Service #{service.inspect} was unavailable: #{exception}")
Copy link
Collaborator

Choose a reason for hiding this comment

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

This exception class overrides the to_s method which means this message would never be used/returned.

This can be validated with the following code snippet

class BaseError < StandardError; end

class CustomError < BaseError
  def initialize
    super("message from initialize")
  end

  def to_s
    "message from to_s"
  end
end

begin
  raise CustomError
rescue CustomError => e
  puts e.message
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, I'll adjust the to_s instead

@@ -5,7 +5,7 @@ class OpenCircuitError < Circuitbox::Error
attr_reader :service

def initialize(service)
super()
super("Service #{service.inspect} has an open circuit")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since the service is converted into a string in CircuitBreaker is there a specific reason inspect is being called?

I think it makes sense to have some standard exception message for this error. Previously one would need to rescue the exception, read the value of service, and construct their own message. This gets rid of the need to do that but with the downside of always allocating the message regardless of it being read. The message should be lazily created by overriding the to_s method like what ServiceFailureError does.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

inspect is to make the substituted value separate from the surrounding text for readability. Imagine you are using local hostnames for your services, for example you have a machine called gollum and you can reach it with its' bare hostname. If you template the name into a message "as is" it can be confusing because your message will look like Service gollum has an open circuit. If the service name consists of multiple words separated by spaces the value visually dissolves in the rest of the message. Since there are no strictly defined semantics for quoting / Markdown in exception messages I opt for the next best thing and use inspect for this "auto-quote". I think in some other instances a combo of backtick+single quote is used too in some Ruby builtin messages, we can also uses that?

Copy link
Collaborator

@matthewshafer matthewshafer left a comment

Choose a reason for hiding this comment

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

After the test is fixed up to match the new exception message this change should be okay to merge.

That being said I'll probably change the wording of the exception messages to be more like our other logging messages in a future PR.

@@ -13,7 +13,7 @@ def setup

def test_includes_the_message_of_the_wrapped_exception
ex = Circuitbox::ServiceFailureError.new('test', error)
assert_equal "Circuitbox::ServiceFailureError wrapped: #{error}", ex.to_s
assert_equal "Circuitbox::ServiceFailureError (original: #{error})", ex.to_s
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test needs to be updated to handle the new response.

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'll take care of it, thanks!

@mashafer mashafer merged commit b8a89ff into yammer:main Jan 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants