[tracing] Fix process type for cloned sessions.
When a session is cloned, OnStop isn't called and thus process descriptor doesn't have process type if it was set after the tracing session started. This brings back logic similar to https://chromium-review.googlesource.com/c/chromium/src/+/6163823 with a few difference: - process type is updated (whereas only the process name was previously set) - The descriptor is written by TrackNameRecorder - process labels are kept and emitted in TrackNameRecorder Change-Id: I65907390d8da74a34359cd2ff5d054a2d20d1be5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6298800 Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Cr-Commit-Position: refs/heads/main@{#1425303}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
93049ba857
commit
2a39a4e38e
base
content/renderer
services/tracing/public/cpp/perfetto
@ -106,8 +106,7 @@ const char* GetNameForProcessType(CurrentProcessType process_type) {
|
||||
// Used for logging histograms for IPC metrics based on their process type.
|
||||
ShortProcessType CurrentProcess::GetShortType(TypeKey key) {
|
||||
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
||||
CurrentProcessType process = static_cast<CurrentProcessType>(
|
||||
process_type_.load(std::memory_order_relaxed));
|
||||
CurrentProcessType process = process_type_.load(std::memory_order_relaxed);
|
||||
switch (process) {
|
||||
case CurrentProcessType::PROCESS_UNSPECIFIED:
|
||||
return ShortProcessType::kUnspecified;
|
||||
@ -184,12 +183,22 @@ void CurrentProcess::SetProcessType(CurrentProcessType process_type) {
|
||||
|
||||
void CurrentProcess::SetProcessNameAndType(const std::string& process_name,
|
||||
CurrentProcessType process_type) {
|
||||
Delegate* delegate;
|
||||
{
|
||||
AutoLock lock(lock_);
|
||||
process_name_ = process_name;
|
||||
process_type_.store(static_cast<CurrentProcessType>(process_type),
|
||||
std::memory_order_relaxed);
|
||||
process_type_.store(process_type, std::memory_order_relaxed);
|
||||
delegate = delegate_;
|
||||
}
|
||||
if (delegate) {
|
||||
delegate->OnProcessNameChanged(process_name, process_type);
|
||||
}
|
||||
}
|
||||
|
||||
void CurrentProcess::SetDelegate(Delegate* delegate, NameKey) {
|
||||
AutoLock lock(lock_);
|
||||
DCHECK(delegate == nullptr || delegate_ == nullptr);
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
@ -18,7 +19,7 @@
|
||||
namespace tracing {
|
||||
class TraceEventDataSource;
|
||||
class CustomEventRecorder;
|
||||
void SetProcessTrackDescriptor(int64_t process_start_timestamp);
|
||||
class TrackNameRecorder;
|
||||
} // namespace tracing
|
||||
|
||||
namespace mojo::core {
|
||||
@ -75,8 +76,7 @@ class BASE_EXPORT CurrentProcess {
|
||||
friend class ::base::test::CurrentProcessForTest;
|
||||
friend class ::tracing::TraceEventDataSource;
|
||||
friend class ::tracing::CustomEventRecorder;
|
||||
friend void ::tracing::SetProcessTrackDescriptor(
|
||||
int64_t process_start_timestamp);
|
||||
friend class ::tracing::TrackNameRecorder;
|
||||
friend class ::mojo::core::Channel;
|
||||
};
|
||||
// Returns an enum corresponding to the type of the current process (e.g.
|
||||
@ -89,8 +89,7 @@ class BASE_EXPORT CurrentProcess {
|
||||
// "browser" or "renderer" process), the access to this function is controlled
|
||||
// by an explicit list.
|
||||
CurrentProcessType GetType(TypeKey key) {
|
||||
return static_cast<CurrentProcessType>(
|
||||
process_type_.load(std::memory_order_relaxed));
|
||||
return process_type_.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
ShortProcessType GetShortType(TypeKey key);
|
||||
@ -100,22 +99,34 @@ class BASE_EXPORT CurrentProcess {
|
||||
NameKey() = default;
|
||||
friend class ::base::test::CurrentProcessForTest;
|
||||
friend class ::tracing::TraceEventDataSource;
|
||||
friend void ::tracing::SetProcessTrackDescriptor(
|
||||
int64_t process_start_timestamp);
|
||||
friend class ::tracing::TrackNameRecorder;
|
||||
};
|
||||
std::string GetName(NameKey key) {
|
||||
AutoLock lock(lock_);
|
||||
return process_name_;
|
||||
}
|
||||
|
||||
class BASE_EXPORT Delegate {
|
||||
public:
|
||||
// Called on the main thread of the process whose name is changing,
|
||||
// immediately after the name is set.
|
||||
virtual void OnProcessNameChanged(const std::string& process_name,
|
||||
CurrentProcessType process_type) = 0;
|
||||
|
||||
protected:
|
||||
~Delegate() = default;
|
||||
};
|
||||
|
||||
// Sets the name and type of the process for the metrics and tracing. This
|
||||
// function should be called as early as possible in the process's lifetime
|
||||
// before starting any threads, typically in *Main() function. Provide
|
||||
// process_name as an argument if it can't be trivially derived from the
|
||||
// process type.
|
||||
void SetProcessType(CurrentProcessType process_type);
|
||||
void SetProcessNameAndType(const std::string& process_name,
|
||||
CurrentProcessType process_type);
|
||||
|
||||
// `delegate` might racily be invoked after resetting, thus its lifetime must
|
||||
// match `CurrentProcess`.
|
||||
void SetDelegate(Delegate* delegate, NameKey key);
|
||||
|
||||
bool IsProcessNameEmpty() const {
|
||||
AutoLock lock(lock_);
|
||||
@ -127,6 +138,9 @@ class BASE_EXPORT CurrentProcess {
|
||||
|
||||
CurrentProcess() = default;
|
||||
|
||||
void SetProcessNameAndType(const std::string& process_name,
|
||||
CurrentProcessType process_type);
|
||||
|
||||
mutable Lock lock_;
|
||||
std::string process_name_;
|
||||
// The process_type_ is set at the startup before processes start running.
|
||||
@ -136,6 +150,8 @@ class BASE_EXPORT CurrentProcess {
|
||||
// where we don't have a guarantee that it will be called early enough in the
|
||||
// process's lifetime, thus we use std::atomic here.
|
||||
std::atomic<CurrentProcessType> process_type_;
|
||||
|
||||
raw_ptr<Delegate> delegate_;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
@ -348,7 +348,7 @@ struct TraceLog::RegisteredAsyncObserver {
|
||||
|
||||
// static
|
||||
TraceLog* TraceLog::GetInstance() {
|
||||
static base::NoDestructor<TraceLog> instance(0);
|
||||
static base::NoDestructor<TraceLog> instance{};
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ void TraceLog::ResetForTesting() {
|
||||
self->InitializePerfettoIfNeeded();
|
||||
}
|
||||
|
||||
TraceLog::TraceLog(int generation) : process_id_(base::kNullProcessId) {
|
||||
TraceLog::TraceLog() : process_id_(base::kNullProcessId) {
|
||||
#if BUILDFLAG(IS_NACL) // NaCl shouldn't expose the process id.
|
||||
SetProcessID(0);
|
||||
#else
|
||||
@ -763,26 +763,6 @@ void TraceLog::SetProcessID(ProcessId process_id) {
|
||||
process_id_ = process_id;
|
||||
}
|
||||
|
||||
int TraceLog::GetNewProcessLabelId() {
|
||||
AutoLock lock(lock_);
|
||||
return next_process_label_id_++;
|
||||
}
|
||||
|
||||
void TraceLog::UpdateProcessLabel(int label_id,
|
||||
const std::string& current_label) {
|
||||
if (!current_label.length()) {
|
||||
return RemoveProcessLabel(label_id);
|
||||
}
|
||||
|
||||
AutoLock lock(lock_);
|
||||
process_labels_[label_id] = current_label;
|
||||
}
|
||||
|
||||
void TraceLog::RemoveProcessLabel(int label_id) {
|
||||
AutoLock lock(lock_);
|
||||
process_labels_.erase(label_id);
|
||||
}
|
||||
|
||||
size_t TraceLog::GetObserverCountForTest() const {
|
||||
AutoLock lock(observers_lock_);
|
||||
return enabled_state_observers_.size();
|
||||
|
@ -174,23 +174,12 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver {
|
||||
|
||||
ProcessId process_id() const { return process_id_; }
|
||||
|
||||
std::unordered_map<int, std::string> process_labels() const {
|
||||
AutoLock lock(lock_);
|
||||
return process_labels_;
|
||||
}
|
||||
|
||||
// Exposed for unittesting:
|
||||
// Allows clearing up our singleton instance.
|
||||
static void ResetForTesting();
|
||||
|
||||
void SetProcessID(ProcessId process_id);
|
||||
|
||||
// Processes can have labels in addition to their names. Use labels, for
|
||||
// instance, to list out the web page titles that a process is handling.
|
||||
int GetNewProcessLabelId();
|
||||
void UpdateProcessLabel(int label_id, const std::string& current_label);
|
||||
void RemoveProcessLabel(int label_id);
|
||||
|
||||
size_t GetObserverCountForTest() const;
|
||||
|
||||
struct TrackEventSession {
|
||||
@ -221,7 +210,7 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver {
|
||||
|
||||
struct RegisteredAsyncObserver;
|
||||
|
||||
explicit TraceLog(int generation);
|
||||
explicit TraceLog();
|
||||
~TraceLog() override;
|
||||
|
||||
void SetDisabledWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||
@ -248,9 +237,6 @@ class BASE_EXPORT TraceLog : public perfetto::TrackEventSessionObserver {
|
||||
std::vector<std::unique_ptr<EnabledStateObserver>>
|
||||
owned_enabled_state_observer_copy_ GUARDED_BY(observers_lock_);
|
||||
|
||||
int next_process_label_id_ GUARDED_BY(lock_) = 0;
|
||||
std::unordered_map<int, std::string> process_labels_;
|
||||
|
||||
ProcessId process_id_;
|
||||
|
||||
// Set when asynchronous Flush is in progress.
|
||||
|
@ -142,6 +142,7 @@
|
||||
#include "services/network/public/mojom/url_loader_factory.mojom.h"
|
||||
#include "services/network/public/mojom/url_response_head.mojom.h"
|
||||
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
|
||||
#include "services/tracing/public/cpp/perfetto/track_name_recorder.h"
|
||||
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
|
||||
#include "third_party/blink/public/common/chrome_debug_urls.h"
|
||||
@ -1920,7 +1921,7 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params)
|
||||
routing_id_(params.routing_id),
|
||||
#endif
|
||||
process_label_id_(
|
||||
base::trace_event::TraceLog::GetInstance()->GetNewProcessLabelId()),
|
||||
tracing::TrackNameRecorder::GetInstance()->GetNewProcessLabelId()),
|
||||
selection_text_offset_(0),
|
||||
selection_range_(gfx::Range::InvalidRange()),
|
||||
render_accessibility_manager_(
|
||||
@ -1984,7 +1985,7 @@ RenderFrameImpl::~RenderFrameImpl() {
|
||||
if (initialized_ && is_main_frame_)
|
||||
MainFrameCounter::DecrementCount();
|
||||
|
||||
base::trace_event::TraceLog::GetInstance()->RemoveProcessLabel(
|
||||
tracing::TrackNameRecorder::GetInstance()->RemoveProcessLabel(
|
||||
process_label_id_);
|
||||
#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC)
|
||||
g_routing_id_frame_map.Get().erase(routing_id_);
|
||||
@ -4217,7 +4218,7 @@ void RenderFrameImpl::RunScriptsAtDocumentElementAvailable() {
|
||||
void RenderFrameImpl::DidReceiveTitle(const blink::WebString& title) {
|
||||
// Ignore all but top level navigations.
|
||||
if (!frame_->Parent() && !title.IsEmpty()) {
|
||||
base::trace_event::TraceLog::GetInstance()->UpdateProcessLabel(
|
||||
tracing::TrackNameRecorder::GetInstance()->UpdateProcessLabel(
|
||||
process_label_id_, title.Utf8());
|
||||
} else {
|
||||
// Set process title for sub-frames and title-less frames in traces.
|
||||
@ -4229,7 +4230,7 @@ void RenderFrameImpl::DidReceiveTitle(const blink::WebString& title) {
|
||||
frame_title += "Subframe: ";
|
||||
}
|
||||
frame_title += loading_url.DeprecatedGetOriginAsURL().spec();
|
||||
base::trace_event::TraceLog::GetInstance()->UpdateProcessLabel(
|
||||
tracing::TrackNameRecorder::GetInstance()->UpdateProcessLabel(
|
||||
process_label_id_, frame_title);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "build/build_config.h"
|
||||
#include "services/tracing/public/cpp/perfetto/trace_string_lookup.h"
|
||||
#include "third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h"
|
||||
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
|
||||
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_thread_descriptor.gen.h"
|
||||
#include "third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h"
|
||||
#include "third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h"
|
||||
@ -23,71 +22,27 @@
|
||||
|
||||
namespace tracing {
|
||||
|
||||
// Set the track descriptor for the current process.
|
||||
void SetProcessTrackDescriptor(int64_t process_start_timestamp) {
|
||||
using perfetto::protos::gen::ChromeProcessDescriptor;
|
||||
|
||||
const auto* trace_log = base::trace_event::TraceLog::GetInstance();
|
||||
int process_id = trace_log->process_id();
|
||||
std::string process_name = base::CurrentProcess::GetInstance().GetName({});
|
||||
auto process_type = static_cast<ChromeProcessDescriptor::ProcessType>(
|
||||
base::CurrentProcess::GetInstance().GetType({}));
|
||||
|
||||
// We record a few (string) fields here that are stripped for background
|
||||
// tracing. We rely on the post-process privacy filtering to remove them.
|
||||
auto process_track = perfetto::ProcessTrack::Current();
|
||||
auto process_track_desc = process_track.Serialize();
|
||||
auto* process = process_track_desc.mutable_process();
|
||||
process->set_pid(process_id);
|
||||
process->set_process_name(process_name);
|
||||
process->set_start_timestamp_ns(process_start_timestamp);
|
||||
for (const auto& label : trace_log->process_labels()) {
|
||||
process->add_process_labels(label.second);
|
||||
}
|
||||
|
||||
auto* chrome_process = process_track_desc.mutable_chrome_process();
|
||||
if (process_type != ChromeProcessDescriptor::PROCESS_UNSPECIFIED) {
|
||||
chrome_process->set_process_type(process_type);
|
||||
}
|
||||
|
||||
// Add the crash trace ID to all the traces uploaded. If there are crashes
|
||||
// during this tracing session, then the crash will contain the process's
|
||||
// trace ID as "chrome-trace-id" crash key. This should be emitted
|
||||
// periodically to ensure it is present in the traces when the process
|
||||
// crashes. Metadata can go missing if process crashes. So, record this in
|
||||
// process descriptor.
|
||||
static const std::optional<uint64_t> crash_trace_id = GetTraceCrashId();
|
||||
if (crash_trace_id) {
|
||||
chrome_process->set_crash_trace_id(*crash_trace_id);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
// Host app package name is only recorded if the corresponding TraceLog
|
||||
// setting is set to true.
|
||||
if (trace_log->ShouldRecordHostAppPackageName()) {
|
||||
// Host app package name is used to group information from different
|
||||
// processes that "belong" to the same WebView app.
|
||||
if (process_type == ChromeProcessDescriptor::PROCESS_RENDERER ||
|
||||
process_type == ChromeProcessDescriptor::PROCESS_BROWSER) {
|
||||
chrome_process->set_host_app_package_name(
|
||||
base::android::BuildInfo::GetInstance()->host_package_name());
|
||||
}
|
||||
}
|
||||
#endif // BUILDFLAG(IS_ANDROID)
|
||||
|
||||
base::TrackEvent::SetTrackDescriptor(process_track,
|
||||
std::move(process_track_desc));
|
||||
}
|
||||
using perfetto::protos::gen::ChromeProcessDescriptor;
|
||||
|
||||
namespace {
|
||||
|
||||
std::optional<uint64_t> GetTraceCrashId() {
|
||||
static base::debug::CrashKeyString* key = base::debug::AllocateCrashKeyString(
|
||||
"chrome-trace-id", base::debug::CrashKeySize::Size32);
|
||||
if (!key) {
|
||||
return std::nullopt;
|
||||
}
|
||||
uint64_t id = base::RandUint64();
|
||||
base::debug::SetCrashKeyString(key, base::NumberToString(id));
|
||||
return id;
|
||||
}
|
||||
|
||||
void FillThreadTrack(const perfetto::ThreadTrack& track, const char* name) {
|
||||
using perfetto::protos::gen::ChromeThreadDescriptor;
|
||||
|
||||
int process_id = static_cast<int>(
|
||||
base::trace_event::TraceLog::GetInstance()->process_id());
|
||||
auto desc = track.Serialize();
|
||||
desc.mutable_thread()->set_pid(process_id);
|
||||
desc.mutable_thread()->set_pid(static_cast<int>(
|
||||
base::trace_event::TraceLog::GetInstance()->process_id()));
|
||||
desc.mutable_thread()->set_thread_name(name);
|
||||
auto thread_type =
|
||||
static_cast<ChromeThreadDescriptor::ThreadType>(GetThreadType(name));
|
||||
@ -117,23 +72,64 @@ void SetThreadTrackDescriptors() {
|
||||
auto thread_track = perfetto::ThreadTrack::Current();
|
||||
FillThreadTrack(thread_track, thread_name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::optional<uint64_t> GetTraceCrashId() {
|
||||
static base::debug::CrashKeyString* key = base::debug::AllocateCrashKeyString(
|
||||
"chrome-trace-id", base::debug::CrashKeySize::Size32);
|
||||
if (!key) {
|
||||
return std::nullopt;
|
||||
void TrackNameRecorder::SetProcessTrackDescriptor(
|
||||
const std::string& process_name,
|
||||
ChromeProcessDescriptor::ProcessType process_type) {
|
||||
// We record a few (string) fields here that are stripped for background
|
||||
// tracing. We rely on the post-process privacy filtering to remove them.
|
||||
auto process_track = perfetto::ProcessTrack::Current();
|
||||
auto process_track_desc = process_track.Serialize();
|
||||
auto* process = process_track_desc.mutable_process();
|
||||
process->set_pid(base::trace_event::TraceLog::GetInstance()->process_id());
|
||||
process->set_process_name(process_name);
|
||||
process->set_start_timestamp_ns(process_start_timestamp_);
|
||||
for (const auto& label : process_labels()) {
|
||||
process->add_process_labels(label.second);
|
||||
}
|
||||
uint64_t id = base::RandUint64();
|
||||
base::debug::SetCrashKeyString(key, base::NumberToString(id));
|
||||
return id;
|
||||
|
||||
auto* chrome_process = process_track_desc.mutable_chrome_process();
|
||||
if (process_type != ChromeProcessDescriptor::PROCESS_UNSPECIFIED) {
|
||||
chrome_process->set_process_type(process_type);
|
||||
}
|
||||
|
||||
// Add the crash trace ID to all the traces uploaded. If there are crashes
|
||||
// during this tracing session, then the crash will contain the process's
|
||||
// trace ID as "chrome-trace-id" crash key. This should be emitted
|
||||
// periodically to ensure it is present in the traces when the process
|
||||
// crashes. Metadata can go missing if process crashes. So, record this in
|
||||
// process descriptor.
|
||||
static const std::optional<uint64_t> crash_trace_id = GetTraceCrashId();
|
||||
if (crash_trace_id) {
|
||||
chrome_process->set_crash_trace_id(*crash_trace_id);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
// Host app package name is only recorded if the corresponding TraceLog
|
||||
// setting is set to true.
|
||||
if (base::trace_event::TraceLog::GetInstance()
|
||||
->ShouldRecordHostAppPackageName()) {
|
||||
// Host app package name is used to group information from different
|
||||
// processes that "belong" to the same WebView app.
|
||||
if (process_type == ChromeProcessDescriptor::PROCESS_RENDERER ||
|
||||
process_type == ChromeProcessDescriptor::PROCESS_BROWSER) {
|
||||
chrome_process->set_host_app_package_name(
|
||||
base::android::BuildInfo::GetInstance()->host_package_name());
|
||||
}
|
||||
}
|
||||
#endif // BUILDFLAG(IS_ANDROID)
|
||||
|
||||
base::TrackEvent::SetTrackDescriptor(process_track,
|
||||
std::move(process_track_desc));
|
||||
}
|
||||
|
||||
TrackNameRecorder::TrackNameRecorder()
|
||||
: process_start_timestamp_(
|
||||
TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds()) {
|
||||
base::ThreadIdNameManager::GetInstance()->AddObserver(this);
|
||||
base::CurrentProcess::GetInstance().SetDelegate(this, {});
|
||||
base::TrackEvent::AddSessionObserver(this);
|
||||
SetThreadTrackDescriptors();
|
||||
}
|
||||
@ -147,11 +143,11 @@ TrackNameRecorder* TrackNameRecorder::GetInstance() {
|
||||
}
|
||||
|
||||
void TrackNameRecorder::OnSetup(const perfetto::DataSourceBase::SetupArgs&) {
|
||||
SetProcessTrackDescriptor(process_start_timestamp_);
|
||||
SetProcessTrackDescriptor();
|
||||
}
|
||||
|
||||
void TrackNameRecorder::OnStop(const perfetto::DataSourceBase::StopArgs&) {
|
||||
SetProcessTrackDescriptor(process_start_timestamp_);
|
||||
SetProcessTrackDescriptor();
|
||||
}
|
||||
|
||||
void TrackNameRecorder::OnThreadNameChanged(const char* name) {
|
||||
@ -159,4 +155,49 @@ void TrackNameRecorder::OnThreadNameChanged(const char* name) {
|
||||
// never happen outside of tests.
|
||||
FillThreadTrack(perfetto::ThreadTrack::Current(), name);
|
||||
}
|
||||
|
||||
void TrackNameRecorder::OnProcessNameChanged(
|
||||
const std::string& process_name,
|
||||
base::CurrentProcessType process_type) {
|
||||
if (perfetto::Tracing::IsInitialized()) {
|
||||
SetProcessTrackDescriptor(
|
||||
process_name,
|
||||
static_cast<ChromeProcessDescriptor::ProcessType>(process_type));
|
||||
}
|
||||
}
|
||||
|
||||
int TrackNameRecorder::GetNewProcessLabelId() {
|
||||
base::AutoLock lock(lock_);
|
||||
return next_process_label_id_++;
|
||||
}
|
||||
|
||||
void TrackNameRecorder::UpdateProcessLabel(int label_id,
|
||||
const std::string& current_label) {
|
||||
if (!current_label.length()) {
|
||||
return RemoveProcessLabel(label_id);
|
||||
}
|
||||
|
||||
if (perfetto::Tracing::IsInitialized()) {
|
||||
auto track = perfetto::ProcessTrack::Current();
|
||||
auto desc = track.Serialize();
|
||||
desc.mutable_process()->add_process_labels(current_label);
|
||||
base::TrackEvent::SetTrackDescriptor(track, std::move(desc));
|
||||
}
|
||||
|
||||
base::AutoLock lock(lock_);
|
||||
process_labels_[label_id] = current_label;
|
||||
}
|
||||
|
||||
void TrackNameRecorder::RemoveProcessLabel(int label_id) {
|
||||
base::AutoLock lock(lock_);
|
||||
process_labels_.erase(label_id);
|
||||
}
|
||||
|
||||
void TrackNameRecorder::SetProcessTrackDescriptor() {
|
||||
std::string process_name = base::CurrentProcess::GetInstance().GetName({});
|
||||
auto process_type = static_cast<ChromeProcessDescriptor::ProcessType>(
|
||||
base::CurrentProcess::GetInstance().GetType({}));
|
||||
SetProcessTrackDescriptor(process_name, process_type);
|
||||
}
|
||||
|
||||
} // namespace tracing
|
||||
|
@ -6,20 +6,23 @@
|
||||
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACK_NAME_RECORDER_H_
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/process/current_process.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "base/threading/thread_id_name_manager.h"
|
||||
#include "base/trace_event/trace_config.h"
|
||||
#include "base/trace_event/typed_macros.h"
|
||||
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
|
||||
#include "third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h"
|
||||
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
|
||||
|
||||
namespace tracing {
|
||||
|
||||
std::optional<uint64_t> GetTraceCrashId();
|
||||
|
||||
// A class that emits track descriptors for Chrome processes and threads.
|
||||
class COMPONENT_EXPORT(TRACING_CPP) TrackNameRecorder
|
||||
: public perfetto::TrackEventSessionObserver,
|
||||
base::ThreadIdNameManager::Observer {
|
||||
base::ThreadIdNameManager::Observer,
|
||||
base::CurrentProcess::Delegate {
|
||||
public:
|
||||
static TrackNameRecorder* GetInstance();
|
||||
|
||||
@ -33,13 +36,42 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackNameRecorder
|
||||
// base::ThreadIdNameManager::Observer implementation.
|
||||
void OnThreadNameChanged(const char* name) override;
|
||||
|
||||
// base::CurrentProcess::Delegate implementation.
|
||||
void OnProcessNameChanged(const std::string& process_name,
|
||||
base::CurrentProcessType process_type) override;
|
||||
|
||||
// Processes can have labels in addition to their names. Use labels, for
|
||||
// instance, to list out the web page titles that a process is handling.
|
||||
int GetNewProcessLabelId();
|
||||
void UpdateProcessLabel(int label_id, const std::string& current_label);
|
||||
void RemoveProcessLabel(int label_id);
|
||||
|
||||
private:
|
||||
friend class base::NoDestructor<TrackNameRecorder>;
|
||||
using ChromeProcessDescriptor =
|
||||
perfetto::protos::gen::ChromeProcessDescriptor;
|
||||
|
||||
TrackNameRecorder();
|
||||
~TrackNameRecorder() override;
|
||||
|
||||
uint64_t process_start_timestamp_;
|
||||
// Set the track descriptor for the current process.
|
||||
void SetProcessTrackDescriptor(
|
||||
const std::string& process_name,
|
||||
ChromeProcessDescriptor::ProcessType process_type);
|
||||
void SetProcessTrackDescriptor();
|
||||
|
||||
absl::flat_hash_map<int, std::string> process_labels() const {
|
||||
base::AutoLock lock(lock_);
|
||||
return process_labels_;
|
||||
}
|
||||
|
||||
int64_t process_start_timestamp_;
|
||||
|
||||
// This lock protects `process_labels_` member accesses from arbitrary
|
||||
// threads.
|
||||
mutable base::Lock lock_;
|
||||
int next_process_label_id_ GUARDED_BY(lock_) = 0;
|
||||
absl::flat_hash_map<int, std::string> process_labels_ GUARDED_BY(lock_);
|
||||
};
|
||||
|
||||
} // namespace tracing
|
||||
|
Reference in New Issue
Block a user