1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/ftrace/iostat_tracker.h"
18
19 #include <cstdint>
20 #include <string>
21
22 #include "perfetto/ext/base/string_utils.h"
23 #include "perfetto/ext/base/string_view.h"
24 #include "perfetto/protozero/field.h"
25 #include "protos/perfetto/trace/ftrace/f2fs.pbzero.h"
26 #include "src/trace_processor/importers/common/event_tracker.h"
27 #include "src/trace_processor/importers/common/track_tracker.h"
28 #include "src/trace_processor/importers/common/tracks.h"
29 #include "src/trace_processor/importers/common/tracks_common.h"
30 #include "src/trace_processor/storage/trace_storage.h"
31
32 namespace perfetto::trace_processor {
33
34 namespace {
35
GetRawDeviceName(uint64_t dev_num)36 std::string GetRawDeviceName(uint64_t dev_num) {
37 return std::to_string((dev_num & 0xFF00) >> 8) + ":" +
38 std::to_string(dev_num & 0xFF);
39 }
40
41 } // namespace
42
IostatTracker(TraceProcessorContext * context)43 IostatTracker::IostatTracker(TraceProcessorContext* context)
44 : context_(context) {}
45
ParseF2fsIostat(int64_t timestamp,protozero::ConstBytes blob)46 void IostatTracker::ParseF2fsIostat(int64_t timestamp,
47 protozero::ConstBytes blob) {
48 protos::pbzero::F2fsIostatFtraceEvent::Decoder evt(blob);
49
50 static constexpr auto kBlueprint = tracks::CounterBlueprint(
51 "f2fs_iostat", tracks::UnknownUnitBlueprint(),
52 tracks::DimensionBlueprints(
53 tracks::kLinuxDeviceDimensionBlueprint,
54 tracks::StringDimensionBlueprint("counter_key")),
55 tracks::FnNameBlueprint(
56 [](base::StringView device, base::StringView name) {
57 return base::StackString<1024>("f2fs_iostat.[%.*s].%.*s",
58 int(device.size()), device.data(),
59 int(name.size()), name.data());
60 }));
61
62 auto push_counter = [&, this](const char* counter_name, uint64_t value) {
63 TrackId track = context_->track_tracker->InternTrack(
64 kBlueprint,
65 tracks::DimensionBlueprints(
66 base::StringView(GetRawDeviceName(evt.dev())), counter_name));
67 context_->event_tracker->PushCounter(timestamp, static_cast<double>(value),
68 track);
69 };
70 push_counter("write_app_total", evt.app_wio());
71 push_counter("write_app_direct", evt.app_dio());
72 push_counter("write_app_buffered", evt.app_bio());
73 push_counter("write_app_mapped", evt.app_mio());
74 push_counter("write_fs_data", evt.fs_dio());
75 push_counter("write_fs_node", evt.fs_nio());
76 push_counter("write_fs_meta", evt.fs_mio());
77 push_counter("write_gc_data", evt.fs_gc_dio());
78 push_counter("write_gc_node", evt.fs_gc_nio());
79 push_counter("write_cp_data", evt.fs_cp_dio());
80 push_counter("write_cp_node", evt.fs_cp_nio());
81 push_counter("write_cp_meta", evt.fs_cp_mio());
82 push_counter("read_app_total", evt.app_rio());
83 push_counter("read_app_direct", evt.app_drio());
84 push_counter("read_app_buffered", evt.app_brio());
85 push_counter("read_app_mapped", evt.app_mrio());
86 push_counter("read_fs_data", evt.fs_drio());
87 push_counter("read_fs_gdata", evt.fs_gdrio());
88 push_counter("read_fs_cdata", evt.fs_cdrio());
89 push_counter("read_fs_node", evt.fs_nrio());
90 push_counter("read_fs_meta", evt.fs_mrio());
91 push_counter("other_fs_discard", evt.fs_discard());
92 }
93
ParseF2fsIostatLatency(int64_t timestamp,protozero::ConstBytes blob)94 void IostatTracker::ParseF2fsIostatLatency(int64_t timestamp,
95 protozero::ConstBytes blob) {
96 protos::pbzero::F2fsIostatLatencyFtraceEvent::Decoder evt(blob.data,
97 blob.size);
98
99 static constexpr auto kBlueprint = tracks::CounterBlueprint(
100 "f2fs_iostat_latency", tracks::UnknownUnitBlueprint(),
101 tracks::DimensionBlueprints(
102 tracks::kLinuxDeviceDimensionBlueprint,
103 tracks::StringDimensionBlueprint("counter_key")),
104 tracks::FnNameBlueprint(
105 [](base::StringView device, base::StringView name) {
106 return base::StackString<1024>("f2fs_iostat_latency.[%.*s].%.*s",
107 int(device.size()), device.data(),
108 int(name.size()), name.data());
109 }));
110
111 auto push_counter = [&, this](const char* counter_name, uint64_t value) {
112 TrackId track = context_->track_tracker->InternTrack(
113 kBlueprint,
114 tracks::DimensionBlueprints(
115 base::StringView(GetRawDeviceName(evt.dev())), counter_name));
116 context_->event_tracker->PushCounter(timestamp, static_cast<double>(value),
117 track);
118 };
119 push_counter("read_data_peak", evt.d_rd_peak());
120 push_counter("read_data_avg", evt.d_rd_avg());
121 push_counter("read_data_cnt", evt.d_rd_cnt());
122 push_counter("read_node_peak", evt.n_rd_peak());
123 push_counter("read_node_avg", evt.n_rd_avg());
124 push_counter("read_node_cnt", evt.n_rd_cnt());
125 push_counter("read_meta_peak", evt.m_rd_peak());
126 push_counter("read_meta_avg", evt.m_rd_avg());
127 push_counter("read_meta_cnt", evt.m_rd_cnt());
128 push_counter("write_sync_data_peak", evt.d_wr_s_peak());
129 push_counter("write_sync_data_avg", evt.d_wr_s_avg());
130 push_counter("write_sync_data_cnt", evt.d_wr_s_cnt());
131 push_counter("write_sync_node_peak", evt.n_wr_s_peak());
132 push_counter("write_sync_node_avg", evt.n_wr_s_avg());
133 push_counter("write_sync_node_cnt", evt.n_wr_s_cnt());
134 push_counter("write_sync_meta_peak", evt.m_wr_s_peak());
135 push_counter("write_sync_meta_avg", evt.m_wr_s_avg());
136 push_counter("write_sync_meta_cnt", evt.m_wr_s_cnt());
137 push_counter("write_async_data_peak", evt.d_wr_as_peak());
138 push_counter("write_async_data_avg", evt.d_wr_as_avg());
139 push_counter("write_async_data_cnt", evt.d_wr_as_cnt());
140 push_counter("write_async_node_peak", evt.n_wr_as_peak());
141 push_counter("write_async_node_avg", evt.n_wr_as_avg());
142 push_counter("write_async_node_cnt", evt.n_wr_as_cnt());
143 push_counter("write_async_meta_peak", evt.m_wr_as_peak());
144 push_counter("write_async_meta_avg", evt.m_wr_as_avg());
145 push_counter("write_async_meta_cnt", evt.m_wr_as_cnt());
146 }
147
148 } // namespace perfetto::trace_processor
149