• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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/metrics/metrics.h"
18 
19 #include "perfetto/base/string_utils.h"
20 #include "perfetto/metrics/android/mem_metric.pbzero.h"
21 #include "perfetto/metrics/metrics.pbzero.h"
22 #include "perfetto/protozero/scattered_heap_buffer.h"
23 #include "src/trace_processor/metrics/sql_metrics.h"
24 
25 namespace perfetto {
26 namespace trace_processor {
27 namespace metrics {
28 
RunMetric(sqlite3_context * ctx,int argc,sqlite3_value ** argv)29 void RunMetric(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
30   auto* tp = static_cast<TraceProcessor*>(sqlite3_user_data(ctx));
31   if (argc == 0 || sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
32     sqlite3_result_error(ctx, "Invalid call to RUN_METRIC", -1);
33     return;
34   }
35 
36   const char* filename =
37       reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
38   const char* sql = sql_metrics::GetBundledMetric(filename);
39   if (!sql) {
40     sqlite3_result_error(ctx, "Unknown filename provided to RUN_METRIC", -1);
41     return;
42   }
43 
44   for (const auto& query : base::SplitString(sql, ";\n\n")) {
45     PERFETTO_DLOG("Executing query in RUN_METRIC: %s", query.c_str());
46 
47     auto it = tp->ExecuteQuery(query);
48     if (auto opt_error = it.GetLastError()) {
49       sqlite3_result_error(ctx, "Error when running RUN_METRIC file", -1);
50       return;
51     } else if (it.Next()) {
52       sqlite3_result_error(
53           ctx, "RUN_METRIC functions should not produce any output", -1);
54       return;
55     }
56   }
57 }
58 
ComputeMetrics(TraceProcessor * tp,const std::vector<std::string> & metric_names,std::vector<uint8_t> * metrics_proto)59 int ComputeMetrics(TraceProcessor* tp,
60                    const std::vector<std::string>& metric_names,
61                    std::vector<uint8_t>* metrics_proto) {
62   // TODO(lalitm): stop hardcoding android.mem metric and read the proto
63   // descriptor for this logic instead.
64   if (metric_names.size() != 1 || metric_names[0] != "android.mem") {
65     PERFETTO_ELOG("Only android.mem metric is currently supported");
66     return 1;
67   }
68 
69   auto queries = base::SplitString(sql_metrics::kAndroidMem, ";\n\n");
70   for (const auto& query : queries) {
71     PERFETTO_DLOG("Executing query: %s", query.c_str());
72     auto prep_it = tp->ExecuteQuery(query);
73     auto prep_has_next = prep_it.Next();
74     if (auto opt_error = prep_it.GetLastError()) {
75       PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
76       return 1;
77     }
78     PERFETTO_DCHECK(!prep_has_next);
79   }
80 
81   protozero::ScatteredHeapBuffer delegate;
82   protozero::ScatteredStreamWriter writer(&delegate);
83   delegate.set_writer(&writer);
84 
85   protos::pbzero::TraceMetrics metrics;
86   metrics.Reset(&writer);
87 
88   // TODO(lalitm): all the below is temporary hardcoded queries and proto
89   // filling to ensure that the code above works.
90   auto it = tp->ExecuteQuery("SELECT COUNT(*) from lmk_by_score;");
91   auto has_next = it.Next();
92   if (auto opt_error = it.GetLastError()) {
93     PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
94     return 1;
95   }
96   PERFETTO_CHECK(has_next);
97   PERFETTO_CHECK(it.Get(0).type == SqlValue::Type::kLong);
98 
99   auto* memory = metrics.set_android_mem();
100   memory->set_system_metrics()->set_lmks()->set_total_count(
101       static_cast<int32_t>(it.Get(0).long_value));
102   metrics.Finalize();
103 
104   *metrics_proto = delegate.StitchSlices();
105 
106   has_next = it.Next();
107   PERFETTO_DCHECK(!has_next);
108   return 0;
109 }
110 
111 }  // namespace metrics
112 }  // namespace trace_processor
113 }  // namespace perfetto
114