blob: 968837349a717c5c2886dc5e145ccc381887278d [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/lib/measure/time_between.h"
namespace tracing {
namespace measure {
namespace {
bool IsOfSupportedType(const trace::Record::Event& event) {
return event.type() == trace::EventType::kInstant ||
event.type() == trace::EventType::kAsyncBegin ||
event.type() == trace::EventType::kDurationBegin ||
event.type() == trace::EventType::kFlowBegin ||
event.type() == trace::EventType::kAsyncEnd ||
event.type() == trace::EventType::kDurationEnd ||
event.type() == trace::EventType::kFlowEnd ||
event.type() == trace::EventType::kDurationComplete;
}
bool EventMatchesSpecWithAnchor(const trace::Record::Event& event, EventSpec spec, Anchor anchor) {
if (!EventMatchesSpec(event, spec)) {
return false;
}
if (event.type() == trace::EventType::kInstant ||
event.type() == trace::EventType::kDurationComplete) {
return true;
} else if (event.type() == trace::EventType::kAsyncBegin ||
event.type() == trace::EventType::kDurationBegin ||
event.type() == trace::EventType::kFlowBegin) {
return anchor == Anchor::Begin;
} else if (event.type() == trace::EventType::kAsyncEnd ||
event.type() == trace::EventType::kDurationEnd ||
event.type() == trace::EventType::kFlowEnd) {
return anchor == Anchor::End;
} else {
return false;
}
}
} // namespace
MeasureTimeBetween::MeasureTimeBetween(std::vector<TimeBetweenSpec> specs)
: specs_(std::move(specs)) {}
// TODO(fmeawad): We currently do not handle TimeBetween 2 DurationComplete
// events that are nested.
bool MeasureTimeBetween::Process(const trace::Record::Event& event) {
if (!IsOfSupportedType(event)) {
return true;
}
for (const TimeBetweenSpec& spec : specs_) {
uint64_t key = spec.common.id;
if (EventMatchesSpecWithAnchor(event, spec.second_event, spec.second_anchor) &&
pending_time_between_.count(key)) {
if (spec.second_anchor == Anchor::End &&
event.type() == trace::EventType::kDurationComplete) {
AddResult(spec.common.id, pending_time_between_[key],
event.data.GetDurationComplete().end_time);
} else {
AddResult(spec.common.id, pending_time_between_[key], event.timestamp);
}
pending_time_between_.erase(key);
}
if (EventMatchesSpecWithAnchor(event, spec.first_event, spec.first_anchor)) {
if (spec.first_anchor == Anchor::End && event.type() == trace::EventType::kDurationComplete) {
pending_time_between_[key] = event.data.GetDurationComplete().end_time;
} else {
pending_time_between_[key] = event.timestamp;
}
}
}
return true;
}
void MeasureTimeBetween::AddResult(uint64_t spec_id, trace_ticks_t from, trace_ticks_t to) {
results_[spec_id].push_back(to - from);
}
} // namespace measure
} // namespace tracing