diff options
Diffstat (limited to 'chromium/components/tracing')
-rw-r--r-- | chromium/components/tracing/BUILD.gn | 30 | ||||
-rw-r--r-- | chromium/components/tracing/DEPS | 1 | ||||
-rw-r--r-- | chromium/components/tracing/OWNERS | 1 | ||||
-rw-r--r-- | chromium/components/tracing/child_memory_dump_manager_delegate_impl.cc | 64 | ||||
-rw-r--r-- | chromium/components/tracing/child_memory_dump_manager_delegate_impl.h | 24 | ||||
-rw-r--r-- | chromium/components/tracing/child_trace_message_filter.cc | 85 | ||||
-rw-r--r-- | chromium/components/tracing/child_trace_message_filter.h | 16 | ||||
-rw-r--r-- | chromium/components/tracing/startup_tracing.cc | 66 | ||||
-rw-r--r-- | chromium/components/tracing/startup_tracing.h | 18 | ||||
-rw-r--r-- | chromium/components/tracing/trace_config_file.cc | 140 | ||||
-rw-r--r-- | chromium/components/tracing/trace_config_file.h | 96 | ||||
-rw-r--r-- | chromium/components/tracing/trace_config_file_unittest.cc | 220 | ||||
-rw-r--r-- | chromium/components/tracing/tracing_export.h | 29 | ||||
-rw-r--r-- | chromium/components/tracing/tracing_messages.h | 23 | ||||
-rw-r--r-- | chromium/components/tracing/tracing_switches.cc | 52 | ||||
-rw-r--r-- | chromium/components/tracing/tracing_switches.h | 22 |
16 files changed, 774 insertions, 113 deletions
diff --git a/chromium/components/tracing/BUILD.gn b/chromium/components/tracing/BUILD.gn index 336f5cb5ea4..bd5b2711492 100644 --- a/chromium/components/tracing/BUILD.gn +++ b/chromium/components/tracing/BUILD.gn @@ -2,29 +2,51 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("tracing") { +component("tracing") { sources = [ "child_memory_dump_manager_delegate_impl.cc", "child_memory_dump_manager_delegate_impl.h", "child_trace_message_filter.cc", "child_trace_message_filter.h", + "tracing_export.h", "tracing_messages.cc", "tracing_messages.h", ] + defines = [ "TRACING_IMPLEMENTATION" ] + deps = [ "//base", "//ipc", ] } -source_set("startup_tracing") { +component("startup_tracing") { sources = [ - "startup_tracing.cc", - "startup_tracing.h", + "trace_config_file.cc", + "trace_config_file.h", + "tracing_export.h", + "tracing_switches.cc", + "tracing_switches.h", ] + defines = [ "TRACING_IMPLEMENTATION" ] + deps = [ "//base", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ + "trace_config_file_unittest.cc", + ] + + deps = [ + ":startup_tracing", + "//base/test:test_support", + "//testing/gtest", + ] +} diff --git a/chromium/components/tracing/DEPS b/chromium/components/tracing/DEPS index 9634ba4f06a..1c40d981eb6 100644 --- a/chromium/components/tracing/DEPS +++ b/chromium/components/tracing/DEPS @@ -1,4 +1,3 @@ include_rules = [ - "+base", "+ipc", ] diff --git a/chromium/components/tracing/OWNERS b/chromium/components/tracing/OWNERS index 2226238acb8..1a389403d36 100644 --- a/chromium/components/tracing/OWNERS +++ b/chromium/components/tracing/OWNERS @@ -1,6 +1,7 @@ jbauman@chromium.org nduca@chromium.org dsinclair@chromium.org +simonhatch@chromium.org # Changes to IPC messages require a security review to avoid introducing # new sandbox escapes. diff --git a/chromium/components/tracing/child_memory_dump_manager_delegate_impl.cc b/chromium/components/tracing/child_memory_dump_manager_delegate_impl.cc index 4e2cc9f318d..fe5c952f6a9 100644 --- a/chromium/components/tracing/child_memory_dump_manager_delegate_impl.cc +++ b/chromium/components/tracing/child_memory_dump_manager_delegate_impl.cc @@ -9,67 +9,89 @@ namespace tracing { +namespace { +void AbortDumpRequest(const base::trace_event::MemoryDumpRequestArgs& args, + const base::trace_event::MemoryDumpCallback& callback) { + if (!callback.is_null()) + callback.Run(args.dump_guid, false /* success */); +} +} // namespace + // static ChildMemoryDumpManagerDelegateImpl* ChildMemoryDumpManagerDelegateImpl::GetInstance() { - return Singleton< + return base::Singleton< ChildMemoryDumpManagerDelegateImpl, - LeakySingletonTraits<ChildMemoryDumpManagerDelegateImpl>>::get(); + base::LeakySingletonTraits<ChildMemoryDumpManagerDelegateImpl>>::get(); } ChildMemoryDumpManagerDelegateImpl::ChildMemoryDumpManagerDelegateImpl() - : ctmf_(nullptr) { - base::trace_event::MemoryDumpManager::GetInstance()->SetDelegate(this); + : ctmf_(nullptr), + tracing_process_id_( + base::trace_event::MemoryDumpManager::kInvalidTracingProcessId) { } -ChildMemoryDumpManagerDelegateImpl::~ChildMemoryDumpManagerDelegateImpl() { -} +ChildMemoryDumpManagerDelegateImpl::~ChildMemoryDumpManagerDelegateImpl() {} void ChildMemoryDumpManagerDelegateImpl::SetChildTraceMessageFilter( ChildTraceMessageFilter* ctmf) { + const auto& task_runner = ctmf ? (ctmf->ipc_task_runner()) : nullptr; // Check that we are either registering the CTMF or tearing it down, but not // replacing a valid instance with another one (should never happen). DCHECK(ctmf_ == nullptr || (ctmf == nullptr && ctmf_task_runner_ != nullptr)); ctmf_ = ctmf; - ctmf_task_runner_ = ctmf ? (ctmf->ipc_task_runner()) : nullptr; + + { + base::AutoLock lock(lock_); + ctmf_task_runner_ = task_runner; + } + + if (ctmf) { + base::trace_event::MemoryDumpManager::GetInstance()->Initialize( + this /* delegate */, false /* is_coordinator */); + } } // Invoked in child processes by the MemoryDumpManager. void ChildMemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump( const base::trace_event::MemoryDumpRequestArgs& args, const base::trace_event::MemoryDumpCallback& callback) { + // RequestGlobalMemoryDump can be called on any thread, cannot access + // ctmf_task_runner_ as it could be racy. + scoped_refptr<base::SingleThreadTaskRunner> ctmf_task_runner; + { + base::AutoLock lock(lock_); + ctmf_task_runner = ctmf_task_runner_; + } + // Bail out if we receive a dump request from the manager before the // ChildTraceMessageFilter has been initialized. - if (!ctmf_task_runner_) { - if (!callback.is_null()) - callback.Run(args.dump_guid, false /* success */); - return; - } + if (!ctmf_task_runner) + return AbortDumpRequest(args, callback); // Make sure we access |ctmf_| only on the thread where it lives to avoid // races on shutdown. - if (!ctmf_task_runner_->BelongsToCurrentThread()) { - ctmf_task_runner_->PostTask( + if (!ctmf_task_runner->BelongsToCurrentThread()) { + const bool did_post_task = ctmf_task_runner->PostTask( FROM_HERE, base::Bind(&ChildMemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump, base::Unretained(this), args, callback)); + if (!did_post_task) + return AbortDumpRequest(args, callback); return; } // The ChildTraceMessageFilter could have been destroyed while hopping on the // right thread. If this is the case, bail out. - if (!ctmf_) { - if (!callback.is_null()) - callback.Run(args.dump_guid, false /* success */); - return; - } + if (!ctmf_) + return AbortDumpRequest(args, callback); // Send the request up to the browser process' MessageDumpmanager. ctmf_->SendGlobalMemoryDumpRequest(args, callback); } -bool ChildMemoryDumpManagerDelegateImpl::IsCoordinatorProcess() const { - return false; +uint64 ChildMemoryDumpManagerDelegateImpl::GetTracingProcessId() const { + return tracing_process_id_; } } // namespace tracing diff --git a/chromium/components/tracing/child_memory_dump_manager_delegate_impl.h b/chromium/components/tracing/child_memory_dump_manager_delegate_impl.h index 912815dd018..ca5de293ed7 100644 --- a/chromium/components/tracing/child_memory_dump_manager_delegate_impl.h +++ b/chromium/components/tracing/child_memory_dump_manager_delegate_impl.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/singleton.h" +#include "base/synchronization/lock.h" namespace base { class SingleThreadTaskRunner; @@ -33,16 +34,27 @@ class ChildMemoryDumpManagerDelegateImpl void RequestGlobalMemoryDump( const base::trace_event::MemoryDumpRequestArgs& args, const base::trace_event::MemoryDumpCallback& callback) override; - bool IsCoordinatorProcess() const override; + uint64 GetTracingProcessId() const override; void SetChildTraceMessageFilter(ChildTraceMessageFilter* ctmf); + // Pass kInvalidTracingProcessId to invalidate the id. + void set_tracing_process_id(uint64 id) { + DCHECK_IMPLIES( + tracing_process_id_ != + base::trace_event::MemoryDumpManager::kInvalidTracingProcessId, + id == base::trace_event::MemoryDumpManager::kInvalidTracingProcessId || + id == tracing_process_id_); + tracing_process_id_ = id; + } + protected: // Make CreateProcessDump() visible to ChildTraceMessageFilter. friend class ChildTraceMessageFilter; private: - friend struct DefaultSingletonTraits<ChildMemoryDumpManagerDelegateImpl>; + friend struct base::DefaultSingletonTraits< + ChildMemoryDumpManagerDelegateImpl>; ChildMemoryDumpManagerDelegateImpl(); ~ChildMemoryDumpManagerDelegateImpl() override; @@ -53,6 +65,14 @@ class ChildMemoryDumpManagerDelegateImpl // It is NULL iff |cmtf_| is NULL. scoped_refptr<base::SingleThreadTaskRunner> ctmf_task_runner_; + // Protects from concurrent access to |ctmf_task_runner_| to allow + // RequestGlobalMemoryDump to be called from arbitrary threads. + base::Lock lock_; + + // The unique id of the child process, created for tracing and is expected to + // be valid only when tracing is enabled. + uint64 tracing_process_id_; + DISALLOW_COPY_AND_ASSIGN(ChildMemoryDumpManagerDelegateImpl); }; diff --git a/chromium/components/tracing/child_trace_message_filter.cc b/chromium/components/tracing/child_trace_message_filter.cc index 19fef02e106..62e13aec2c0 100644 --- a/chromium/components/tracing/child_trace_message_filter.cc +++ b/chromium/components/tracing/child_trace_message_filter.cc @@ -4,6 +4,7 @@ #include "components/tracing/child_trace_message_filter.h" +#include "base/metrics/statistics_recorder.h" #include "base/trace_event/trace_event.h" #include "components/tracing/child_memory_dump_manager_delegate_impl.h" #include "components/tracing/tracing_messages.h" @@ -13,6 +14,12 @@ using base::trace_event::TraceLog; namespace tracing { +namespace { + +const int kMinTimeBetweenHistogramChangesInSeconds = 10; + +} // namespace + ChildTraceMessageFilter::ChildTraceMessageFilter( base::SingleThreadTaskRunner* ipc_task_runner) : sender_(NULL), @@ -50,6 +57,8 @@ bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) { OnProcessMemoryDumpRequest) IPC_MESSAGE_HANDLER(TracingMsg_GlobalMemoryDumpResponse, OnGlobalMemoryDumpResponse) + IPC_MESSAGE_HANDLER(TracingMsg_SetUMACallback, OnSetUMACallback) + IPC_MESSAGE_HANDLER(TracingMsg_ClearUMACallback, OnClearUMACallback) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -226,4 +235,80 @@ void ChildTraceMessageFilter::OnGlobalMemoryDumpResponse(uint64 dump_guid, pending_memory_dump_callback_.Run(dump_guid, success); } +void ChildTraceMessageFilter::OnHistogramChanged( + const std::string& histogram_name, + base::Histogram::Sample reference_lower_value, + base::Histogram::Sample reference_upper_value, + base::Histogram::Sample actual_value) { + if (actual_value < reference_lower_value || + actual_value > reference_upper_value) + return; + + ipc_task_runner_->PostTask( + FROM_HERE, base::Bind(&ChildTraceMessageFilter::SendTriggerMessage, this, + histogram_name)); +} + +void ChildTraceMessageFilter::SendTriggerMessage( + const std::string& histogram_name) { + if (!histogram_last_changed_.is_null()) { + base::Time computed_next_allowed_time = + histogram_last_changed_ + + base::TimeDelta::FromSeconds(kMinTimeBetweenHistogramChangesInSeconds); + if (computed_next_allowed_time > base::Time::Now()) + return; + } + histogram_last_changed_ = base::Time::Now(); + + if (sender_) + sender_->Send(new TracingHostMsg_TriggerBackgroundTrace(histogram_name)); +} + +void ChildTraceMessageFilter::OnSetUMACallback( + const std::string& histogram_name, + int histogram_lower_value, + int histogram_upper_value) { + histogram_last_changed_ = base::Time(); + base::StatisticsRecorder::SetCallback( + histogram_name, + base::Bind(&ChildTraceMessageFilter::OnHistogramChanged, this, + histogram_name, histogram_lower_value, histogram_upper_value)); + + base::HistogramBase* existing_histogram = + base::StatisticsRecorder::FindHistogram(histogram_name); + if (!existing_histogram) + return; + + scoped_ptr<base::HistogramSamples> samples = + existing_histogram->SnapshotSamples(); + if (!samples) + return; + + scoped_ptr<base::SampleCountIterator> sample_iterator = samples->Iterator(); + if (!sample_iterator) + return; + + while (!sample_iterator->Done()) { + base::HistogramBase::Sample min; + base::HistogramBase::Sample max; + base::HistogramBase::Count count; + sample_iterator->Get(&min, &max, &count); + if (min >= histogram_lower_value && max <= histogram_upper_value && + count > 0) { + ipc_task_runner_->PostTask( + FROM_HERE, base::Bind(&ChildTraceMessageFilter::SendTriggerMessage, + this, histogram_name)); + break; + } + + sample_iterator->Next(); + } +} + +void ChildTraceMessageFilter::OnClearUMACallback( + const std::string& histogram_name) { + histogram_last_changed_ = base::Time(); + base::StatisticsRecorder::ClearCallback(histogram_name); +} + } // namespace tracing diff --git a/chromium/components/tracing/child_trace_message_filter.h b/chromium/components/tracing/child_trace_message_filter.h index f61e29429e2..124f5625f3b 100644 --- a/chromium/components/tracing/child_trace_message_filter.h +++ b/chromium/components/tracing/child_trace_message_filter.h @@ -7,7 +7,10 @@ #include "base/bind.h" #include "base/memory/ref_counted_memory.h" +#include "base/metrics/histogram.h" +#include "base/time/time.h" #include "base/trace_event/memory_dump_request_args.h" +#include "components/tracing/tracing_export.h" #include "ipc/message_filter.h" namespace base { @@ -17,7 +20,7 @@ class SingleThreadTaskRunner; namespace tracing { // This class sends and receives trace messages on child processes. -class ChildTraceMessageFilter : public IPC::MessageFilter { +class TRACING_EXPORT ChildTraceMessageFilter : public IPC::MessageFilter { public: explicit ChildTraceMessageFilter( base::SingleThreadTaskRunner* ipc_task_runner); @@ -57,6 +60,15 @@ class ChildTraceMessageFilter : public IPC::MessageFilter { void OnProcessMemoryDumpRequest( const base::trace_event::MemoryDumpRequestArgs& args); void OnGlobalMemoryDumpResponse(uint64 dump_guid, bool success); + void OnSetUMACallback(const std::string& histogram_name, + int histogram_lower_value, + int histogram_upper_value); + void OnClearUMACallback(const std::string& histogram_name); + void OnHistogramChanged(const std::string& histogram_name, + base::Histogram::Sample reference_lower_value, + base::Histogram::Sample reference_upper_value, + base::Histogram::Sample actual_value); + void SendTriggerMessage(const std::string& histogram_name); // Callback from trace subsystem. void OnTraceDataCollected( @@ -79,6 +91,8 @@ class ChildTraceMessageFilter : public IPC::MessageFilter { // callback of the outstanding memory dump request, if any. base::trace_event::MemoryDumpCallback pending_memory_dump_callback_; + base::Time histogram_last_changed_; + DISALLOW_COPY_AND_ASSIGN(ChildTraceMessageFilter); }; diff --git a/chromium/components/tracing/startup_tracing.cc b/chromium/components/tracing/startup_tracing.cc deleted file mode 100644 index 321b95092a4..00000000000 --- a/chromium/components/tracing/startup_tracing.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2015 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 "components/tracing/startup_tracing.h" - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/path_service.h" -#include "base/trace_event/trace_event.h" - -namespace tracing { - -namespace { - -// Maximum trace config file size that will be loaded, in bytes. -const size_t kTraceConfigFileSizeLimit = 64 * 1024; - -// Trace config file path: -// - Android: /data/local/.config/chrome-trace-config.json -// - POSIX other than Android: $HOME/.config/chrome-trace-config.json -// - Win: %USERPROFILE%/.config/chrome-trace-config.json -#if defined(OS_ANDROID) -const base::FilePath::CharType kAndroidTraceConfigDir[] = - FILE_PATH_LITERAL("/data/local"); -#endif - -const base::FilePath::CharType kChromeConfigDir[] = - FILE_PATH_LITERAL(".config"); -const base::FilePath::CharType kTraceConfigFileName[] = - FILE_PATH_LITERAL("chrome-trace-config.json"); - -base::FilePath GetTraceConfigFilePath() { -#if defined(OS_ANDROID) - base::FilePath path(kAndroidTraceConfigDir); -#elif defined(OS_POSIX) || defined(OS_WIN) - base::FilePath path; - PathService::Get(base::DIR_HOME, &path); -#else - base::FilePath path; -#endif - path = path.Append(kChromeConfigDir); - path = path.Append(kTraceConfigFileName); - return path; -} - -} // namespace - -void EnableStartupTracingIfConfigFileExists() { - base::FilePath trace_config_file_path = GetTraceConfigFilePath(); - if (!base::PathExists(trace_config_file_path)) - return; - - std::string trace_config_str; - if (!base::ReadFileToString(trace_config_file_path, - &trace_config_str, - kTraceConfigFileSizeLimit)) { - return; - } - - base::trace_event::TraceConfig trace_config(trace_config_str); - base::trace_event::TraceLog::GetInstance()->SetEnabled( - trace_config, base::trace_event::TraceLog::RECORDING_MODE); -} - -} // namespace tracing diff --git a/chromium/components/tracing/startup_tracing.h b/chromium/components/tracing/startup_tracing.h deleted file mode 100644 index ae68f6fa654..00000000000 --- a/chromium/components/tracing/startup_tracing.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2015 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. - -#ifndef COMPONENTS_TRACING_STARTUP_TRACING_H_ -#define COMPONENTS_TRACING_STARTUP_TRACING_H_ - -namespace tracing { - -// Enable startup tracing according to the trace config file. If the trace -// config file does not exist, it will do nothing. This is designed to be used -// by Telemetry. Telemetry will stop tracing via DevTools later. To avoid -// conflict, this should not be used when --trace-startup is enabled. -void EnableStartupTracingIfConfigFileExists(); - -} // namespace tracing - -#endif // COMPONENTS_TRACING_STARTUP_TRACING_H_ diff --git a/chromium/components/tracing/trace_config_file.cc b/chromium/components/tracing/trace_config_file.cc new file mode 100644 index 00000000000..769d527ca8b --- /dev/null +++ b/chromium/components/tracing/trace_config_file.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2015 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 "components/tracing/trace_config_file.h" + +#include <string> + +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/memory/singleton.h" +#include "base/values.h" +#include "components/tracing/tracing_switches.h" + +namespace tracing { + +namespace { + +// Maximum trace config file size that will be loaded, in bytes. +const size_t kTraceConfigFileSizeLimit = 64 * 1024; + +// Trace config file path: +// - Android: /data/local/chrome-trace-config.json +// - Others: specified by --trace-config-file flag. +#if defined(OS_ANDROID) +const base::FilePath::CharType kAndroidTraceConfigFile[] = + FILE_PATH_LITERAL("/data/local/chrome-trace-config.json"); +#endif + +const base::FilePath::CharType kDefaultResultFile[] = + FILE_PATH_LITERAL("chrometrace.log"); + +// String parameters that can be used to parse the trace config file content. +const char kTraceConfigParam[] = "trace_config"; +const char kStartupDurationParam[] = "startup_duration"; +const char kResultFileParam[] = "result_file"; + +} // namespace + +TraceConfigFile* TraceConfigFile::GetInstance() { + return base::Singleton<TraceConfigFile, + base::DefaultSingletonTraits<TraceConfigFile>>::get(); +} + +TraceConfigFile::TraceConfigFile() + : is_enabled_(false), + trace_config_(base::trace_event::TraceConfig()), + startup_duration_(0), + result_file_(kDefaultResultFile) { +#if defined(OS_ANDROID) + base::FilePath trace_config_file(kAndroidTraceConfigFile); +#else + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (!command_line.HasSwitch(switches::kTraceConfigFile) || + command_line.HasSwitch(switches::kTraceStartup) || + command_line.HasSwitch(switches::kTraceShutdown)) { + return; + } + base::FilePath trace_config_file = + command_line.GetSwitchValuePath(switches::kTraceConfigFile); +#endif + + if (trace_config_file.empty()) { + // If the trace config file path is not specified, trace Chrome with the + // default configuration for 5 sec. + startup_duration_ = 5; + is_enabled_ = true; + return; + } + + if (!base::PathExists(trace_config_file)) + return; + + std::string trace_config_file_content; + if (!base::ReadFileToString(trace_config_file, + &trace_config_file_content, + kTraceConfigFileSizeLimit)) { + return; + } + is_enabled_ = ParseTraceConfigFileContent(trace_config_file_content); +} + +TraceConfigFile::~TraceConfigFile() { +} + +bool TraceConfigFile::ParseTraceConfigFileContent(const std::string& content) { + scoped_ptr<base::Value> value(base::JSONReader::Read(content)); + if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) + return false; + + scoped_ptr<base::DictionaryValue> dict( + static_cast<base::DictionaryValue*>(value.release())); + + base::DictionaryValue* trace_config_dict = NULL; + if (!dict->GetDictionary(kTraceConfigParam, &trace_config_dict)) + return false; + + std::string trace_config_str; + base::JSONWriter::Write(*trace_config_dict, &trace_config_str); + trace_config_ = base::trace_event::TraceConfig(trace_config_str); + + if (!dict->GetInteger(kStartupDurationParam, &startup_duration_)) + startup_duration_ = 0; + + if (startup_duration_ < 0) + startup_duration_ = 0; + + std::string result_file_str; + if (dict->GetString(kResultFileParam, &result_file_str)) + result_file_ = base::FilePath().AppendASCII(result_file_str); + + return true; +} + +bool TraceConfigFile::IsEnabled() const { + return is_enabled_; +} + +base::trace_event::TraceConfig TraceConfigFile::GetTraceConfig() const { + DCHECK(IsEnabled()); + return trace_config_; +} + +int TraceConfigFile::GetStartupDuration() const { + DCHECK(IsEnabled()); + return startup_duration_; +} + +#if !defined(OS_ANDROID) +base::FilePath TraceConfigFile::GetResultFile() const { + DCHECK(IsEnabled()); + return result_file_; +} +#endif + +} // namespace tracing diff --git a/chromium/components/tracing/trace_config_file.h b/chromium/components/tracing/trace_config_file.h new file mode 100644 index 00000000000..863fee49b5b --- /dev/null +++ b/chromium/components/tracing/trace_config_file.h @@ -0,0 +1,96 @@ +// Copyright (c) 2015 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. + +#ifndef COMPONENTS_TRACING_TRACE_CONFIG_FILE_H_ +#define COMPONENTS_TRACING_TRACE_CONFIG_FILE_H_ + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/trace_event/trace_config.h" +#include "components/tracing/tracing_export.h" + +namespace base { +template <typename Type> struct DefaultSingletonTraits; +} // namespace base + +namespace tracing { + +// TraceConfigFile is a singleton that contains the configurations of tracing. +// One can create a trace config file and use it to configure startup and/or +// shutdown tracing. +// +// The trace config file should be JSON formated. One example is: +// { +// "trace_config": { +// "record_mode": "record-until-full", +// "included_categories": ["cc", "skia"] +// }, +// "startup_duration": 5, +// "result_file": "chrometrace.log" +// } +// +// trace_config: The configuration of tracing. Please see the details in +// base/trace_event/trace_config.h. +// +// startup_duration: The duration for startup tracing in terms of seconds. +// Tracing will stop automatically after the duration. If this +// value is not specified, the duration is 0 and one needs +// to stop tracing by other ways, e.g., by DevTools, or get +// the result file after shutting the browser down. +// +// result_file: The file that contains the trace log. The default result +// file path is chrometrace.log. Chrome will dump the trace +// log to this file +// 1) after startup_duration if it is specified; +// 2) or after browser shutdown if startup duration is 0. +// One can also stop tracing and get the result by other ways, +// e.g., by DevTools. In that case, the trace log will not be +// saved to this file. +// Notice: This is not supported on Android. The result file +// path will be generated by tracing controller. +// +// The trace config file can be specified by the --trace-config-file flag on +// most platforms except on Android, e.g., --trace-config-file=path/to/file/. +// This flag should not be used with --trace-startup or --trace-shutdown. If +// those two flags are used, --trace-config-file flag will be ignored. If the +// --trace-config-file flag is used without the file path, Chrome will do +// startup tracing with 5 seconds' startup duration. +// +// On Android, Chrome does not read the --trace-config-file flag, because not +// all Chrome based browsers read customized flag, e.g., Android WebView. Chrome +// on Android reads from a fixed file location: +// /data/local/chrome-trace-config.json +// If this file exists, Chrome will start tracing according to the configuration +// specified in the file, otherwise, Chrome will not start tracing. +class TRACING_EXPORT TraceConfigFile { + public: + static TraceConfigFile* GetInstance(); + + bool IsEnabled() const; + base::trace_event::TraceConfig GetTraceConfig() const; + int GetStartupDuration() const; +#if !defined(OS_ANDROID) + base::FilePath GetResultFile() const; +#endif + + private: + // This allows constructor and destructor to be private and usable only + // by the Singleton class. + friend struct base::DefaultSingletonTraits<TraceConfigFile>; + TraceConfigFile(); + ~TraceConfigFile(); + + bool ParseTraceConfigFileContent(const std::string& content); + + bool is_enabled_; + base::trace_event::TraceConfig trace_config_; + int startup_duration_; + base::FilePath result_file_; + + DISALLOW_COPY_AND_ASSIGN(TraceConfigFile); +}; + +} // namespace tracing + +#endif // COMPONENTS_TRACING_TRACE_CONFIG_FILE_H_ diff --git a/chromium/components/tracing/trace_config_file_unittest.cc b/chromium/components/tracing/trace_config_file_unittest.cc new file mode 100644 index 00000000000..d62c4d44217 --- /dev/null +++ b/chromium/components/tracing/trace_config_file_unittest.cc @@ -0,0 +1,220 @@ +// Copyright (c) 2015 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/at_exit.h" +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "components/tracing/trace_config_file.h" +#include "components/tracing/tracing_switches.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace tracing { + +namespace { + +const char kTraceConfig[] = + "{" + "\"enable_argument_filter\":true," + "\"enable_sampling\":true," + "\"enable_systrace\":true," + "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"]," + "\"included_categories\":[\"included\"," + "\"inc_pattern*\"," + "\"disabled-by-default-cc\"]," + "\"record_mode\":\"record-continuously\"," + "\"synthetic_delays\":[\"test.Delay1;16\",\"test.Delay2;32\"]" + "}"; + +std::string GetTraceConfigFileContent(std::string trace_config, + std::string startup_duration, + std::string result_file) { + std::string content = "{"; + if (!trace_config.empty()) + content += "\"trace_config\":" + trace_config; + + if (!startup_duration.empty()) { + if (content != "{") + content += ","; + content += "\"startup_duration\":" + startup_duration; + } + + if (!result_file.empty()) { + if (content != "{") + content += ","; + content += "\"result_file\":\"" + result_file + "\""; + } + + content += "}"; + return content; +} + +} // namespace + +TEST(TraceConfigFileTest, TraceStartupEnabled) { + base::ShadowingAtExitManager sem; + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kTraceStartup); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kTraceConfigFile); + + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +TEST(TraceConfigFileTest, TraceShutdownEnabled) { + base::ShadowingAtExitManager sem; + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kTraceShutdown); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kTraceConfigFile); + + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +TEST(TraceConfigFileTest, TraceConfigFileNotEnabled) { + base::ShadowingAtExitManager sem; + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +TEST(TraceConfigFileTest, TraceConfigFileEnabledWithoutPath) { + base::ShadowingAtExitManager sem; + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kTraceConfigFile); + + ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled()); + EXPECT_EQ(base::trace_event::TraceConfig().ToString(), + TraceConfigFile::GetInstance()->GetTraceConfig().ToString()); + EXPECT_EQ(5, TraceConfigFile::GetInstance()->GetStartupDuration()); + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("chrometrace.log")), + TraceConfigFile::GetInstance()->GetResultFile()); +} + +TEST(TraceConfigFileTest, TraceConfigFileEnabledWithInvalidPath) { + base::ShadowingAtExitManager sem; + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, + base::FilePath(FILE_PATH_LITERAL("invalid-trace-config-file-path"))); + + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +TEST(TraceConfigFileTest, ValidContent) { + base::ShadowingAtExitManager sem; + std::string content = GetTraceConfigFileContent( + kTraceConfig, "10", "trace_result_file.log"); + + base::FilePath trace_config_file; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ASSERT_TRUE( + base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file)); + ASSERT_NE(-1, base::WriteFile( + trace_config_file, content.c_str(), (int)content.length())); + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, trace_config_file); + + ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled()); + EXPECT_STREQ( + kTraceConfig, + TraceConfigFile::GetInstance()->GetTraceConfig().ToString().c_str()); + EXPECT_EQ(10, TraceConfigFile::GetInstance()->GetStartupDuration()); + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("trace_result_file.log")), + TraceConfigFile::GetInstance()->GetResultFile()); +} + +TEST(TraceConfigFileTest, ValidContentWithOnlyTraceConfig) { + base::ShadowingAtExitManager sem; + std::string content = GetTraceConfigFileContent(kTraceConfig, "", ""); + + base::FilePath trace_config_file; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ASSERT_TRUE( + base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file)); + ASSERT_NE(-1, base::WriteFile( + trace_config_file, content.c_str(), (int)content.length())); + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, trace_config_file); + + ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled()); + EXPECT_STREQ( + kTraceConfig, + TraceConfigFile::GetInstance()->GetTraceConfig().ToString().c_str()); + EXPECT_EQ(0, TraceConfigFile::GetInstance()->GetStartupDuration()); + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("chrometrace.log")), + TraceConfigFile::GetInstance()->GetResultFile()); +} + +TEST(TraceConfigFileTest, ContentWithNegtiveDuration) { + base::ShadowingAtExitManager sem; + std::string content = GetTraceConfigFileContent(kTraceConfig, "-1", ""); + + base::FilePath trace_config_file; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ASSERT_TRUE( + base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file)); + ASSERT_NE(-1, base::WriteFile( + trace_config_file, content.c_str(), (int)content.length())); + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, trace_config_file); + + ASSERT_TRUE(TraceConfigFile::GetInstance()->IsEnabled()); + EXPECT_STREQ( + kTraceConfig, + TraceConfigFile::GetInstance()->GetTraceConfig().ToString().c_str()); + EXPECT_EQ(0, TraceConfigFile::GetInstance()->GetStartupDuration()); + EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("chrometrace.log")), + TraceConfigFile::GetInstance()->GetResultFile()); +} + +TEST(TraceConfigFileTest, ContentWithoutTraceConfig) { + base::ShadowingAtExitManager sem; + std::string content = GetTraceConfigFileContent( + "", "10", "trace_result_file.log"); + + base::FilePath trace_config_file; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ASSERT_TRUE( + base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file)); + ASSERT_NE(-1, base::WriteFile( + trace_config_file, content.c_str(), (int)content.length())); + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, trace_config_file); + + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +TEST(TraceConfigFileTest, InvalidContent) { + base::ShadowingAtExitManager sem; + std::string content = "invalid trace config file content"; + + base::FilePath trace_config_file; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ASSERT_TRUE( + base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file)); + ASSERT_NE(-1, base::WriteFile( + trace_config_file, content.c_str(), (int)content.length())); + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, trace_config_file); + + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +TEST(TraceConfigFileTest, EmptyContent) { + base::ShadowingAtExitManager sem; + base::FilePath trace_config_file; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + ASSERT_TRUE( + base::CreateTemporaryFileInDir(temp_dir.path(), &trace_config_file)); + base::CommandLine::ForCurrentProcess()->AppendSwitchPath( + switches::kTraceConfigFile, trace_config_file); + + EXPECT_FALSE(TraceConfigFile::GetInstance()->IsEnabled()); +} + +} // namespace tracing diff --git a/chromium/components/tracing/tracing_export.h b/chromium/components/tracing/tracing_export.h new file mode 100644 index 00000000000..ac24e303bcd --- /dev/null +++ b/chromium/components/tracing/tracing_export.h @@ -0,0 +1,29 @@ +// Copyright 2015 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. + +#ifndef COMPONENTS_TRACING_TRACING_EXPORT_H_ +#define COMPONENTS_TRACING_TRACING_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(TRACING_IMPLEMENTATION) +#define TRACING_EXPORT __declspec(dllexport) +#else +#define TRACING_EXPORT __declspec(dllimport) +#endif // defined(TRACING_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(TRACING_IMPLEMENTATION) +#define TRACING_EXPORT __attribute__((visibility("default"))) +#else +#define TRACING_EXPORT +#endif // defined(TRACING_IMPLEMENTATION) +#endif + +#else // defined(COMPONENT_BUILD) +#define TRACING_EXPORT +#endif + +#endif // COMPONENTS_TRACING_TRACING_EXPORT_H_ diff --git a/chromium/components/tracing/tracing_messages.h b/chromium/components/tracing/tracing_messages.h index 88c7834064b..cd5a2020dda 100644 --- a/chromium/components/tracing/tracing_messages.h +++ b/chromium/components/tracing/tracing_messages.h @@ -7,14 +7,18 @@ #include <vector> #include "base/basictypes.h" +#include "base/metrics/histogram.h" #include "base/sync_socket.h" #include "base/trace_event/memory_dump_request_args.h" #include "base/trace_event/trace_event_impl.h" +#include "components/tracing/tracing_export.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_message_utils.h" #include "ipc/ipc_platform_file.h" +#undef IPC_MESSAGE_EXPORT +#define IPC_MESSAGE_EXPORT TRACING_EXPORT #define IPC_MESSAGE_START TracingMsgStart IPC_STRUCT_TRAITS_BEGIN(base::trace_event::TraceLogStatus) @@ -25,8 +29,16 @@ IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(base::trace_event::MemoryDumpRequestArgs) IPC_STRUCT_TRAITS_MEMBER(dump_guid) IPC_STRUCT_TRAITS_MEMBER(dump_type) +IPC_STRUCT_TRAITS_MEMBER(level_of_detail) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(base::trace_event::MemoryDumpArgs) + IPC_STRUCT_TRAITS_MEMBER(level_of_detail) +IPC_STRUCT_TRAITS_END() + +IPC_ENUM_TRAITS_MAX_VALUE(base::trace_event::MemoryDumpLevelOfDetail, + base::trace_event::MemoryDumpLevelOfDetail::LAST) + IPC_ENUM_TRAITS_MAX_VALUE( base::trace_event::MemoryDumpType, static_cast<int>(base::trace_event::MemoryDumpType::LAST)) @@ -75,6 +87,14 @@ IPC_MESSAGE_CONTROL2(TracingMsg_GlobalMemoryDumpResponse, uint64 /* dump_guid */, bool /* success */) +IPC_MESSAGE_CONTROL3(TracingMsg_SetUMACallback, + std::string /* histogram_name */, + base::HistogramBase::Sample /* histogram_lower_value */, + base::HistogramBase::Sample /* histogram_uppwer_value */) + +IPC_MESSAGE_CONTROL1(TracingMsg_ClearUMACallback, + std::string /* histogram_name */) + // Sent everytime when a watch event is matched. IPC_MESSAGE_CONTROL0(TracingHostMsg_WatchEventMatched) @@ -110,3 +130,6 @@ IPC_MESSAGE_CONTROL1(TracingHostMsg_GlobalMemoryDumpRequest, IPC_MESSAGE_CONTROL2(TracingHostMsg_ProcessMemoryDumpResponse, uint64 /* dump_guid */, bool /* success */) + +IPC_MESSAGE_CONTROL1(TracingHostMsg_TriggerBackgroundTrace, + std::string /* name */) diff --git a/chromium/components/tracing/tracing_switches.cc b/chromium/components/tracing/tracing_switches.cc new file mode 100644 index 00000000000..ba3c1b158fb --- /dev/null +++ b/chromium/components/tracing/tracing_switches.cc @@ -0,0 +1,52 @@ +// Copyright 2015 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 "components/tracing/tracing_switches.h" + +namespace switches { + +// Causes TRACE_EVENT flags to be recorded from startup. +// This flag will be ignored if --trace-startup or --trace-shutdown is provided. +const char kTraceConfigFile[] = "trace-config-file"; + +// Causes TRACE_EVENT flags to be recorded beginning with shutdown. Optionally, +// can specify the specific trace categories to include (e.g. +// --trace-shutdown=base,net) otherwise, all events are recorded. +// --trace-shutdown-file can be used to control where the trace log gets stored +// to since there is otherwise no way to access the result. +const char kTraceShutdown[] = "trace-shutdown"; + +// If supplied, sets the file which shutdown tracing will be stored into, if +// omitted the default will be used "chrometrace.log" in the current directory. +// Has no effect unless --trace-shutdown is also supplied. +// Example: --trace-shutdown --trace-shutdown-file=/tmp/trace_event.log +const char kTraceShutdownFile[] = "trace-shutdown-file"; + +// Causes TRACE_EVENT flags to be recorded from startup. Optionally, can +// specify the specific trace categories to include (e.g. +// --trace-startup=base,net) otherwise, all events are recorded. Setting this +// flag results in the first call to BeginTracing() to receive all trace events +// since startup. In Chrome, you may find --trace-startup-file and +// --trace-startup-duration to control the auto-saving of the trace (not +// supported in the base-only TraceLog component). +const char kTraceStartup[] = "trace-startup"; + +// Sets the time in seconds until startup tracing ends. If omitted a default of +// 5 seconds is used. Has no effect without --trace-startup, or if +// --startup-trace-file=none was supplied. +const char kTraceStartupDuration[] = "trace-startup-duration"; + +// If supplied, sets the file which startup tracing will be stored into, if +// omitted the default will be used "chrometrace.log" in the current directory. +// Has no effect unless --trace-startup is also supplied. +// Example: --trace-startup --trace-startup-file=/tmp/trace_event.log +// As a special case, can be set to 'none' - this disables automatically saving +// the result to a file and the first manually recorded trace will then receive +// all events since startup. +const char kTraceStartupFile[] = "trace-startup-file"; + +// Sets the target URL for uploading tracing data. +const char kTraceUploadURL[] = "trace-upload-url"; + +} // namespace switches diff --git a/chromium/components/tracing/tracing_switches.h b/chromium/components/tracing/tracing_switches.h new file mode 100644 index 00000000000..263a49bcf5c --- /dev/null +++ b/chromium/components/tracing/tracing_switches.h @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +#ifndef COMPONENTS_TRACING_TRACING_SWITCHES_H_ +#define COMPONENTS_TRACING_TRACING_SWITCHES_H_ + +#include "components/tracing/tracing_export.h" + +namespace switches { + +TRACING_EXPORT extern const char kTraceConfigFile[]; +TRACING_EXPORT extern const char kTraceShutdown[]; +TRACING_EXPORT extern const char kTraceShutdownFile[]; +TRACING_EXPORT extern const char kTraceStartup[]; +TRACING_EXPORT extern const char kTraceStartupDuration[]; +TRACING_EXPORT extern const char kTraceStartupFile[]; +TRACING_EXPORT extern const char kTraceUploadURL[]; + +} // namespace switches + +#endif // COMPONENTS_TRACING_TRACING_SWITCHES_H_ |