// Copyright 2013 The Chromium 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 "base/trace_event/trace_event_system_stats_monitor.h" #include #include "base/debug/leak_annotations.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" #include "base/process/process_metrics.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/threading/thread_local_storage.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" namespace base { namespace trace_event { namespace { ///////////////////////////////////////////////////////////////////////////// // Holds profiled system stats until the tracing system needs to serialize it. class SystemStatsHolder : public base::trace_event::ConvertableToTraceFormat { public: SystemStatsHolder() = default; ~SystemStatsHolder() override = default; // Fills system_metrics_ with profiled system memory and disk stats. // Uses the previous stats to compute rates if this is not the first profile. void GetSystemProfilingStats(); // base::trace_event::ConvertableToTraceFormat overrides: void AppendAsTraceFormat(std::string* out) const override { AppendSystemProfileAsTraceFormat(system_stats_, out); } private: SystemMetrics system_stats_; DISALLOW_COPY_AND_ASSIGN(SystemStatsHolder); }; void SystemStatsHolder::GetSystemProfilingStats() { system_stats_ = SystemMetrics::Sample(); } } // namespace ////////////////////////////////////////////////////////////////////////////// TraceEventSystemStatsMonitor::TraceEventSystemStatsMonitor( scoped_refptr task_runner) : task_runner_(task_runner), weak_factory_(this) { // Force the "system_stats" category to show up in the trace viewer. TraceLog::GetCategoryGroupEnabled(TRACE_DISABLED_BY_DEFAULT("system_stats")); // Allow this to be instantiated on unsupported platforms, but don't run. TraceLog::GetInstance()->AddEnabledStateObserver(this); } TraceEventSystemStatsMonitor::~TraceEventSystemStatsMonitor() { if (dump_timer_.IsRunning()) StopProfiling(); TraceLog::GetInstance()->RemoveEnabledStateObserver(this); } void TraceEventSystemStatsMonitor::OnTraceLogEnabled() { // Check to see if system tracing is enabled. bool enabled; TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT( "system_stats"), &enabled); if (!enabled) return; task_runner_->PostTask( FROM_HERE, base::BindOnce(&TraceEventSystemStatsMonitor::StartProfiling, weak_factory_.GetWeakPtr())); } void TraceEventSystemStatsMonitor::OnTraceLogDisabled() { task_runner_->PostTask( FROM_HERE, base::BindOnce(&TraceEventSystemStatsMonitor::StopProfiling, weak_factory_.GetWeakPtr())); } void TraceEventSystemStatsMonitor::StartProfiling() { // Watch for the tracing framework sending enabling more than once. if (dump_timer_.IsRunning()) return; dump_timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(TraceEventSystemStatsMonitor:: kSamplingIntervalMilliseconds), base::Bind(&TraceEventSystemStatsMonitor:: DumpSystemStats, weak_factory_.GetWeakPtr())); } // If system tracing is enabled, dumps a profile to the tracing system. void TraceEventSystemStatsMonitor::DumpSystemStats() { std::unique_ptr dump_holder(new SystemStatsHolder()); dump_holder->GetSystemProfilingStats(); TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( TRACE_DISABLED_BY_DEFAULT("system_stats"), "base::TraceEventSystemStatsMonitor::SystemStats", this, std::move(dump_holder)); } void TraceEventSystemStatsMonitor::StopProfiling() { dump_timer_.Stop(); } bool TraceEventSystemStatsMonitor::IsTimerRunningForTest() const { return dump_timer_.IsRunning(); } void AppendSystemProfileAsTraceFormat(const SystemMetrics& system_metrics, std::string* output) { std::string tmp; base::JSONWriter::Write(*system_metrics.ToValue(), &tmp); *output += tmp; } } // namespace trace_event } // namespace base