On redirects, we decrement the redirect counter and the total but don't decrement `observed_errors`, which means we don't inflate the sleep time.

We could push all of the logic into one function but it would be pretty complex. Here's a summary of the behavior in the class:

- after a TimeoutError:

- increment
- check exhaustion, then raise the timeouterror
- sleep

- after a HTTPException:

- increment
- check exhaustion, then raise a MaxRetryError with the url and the error as parameters.
- sleep

- after a SocketError:

- increment
- check exhaustion, then raise a ProxyError or a MaxRetryError depending on the state of self.proxy.
- sleep

- after a redirect:

- increment
(Nothing else: the top of the following recursive call has a check for exhaustion.)

after a HTTP response was received:

- increment
- check exhaustion; if exhausted, return the response
- sleep

We could push this behavior down into one function. I am concerned about the complexity of determining which error to raise, in the event of exhaustion. Also, in the last case, we don't actually raise an exception, instead increment and then pass through.