blob: 55be17e279f4a5a3df2d99cb2ef8e94c9103c24c [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)
#include "pagespeed/opt/logging/request_timing_info.h"
#include "base/logging.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/timer.h"
namespace net_instaweb {
namespace {
bool SetValueIfGEZero(int64 in, int64* out) {
if (in < 0) {
return false;
}
*out = in;
return true;
}
} // namespace
RequestTimingInfo::RequestTimingInfo(Timer* timer, AbstractMutex* mutex)
: timer_(timer),
init_ts_ms_(-1),
start_ts_ms_(-1),
processing_start_ts_ms_(-1),
pcache_lookup_start_ts_ms_(-1),
pcache_lookup_end_ts_ms_(-1),
parsing_start_ts_ms_(-1),
end_ts_ms_(-1),
mu_(mutex),
fetch_start_ts_ms_(-1),
fetch_header_ts_ms_(-1),
fetch_end_ts_ms_(-1),
first_byte_ts_ms_(-1),
http_cache_latency_ms_(-1),
l2http_cache_latency_ms_(-1) {
init_ts_ms_ = NowMs();
}
void RequestTimingInfo::RequestStarted() {
SetToNow(&start_ts_ms_);
VLOG(2) << "RequestStarted: " << start_ts_ms_;
}
void RequestTimingInfo::FirstByteReturned() {
ScopedMutex l(mu_);
SetToNow(&first_byte_ts_ms_);
}
void RequestTimingInfo::FetchStarted() {
ScopedMutex l(mu_);
if (fetch_start_ts_ms_ > 0) {
// It's possible this is called more than once, just ignore subsequent
// calls.
return;
}
SetToNow(&fetch_start_ts_ms_);
}
void RequestTimingInfo::FetchHeaderReceived() {
ScopedMutex l(mu_);
SetToNow(&fetch_header_ts_ms_);
}
void RequestTimingInfo::FetchFinished() {
ScopedMutex l(mu_);
SetToNow(&fetch_end_ts_ms_);
}
void RequestTimingInfo::SetHTTPCacheLatencyMs(int64 latency_ms) {
ScopedMutex l(mu_);
SetValueIfGEZero(latency_ms, &http_cache_latency_ms_);
}
void RequestTimingInfo::SetL2HTTPCacheLatencyMs(int64 latency_ms) {
ScopedMutex l(mu_);
SetValueIfGEZero(latency_ms, &l2http_cache_latency_ms_);
}
int64 RequestTimingInfo::GetElapsedMs() const {
DCHECK_GE(init_ts_ms_, 0);
return NowMs() - init_ts_ms_;
}
bool RequestTimingInfo::GetProcessingElapsedMs(
int64* processing_elapsed_ms) const {
if (end_ts_ms_ < 0 || start_ts_ms_ < 0) {
return false;
}
int64 elapsed_ms = end_ts_ms_ - start_ts_ms_;
int64 fetch_elapsed_ms = 0;
if (GetFetchLatencyMs(&fetch_elapsed_ms)) {
elapsed_ms -= fetch_elapsed_ms;
}
*processing_elapsed_ms = elapsed_ms;
return true;
}
bool RequestTimingInfo::GetTimeToStartFetchMs(
int64* elapsed_ms) const {
ScopedMutex l(mu_);
return GetTimeFromStart(fetch_start_ts_ms_, elapsed_ms);
}
bool RequestTimingInfo::GetFetchHeaderLatencyMs(
int64* elapsed_ms) const {
ScopedMutex l(mu_);
if (fetch_header_ts_ms_ < 0 || fetch_start_ts_ms_< 0) {
return false;
}
const int64 tmp_elapsed_ms = fetch_header_ts_ms_ - fetch_start_ts_ms_;
if (tmp_elapsed_ms < 0) {
return false;
}
*elapsed_ms = tmp_elapsed_ms;
return true;
}
bool RequestTimingInfo::GetFetchLatencyMs(int64* elapsed_ms) const {
ScopedMutex l(mu_);
if (fetch_end_ts_ms_ < 0 || fetch_start_ts_ms_ < 0) {
return false;
}
*elapsed_ms = fetch_end_ts_ms_ - fetch_start_ts_ms_;
return true;
}
bool RequestTimingInfo::GetTimeToFirstByte(int64* latency_ms) const {
ScopedMutex l(mu_);
if (first_byte_ts_ms_ < 0) {
return false;
}
*latency_ms = first_byte_ts_ms_ - init_ts_ms_;
return true;
}
int64 RequestTimingInfo::NowMs() const {
if (timer_ == NULL) {
return 0;
}
return timer_->NowMs();
}
void RequestTimingInfo::SetToNow(int64* ts) const {
DCHECK_GE(*ts, -1);
*ts = NowMs();
}
bool RequestTimingInfo::GetTimeFromStart(
int64 ts_ms, int64* elapsed_ms) const {
if (ts_ms < 0 || start_ts_ms_ < 0) {
return false;
}
*elapsed_ms = ts_ms - start_ts_ms_;
return true;
}
bool RequestTimingInfo::GetHTTPCacheLatencyMs(
int64* latency_ms) const {
ScopedMutex l(mu_);
return SetValueIfGEZero(http_cache_latency_ms_, latency_ms);
}
bool RequestTimingInfo::GetL2HTTPCacheLatencyMs(
int64* latency_ms) const {
ScopedMutex l(mu_);
return SetValueIfGEZero(l2http_cache_latency_ms_, latency_ms);
}
} // namespace net_instaweb