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 "base/metrics/metrics_hashes.h"
8 #include "base/no_destructor.h"
9 #include "base/profiler/stack_sampling_profiler.h"
10 #include "base/threading/thread_local.h"
11 #include "third_party/abseil-cpp/absl/types/optional.h"
12
13 namespace base {
14
15 namespace {
16
GetPlatformThreadIdForScope(SampleMetadataScope scope)17 absl::optional<PlatformThreadId> GetPlatformThreadIdForScope(
18 SampleMetadataScope scope) {
19 if (scope == SampleMetadataScope::kProcess)
20 return absl::nullopt;
21 return PlatformThread::CurrentId();
22 }
23
24 } // namespace
25
SampleMetadata(StringPiece name,SampleMetadataScope scope)26 SampleMetadata::SampleMetadata(StringPiece name, SampleMetadataScope scope)
27 : name_hash_(HashMetricName(name)), scope_(scope) {}
28
Set(int64_t value)29 void SampleMetadata::Set(int64_t value) {
30 GetSampleMetadataRecorder()->Set(name_hash_, absl::nullopt,
31 GetPlatformThreadIdForScope(scope_), value);
32 }
33
Set(int64_t key,int64_t value)34 void SampleMetadata::Set(int64_t key, int64_t value) {
35 GetSampleMetadataRecorder()->Set(name_hash_, key,
36 GetPlatformThreadIdForScope(scope_), value);
37 }
38
Remove()39 void SampleMetadata::Remove() {
40 GetSampleMetadataRecorder()->Remove(name_hash_, absl::nullopt,
41 GetPlatformThreadIdForScope(scope_));
42 }
43
Remove(int64_t key)44 void SampleMetadata::Remove(int64_t key) {
45 GetSampleMetadataRecorder()->Remove(name_hash_, key,
46 GetPlatformThreadIdForScope(scope_));
47 }
48
ScopedSampleMetadata(StringPiece name,int64_t value,SampleMetadataScope scope)49 ScopedSampleMetadata::ScopedSampleMetadata(StringPiece name,
50 int64_t value,
51 SampleMetadataScope scope)
52 : name_hash_(HashMetricName(name)),
53 thread_id_(GetPlatformThreadIdForScope(scope)) {
54 GetSampleMetadataRecorder()->Set(name_hash_, absl::nullopt, thread_id_,
55 value);
56 }
57
ScopedSampleMetadata(StringPiece name,int64_t key,int64_t value,SampleMetadataScope scope)58 ScopedSampleMetadata::ScopedSampleMetadata(StringPiece name,
59 int64_t key,
60 int64_t value,
61 SampleMetadataScope scope)
62 : name_hash_(HashMetricName(name)),
63 key_(key),
64 thread_id_(GetPlatformThreadIdForScope(scope)) {
65 GetSampleMetadataRecorder()->Set(name_hash_, key, thread_id_, value);
66 }
67
~ScopedSampleMetadata()68 ScopedSampleMetadata::~ScopedSampleMetadata() {
69 GetSampleMetadataRecorder()->Remove(name_hash_, key_, thread_id_);
70 }
71
72 // This function is friended by StackSamplingProfiler so must live directly in
73 // the base namespace.
ApplyMetadataToPastSamplesImpl(TimeTicks period_start,TimeTicks period_end,uint64_t name_hash,absl::optional<int64_t> key,int64_t value,absl::optional<PlatformThreadId> thread_id)74 void ApplyMetadataToPastSamplesImpl(
75 TimeTicks period_start,
76 TimeTicks period_end,
77 uint64_t name_hash,
78 absl::optional<int64_t> key,
79 int64_t value,
80 absl::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,StringPiece name,int64_t value,SampleMetadataScope scope)85 void ApplyMetadataToPastSamples(TimeTicks period_start,
86 TimeTicks period_end,
87 StringPiece name,
88 int64_t value,
89 SampleMetadataScope scope) {
90 return ApplyMetadataToPastSamplesImpl(
91 period_start, period_end, HashMetricName(name), absl::nullopt, value,
92 GetPlatformThreadIdForScope(scope));
93 }
94
ApplyMetadataToPastSamples(TimeTicks period_start,TimeTicks period_end,StringPiece name,int64_t key,int64_t value,SampleMetadataScope scope)95 void ApplyMetadataToPastSamples(TimeTicks period_start,
96 TimeTicks period_end,
97 StringPiece 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,absl::optional<PlatformThreadId> thread_id)106 void AddProfileMetadataImpl(uint64_t name_hash,
107 int64_t key,
108 int64_t value,
109 absl::optional<PlatformThreadId> thread_id) {
110 StackSamplingProfiler::AddProfileMetadata(name_hash, key, value, thread_id);
111 }
112
AddProfileMetadata(StringPiece name,int64_t key,int64_t value,SampleMetadataScope scope)113 void AddProfileMetadata(StringPiece 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