This first cut is limited to only a couple of use-cases, which is quite ok. But trying to think ahead, what would we want a tracking API to look like that has full coverage of the request lifecycle? Here's my proposal:

tracker.track()
  ..before((req) {...})  // called before the request is received by the request handler
  ..during((req) {...})  // called after the request is sent to the handler but before it is served with success or error
  ..afterResponse((req, resp) {...})  // called after a response has been received but not yet processed by client listener
  ..afterError((req, err) {...})  // called after an error has been received but not yet processed by client listener
  ..afterResponseHandled((req, resp) {...})  // called after the response has been processed by client listener
  ..afterErrorHandled((req, err) {...})  // called after the error has been processed by client listener
;

If that's the picture of the future, then this is what we should have now:

tracker.track()
  ..during((req) {...})  // called after the request is sent to the handler but before it is served with success or error
  ..afterResponseHandled((req, resp) {...})  // called after the response has been processed by client listener
  ..afterErrorHandled((req, err) {...})  // called after the error has been processed by client listener
;

What do you think?