#include "components/metrics/call_stack_profile_builder.h"
+#include <stdint.h>
#include <algorithm>
#include <iterator>
#include <map>
#include "base/logging.h"
#include "base/metrics/metrics_hashes.h"
#include "base/no_destructor.h"
+#include "base/numerics/safe_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/metrics/call_stack_profile_encoding.h"
base::TimeTicks period_start,
base::TimeTicks period_end,
const base::MetadataRecorder::Item& item) {
- DCHECK_LE(period_start, period_end);
- DCHECK_LE(period_end, base::TimeTicks::Now());
+ CHECK_LE(period_start, period_end);
+ CHECK_LE(period_end, base::TimeTicks::Now());
// We don't set metadata if the period extends before the start of the
// sampling, to avoid biasing against the unobserved execution. This will
google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>* samples =
call_stack_profile->mutable_stack_sample();
- DCHECK_EQ(sample_timestamps_.size(), static_cast<size_t>(samples->size()));
+ CHECK_EQ(sample_timestamps_.size(), static_cast<size_t>(samples->size()));
const ptrdiff_t start_offset =
std::lower_bound(sample_timestamps_.begin(), sample_timestamps_.end(),
call_stack_profile->mutable_metadata_name_hash());
}
+void CallStackProfileBuilder::AddProfileMetadata(
+ const base::MetadataRecorder::Item& item) {
+ CallStackProfile* call_stack_profile =
+ sampled_profile_.mutable_call_stack_profile();
+
+ metadata_.SetMetadata(item,
+ call_stack_profile->mutable_profile_metadata()->Add(),
+ call_stack_profile->mutable_metadata_name_hash());
+}
+
void CallStackProfileBuilder::OnSampleCompleted(
std::vector<base::Frame> frames,
base::TimeTicks sample_timestamp) {
ptrdiff_t module_offset =
reinterpret_cast<const char*>(instruction_pointer) -
reinterpret_cast<const char*>(frame.module->GetBaseAddress());
- // Temporarily disable this DCHECK as there's likely bug in ModuleCache
- // that causes this to fail. This results in bad telemetry data but no
- // functional effect. https://crbug.com/1240645.
- // DCHECK_GE(module_offset, 0);
+ DCHECK_GE(module_offset, 0);
location->set_address(static_cast<uint64_t>(module_offset));
location->set_module_id_index(module_loc->second);
}
if (profile_start_time_.is_null())
profile_start_time_ = sample_timestamp;
+ // Write timestamps to protobuf message. Currently the timestamps are only
+ // used for browser process to apply LCP tags. The browser process will clear
+ // the timestamps information once it is done with LCP tagging. Timestamps
+ // will not be included in the final profile sent to UMA.
+ const int64_t offset =
+ (sample_timestamp - profile_start_time_).InMilliseconds();
+ stack_sample_proto->set_sample_time_offset_ms(
+ base::saturated_cast<int32_t>(offset));
+
sample_timestamps_.push_back(sample_timestamp);
}
profile_duration.InMilliseconds());
call_stack_profile->set_sampling_period_ms(sampling_period.InMilliseconds());
+ // Heap profiler sets `profile_time_offset_ms` through constructor.
+ // For CPU profiles, `profile_time_offset_ms` is the time of the first
+ // sample.
+ if (!call_stack_profile->has_profile_time_offset_ms()) {
+ call_stack_profile->set_profile_time_offset_ms(
+ profile_start_time_.since_origin().InMilliseconds());
+ }
+
// Write CallStackProfile::ModuleIdentifier protobuf message.
for (const auto* module : modules_) {
CallStackProfile::ModuleIdentifier* module_id =
module_id->set_name_md5_prefix(
HashModuleFilename(module->GetDebugBasename()));
}
+ // sampled_profile_ cannot be reused after it is cleared by this function.
+ // Check we still have the information from the constructor.
+ CHECK(sampled_profile_.has_process());
+ CHECK(sampled_profile_.has_thread());
+ CHECK(sampled_profile_.has_trigger_event());
PassProfilesToMetricsProvider(profile_start_time_,
std::move(sampled_profile_));
+ // Protobuffers are in an uncertain state after moving from; clear to get
+ // back to known state.
+ sampled_profile_.Clear();
// Run the completed callback if there is one.
if (!completed_callback_.is_null())
stack_index_.clear();
module_index_.clear();
modules_.clear();
+ sample_timestamps_.clear();
}
// static