blob: 278041f9c7f5d3caec3e2a5d3c7076eb760db99f [file] [log] [blame]
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: piatek@google.com (Michael Piatek)
#ifndef PAGESPEED_OPT_LOGGING_REQUEST_TIMING_INFO_H_
#define PAGESPEED_OPT_LOGGING_REQUEST_TIMING_INFO_H_
#include "pagespeed/kernel/base/basictypes.h"
namespace net_instaweb {
class AbstractMutex;
class Timer;
// RequestTimingInfo tracks various event timestamps over the lifetime of a
// request. The timeline looks (roughly) like the following, with the associated
// RequestTimingInfo calls.
// - Request Received/Context created: Init
// <queueing delay>
// - Trigger: RequestStarted
// <option lookup>
// - Start Processing: ProcessingStarted
// - Lookup Properties?: PropertyCacheLookup*
// - Fetch?: Fetch*
// - Start parsing?: ParsingStarted
// - First byte sent to client: FirstByteReturned.
// - Finish: RequestFinished
// NOTE: This class is thread safe.
class RequestTimingInfo {
public:
// Initialize the TimingInfo with the specified Timer. Sets init_ts_ to
// Timer::NowMs, from which GetElapsedMs is based.
// NOTE: Timer and mutex are not owned by TimingInfo.
RequestTimingInfo(Timer* timer, AbstractMutex* mutex);
// This should be called when the request "starts", potentially after
// queuing. It denotes the request "start time", which "elapsed" timing
// values are relative to.
void RequestStarted();
// This should be called once the options are available and PSOL can start
// doing meaningful work.
void ProcessingStarted() { SetToNow(&processing_start_ts_ms_); }
// This should be called if/when HTML parsing begins.
void ParsingStarted() { SetToNow(&parsing_start_ts_ms_); }
// Called when the first byte is sent back to the user.
void FirstByteReturned();
// This should be called when a PropertyCache lookup is initiated.
void PropertyCacheLookupStarted() {
SetToNow(&pcache_lookup_start_ts_ms_);
}
// This should be called when a PropertyCache lookup completes.
void PropertyCacheLookupFinished() { SetToNow(&pcache_lookup_end_ts_ms_); }
// Called when the request is finished, i.e. the response has been sent to
// the client.
void RequestFinished() { SetToNow(&end_ts_ms_); }
// Fetch related timing events.
// Note: Only the first call to FetchStarted will have an effect,
// subsequent calls are silent no-ops.
// TODO(gee): Fetch and cache timing is busted for reconstructing resources
// with multiple inputs.
void FetchStarted();
void FetchHeaderReceived();
void FetchFinished();
// TODO(gee): I'd really prefer these to be start/end calls, but the
// WriteThroughCache design pattern will not allow for this.
void SetHTTPCacheLatencyMs(int64 latency_ms);
void SetL2HTTPCacheLatencyMs(int64 latency_ms);
// Milliseconds since Init.
int64 GetElapsedMs() const;
// Milliseconds from request start to processing start.
bool GetTimeToStartProcessingMs(int64* elapsed_ms) const {
return GetTimeFromStart(processing_start_ts_ms_, elapsed_ms);
}
// Milliseconds spent "processing": end time - start time - fetch time.
// TODO(gee): This naming is somewhat misleading since it is from request
// start not processing start. Leaving as is for historical reasons, at
// least for the time being.
bool GetProcessingElapsedMs(int64* elapsed_ms) const;
// Milliseconds from request start to pcache lookup start.
bool GetTimeToPropertyCacheLookupStartMs(int64* elapsed_ms) const {
return GetTimeFromStart(pcache_lookup_start_ts_ms_, elapsed_ms);
}
// Milliseconds from request start to pcache lookup end.
bool GetTimeToPropertyCacheLookupEndMs(int64* elapsed_ms) const {
return GetTimeFromStart(pcache_lookup_end_ts_ms_, elapsed_ms);
}
// HTTP Cache latencies.
bool GetHTTPCacheLatencyMs(int64* latency_ms) const;
bool GetL2HTTPCacheLatencyMs(int64* latency_ms) const;
// Milliseconds from request start to fetch start.
bool GetTimeToStartFetchMs(int64* elapsed_ms) const;
// Milliseconds from fetch start to header received.
bool GetFetchHeaderLatencyMs(int64* latency_ms) const;
// Milliseconds from fetch start to fetch end.
bool GetFetchLatencyMs(int64* latency_ms) const;
// Milliseconds from receiving the request (Init) to responding with the
// first byte of data.
bool GetTimeToFirstByte(int64* latency_ms) const;
// Milliseconds from request start to parse start.
bool GetTimeToStartParseMs(int64* elapsed_ms) const {
return GetTimeFromStart(parsing_start_ts_ms_, elapsed_ms);
}
int64 init_ts_ms() const { return init_ts_ms_; }
int64 start_ts_ms() const { return start_ts_ms_; }
private:
int64 NowMs() const;
// Set "ts_ms" to NowMs().
void SetToNow(int64* ts_ms) const;
// Set "elapsed_ms" to "ts_ms" - start_ms_ and returns true on success.
// Returns false if either start_ms_ or "ts_ms" have not been set (< 0).
bool GetTimeFromStart(int64 ts_ms, int64* elapsed_ms) const;
Timer* timer_;
// Event Timestamps. These should appear in (roughly) chronological order.
// These need not be protected by mu_ as they are only accessed by a single
// thread at any given time, and subsequent accesses are made through
// paths which are synchronized by other locks (pcache callback collector,
// sequences, etc.).
int64 init_ts_ms_;
int64 start_ts_ms_;
int64 processing_start_ts_ms_;
int64 pcache_lookup_start_ts_ms_;
int64 pcache_lookup_end_ts_ms_;
int64 parsing_start_ts_ms_;
int64 end_ts_ms_;
AbstractMutex* mu_; // Not owned by TimingInfo.
// The following members are protected by mu_;
int64 fetch_start_ts_ms_;
int64 fetch_header_ts_ms_;
int64 fetch_end_ts_ms_;
int64 first_byte_ts_ms_;
// Latencies.
int64 http_cache_latency_ms_;
int64 l2http_cache_latency_ms_;
DISALLOW_COPY_AND_ASSIGN(RequestTimingInfo);
};
} // namespace net_instaweb
#endif // PAGESPEED_OPT_LOGGING_REQUEST_TIMING_INFO_H_