1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/profiler/sample_metadata.h"
6
7 #include <optional>
8 #include <string_view>
9
10 #include "base/metrics/metrics_hashes.h"
11 #include "base/no_destructor.h"
12 #include "base/profiler/stack_sampling_profiler.h"
13 #include "base/threading/thread_local.h"
14
15 namespace base {
16
17 namespace {
18
GetPlatformThreadIdForScope(SampleMetadataScope scope)19 std::optional<PlatformThreadId> GetPlatformThreadIdForScope(
20 SampleMetadataScope scope) {
21 if (scope == SampleMetadataScope::kProcess)
22 return std::nullopt;
23 return PlatformThread::CurrentId();
24 }
25
26 } // namespace
27
SampleMetadata(std::string_view name,SampleMetadataScope scope)28 SampleMetadata::SampleMetadata(std::string_view name, SampleMetadataScope scope)
29 : name_hash_(HashMetricName(name)), scope_(scope) {}
30
Set(int64_t value)31 void SampleMetadata::Set(int64_t value) {
32 GetSampleMetadataRecorder()->Set(name_hash_, std::nullopt,
33 GetPlatformThreadIdForScope(scope_), value);
34 }
35
Set(int64_t key,int64_t value)36 void SampleMetadata::Set(int64_t key, int64_t value) {
37 GetSampleMetadataRecorder()->Set(name_hash_, key,
38 GetPlatformThreadIdForScope(scope_), value);
39 }
40
Remove()41 void SampleMetadata::Remove() {
42 GetSampleMetadataRecorder()->Remove(name_hash_, std::nullopt,
43 GetPlatformThreadIdForScope(scope_));
44 }
45
Remove(int64_t key)46 void SampleMetadata::Remove(int64_t key) {
47 GetSampleMetadataRecorder()->Remove(name_hash_, key,
48 GetPlatformThreadIdForScope(scope_));
49 }
50
ScopedSampleMetadata(std::string_view name,int64_t value,SampleMetadataScope scope)51 ScopedSampleMetadata::ScopedSampleMetadata(std::string_view name,
52 int64_t value,
53 SampleMetadataScope scope)
54 : name_hash_(HashMetricName(name)),
55 thread_id_(GetPlatformThreadIdForScope(scope)) {
56 GetSampleMetadataRecorder()->Set(name_hash_, std::nullopt, thread_id_, value);
57 }
58
ScopedSampleMetadata(std::string_view name,int64_t key,int64_t value,SampleMetadataScope scope)59 ScopedSampleMetadata::ScopedSampleMetadata(std::string_view name,
60 int64_t key,
61 int64_t value,
62 SampleMetadataScope scope)
63 : name_hash_(HashMetricName(name)),
64 key_(key),
65 thread_id_(GetPlatformThreadIdForScope(scope)) {
66 GetSampleMetadataRecorder()->Set(name_hash_, key, thread_id_, value);
67 }
68
~ScopedSampleMetadata()69 ScopedSampleMetadata::~ScopedSampleMetadata() {
70 GetSampleMetadataRecorder()->Remove(name_hash_, key_, thread_id_);
71 }
72
73 // This function is friended by StackSamplingProfiler so must live directly in
74 // the base namespace.
ApplyMetadataToPastSamplesImpl(TimeTicks period_start,TimeTicks period_end,uint64_t name_hash,std::optional<int64_t> key,int64_t value,std::optional<PlatformThreadId> thread_id)75 void ApplyMetadataToPastSamplesImpl(TimeTicks period_start,
76 TimeTicks period_end,
77 uint64_t name_hash,
78 std::optional<int64_t> key,
79 int64_t value,
80 std::optional<PlatformThreadId> thread_id) {
81 StackSamplingProfiler::ApplyMetadataToPastSamples(
82 period_start, period_end, name_hash, key, value, thread_id);
83 }
84
ApplyMetadataToPastSamples(TimeTicks period_start,TimeTicks period_end,std::string_view name,int64_t value,SampleMetadataScope scope)85 void ApplyMetadataToPastSamples(TimeTicks period_start,
86 TimeTicks period_end,
87 std::string_view name,
88 int64_t value,
89 SampleMetadataScope scope) {
90 return ApplyMetadataToPastSamplesImpl(
91 period_start, period_end, HashMetricName(name), std::nullopt, value,
92 GetPlatformThreadIdForScope(scope));
93 }
94
ApplyMetadataToPastSamples(TimeTicks period_start,TimeTicks period_end,std::string_view name,int64_t key,int64_t value,SampleMetadataScope scope)95 void ApplyMetadataToPastSamples(TimeTicks period_start,
96 TimeTicks period_end,
97 std::string_view name,
98 int64_t key,
99 int64_t value,
100 SampleMetadataScope scope) {
101 return ApplyMetadataToPastSamplesImpl(period_start, period_end,
102 HashMetricName(name), key, value,
103 GetPlatformThreadIdForScope(scope));
104 }
105
AddProfileMetadataImpl(uint64_t name_hash,int64_t key,int64_t value,std::optional<PlatformThreadId> thread_id)106 void AddProfileMetadataImpl(uint64_t name_hash,
107 int64_t key,
108 int64_t value,
109 std::optional<PlatformThreadId> thread_id) {
110 StackSamplingProfiler::AddProfileMetadata(name_hash, key, value, thread_id);
111 }
112
AddProfileMetadata(std::string_view name,int64_t key,int64_t value,SampleMetadataScope scope)113 void AddProfileMetadata(std::string_view name,
114 int64_t key,
115 int64_t value,
116 SampleMetadataScope scope) {
117 return AddProfileMetadataImpl(HashMetricName(name), key, value,
118 GetPlatformThreadIdForScope(scope));
119 }
120
GetSampleMetadataRecorder()121 MetadataRecorder* GetSampleMetadataRecorder() {
122 static NoDestructor<MetadataRecorder> instance;
123 return instance.get();
124 }
125
126 } // namespace base
127