Search code examples
delphiindy

Easy to way to time Indy connect and receive times?


Is there an easy way to get the time it took Indy to connect, and the time it took to receive data, in a TIdHTTP.Get() or TIdHTTP.Put() operation?

EDIT:
I want to get statistics to determine which timeouts are best to use for the ReceiveTimeout and ConnectTimeOut properties.


Solution

  • For timing a connect, you can use the OnStatus(hsConnecting) and OnStatus(hsConnected)/OnConnected events. Note that if a URL involves a hostname (which is the usual case), there is also an OnStatus(hsResolving) event that precedes the OnStatus(hsConnecting) event. However, DNS resolution does not play into ConnectTimeout handling at this time.

    For timing the receive, that is a bit trickier, since there are no events for detecting the end of sending a request, or the beginning/ending of reading a response 1. And also that a given HTTP request may involve multiple steps (redirects, authentication, etc), which may also involve multiple disconnects/re-connects since HTTP is a stateless protocol not dependent on a persistent connection, like most other protocols are. So, about the only way I can think of accomplishing this is to attach an Intercept component to the TIdHTTP.Intercept property and then manually parse the HTTP messages as they are being exchanged.

    • 1 Actually, that is not entirely true. There is a TIdHTTP.OnHeadersAvailable event, which is fired after the HTTP response headers have been read, and before the HTTP response body is read, at least. So, if you don't care about the timing of the headers, you can use that event to start timing the receiving of the body data, at least. And then stop the timing when Get()/Post() exits. For each multi-step that requires TIdHTTP to repeat a request, you should get a new OnHeadersAvailable event, which you can use to reset your timer. That way, you end up with the time of the final response only.

    However, note that ReceiveTimeout is a per-byte timeout, so an alternative might be to use a custom TStream (or Indy's TIdEventStream) to receive the HTTP response data into, and then you can time the durations between individual writes to that stream by overwriting its Write() method (or using the OnWrite event).