| // 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 <memory> |
| |
| #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 { |
| |
| #if !defined(STARBOARD) |
| ///////////////////////////////////////////////////////////////////////////// |
| // 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(); |
| } |
| |
| #endif // !defined(STARBOARD) |
| |
| } // namespace |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| TraceEventSystemStatsMonitor::TraceEventSystemStatsMonitor( |
| scoped_refptr<SingleThreadTaskRunner> 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() { |
| #if defined(STARBOARD) |
| NOTREACHED(); |
| #else |
| std::unique_ptr<SystemStatsHolder> 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)); |
| #endif |
| } |
| |
| void TraceEventSystemStatsMonitor::StopProfiling() { |
| dump_timer_.Stop(); |
| } |
| |
| bool TraceEventSystemStatsMonitor::IsTimerRunningForTest() const { |
| return dump_timer_.IsRunning(); |
| } |
| |
| #if !defined(STARBOARD) |
| void AppendSystemProfileAsTraceFormat(const SystemMetrics& system_metrics, |
| std::string* output) { |
| std::string tmp; |
| base::JSONWriter::Write(*system_metrics.ToValue(), &tmp); |
| *output += tmp; |
| } |
| #endif // !defined(STARBOARD) |
| |
| } // namespace trace_event |
| } // namespace base |