Merge changes I24229f22,I163dc100

* changes:
  tp: move statsd_module into full target from minimal
  tp: move sorter into its own folder
diff --git a/Android.bp b/Android.bp
index 340826e..eeed817 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1964,7 +1964,6 @@
         ":perfetto_src_protozero_filtering_message_filter",
         ":perfetto_src_protozero_proto_ring_buffer",
         ":perfetto_src_protozero_protozero",
-        ":perfetto_src_trace_processor_analysis_analysis",
         ":perfetto_src_trace_processor_containers_containers",
         ":perfetto_src_trace_processor_db_db",
         ":perfetto_src_trace_processor_dynamic_dynamic",
@@ -9005,14 +9004,6 @@
     ],
 }
 
-// GN: //src/trace_processor/analysis:analysis
-filegroup {
-    name: "perfetto_src_trace_processor_analysis_analysis",
-    srcs: [
-        "src/trace_processor/analysis/describe_slice.cc",
-    ],
-}
-
 // GN: //src/trace_processor/containers:containers
 filegroup {
     name: "perfetto_src_trace_processor_containers_containers",
@@ -9082,7 +9073,6 @@
         "src/trace_processor/dynamic/ancestor_generator.cc",
         "src/trace_processor/dynamic/connected_flow_generator.cc",
         "src/trace_processor/dynamic/descendant_generator.cc",
-        "src/trace_processor/dynamic/describe_slice_generator.cc",
         "src/trace_processor/dynamic/dynamic_table_generator.cc",
         "src/trace_processor/dynamic/experimental_annotated_stack_generator.cc",
         "src/trace_processor/dynamic/experimental_counter_dur_generator.cc",
@@ -11226,7 +11216,6 @@
         ":perfetto_src_protozero_testing_messages_lite_gen",
         ":perfetto_src_protozero_testing_messages_zero_gen",
         ":perfetto_src_protozero_unittests",
-        ":perfetto_src_trace_processor_analysis_analysis",
         ":perfetto_src_trace_processor_containers_containers",
         ":perfetto_src_trace_processor_containers_unittests",
         ":perfetto_src_trace_processor_db_db",
@@ -11879,7 +11868,6 @@
         ":perfetto_src_profiling_symbolizer_symbolizer",
         ":perfetto_src_protozero_proto_ring_buffer",
         ":perfetto_src_protozero_protozero",
-        ":perfetto_src_trace_processor_analysis_analysis",
         ":perfetto_src_trace_processor_containers_containers",
         ":perfetto_src_trace_processor_db_db",
         ":perfetto_src_trace_processor_dynamic_dynamic",
@@ -12078,7 +12066,6 @@
         ":perfetto_src_profiling_symbolizer_symbolizer",
         ":perfetto_src_protozero_proto_ring_buffer",
         ":perfetto_src_protozero_protozero",
-        ":perfetto_src_trace_processor_analysis_analysis",
         ":perfetto_src_trace_processor_containers_containers",
         ":perfetto_src_trace_processor_db_db",
         ":perfetto_src_trace_processor_dynamic_dynamic",
diff --git a/BUILD b/BUILD
index 0ffff73..23e2d94 100644
--- a/BUILD
+++ b/BUILD
@@ -1000,15 +1000,6 @@
     ],
 )
 
-# GN target: //src/trace_processor/analysis:analysis
-perfetto_filegroup(
-    name = "src_trace_processor_analysis_analysis",
-    srcs = [
-        "src/trace_processor/analysis/describe_slice.cc",
-        "src/trace_processor/analysis/describe_slice.h",
-    ],
-)
-
 # GN target: //src/trace_processor/containers:containers
 perfetto_cc_library(
     name = "src_trace_processor_containers_containers",
@@ -1067,8 +1058,6 @@
         "src/trace_processor/dynamic/connected_flow_generator.h",
         "src/trace_processor/dynamic/descendant_generator.cc",
         "src/trace_processor/dynamic/descendant_generator.h",
-        "src/trace_processor/dynamic/describe_slice_generator.cc",
-        "src/trace_processor/dynamic/describe_slice_generator.h",
         "src/trace_processor/dynamic/dynamic_table_generator.cc",
         "src/trace_processor/dynamic/dynamic_table_generator.h",
         "src/trace_processor/dynamic/experimental_annotated_stack_generator.cc",
@@ -4396,7 +4385,6 @@
     name = "trace_processor",
     srcs = [
         ":src_kernel_utils_syscall_table",
-        ":src_trace_processor_analysis_analysis",
         ":src_trace_processor_db_db",
         ":src_trace_processor_dynamic_dynamic",
         ":src_trace_processor_export_json",
@@ -4531,7 +4519,6 @@
         ":src_profiling_symbolizer_symbolize_database",
         ":src_profiling_symbolizer_symbolizer",
         ":src_protozero_proto_ring_buffer",
-        ":src_trace_processor_analysis_analysis",
         ":src_trace_processor_db_db",
         ":src_trace_processor_dynamic_dynamic",
         ":src_trace_processor_export_json",
@@ -4725,7 +4712,6 @@
         ":src_profiling_symbolizer_symbolize_database",
         ":src_profiling_symbolizer_symbolizer",
         ":src_protozero_proto_ring_buffer",
-        ":src_trace_processor_analysis_analysis",
         ":src_trace_processor_db_db",
         ":src_trace_processor_dynamic_dynamic",
         ":src_trace_processor_export_json",
diff --git a/docs/contributing/common-tasks.md b/docs/contributing/common-tasks.md
index 421cd13..7d6bd8b 100644
--- a/docs/contributing/common-tasks.md
+++ b/docs/contributing/common-tasks.md
@@ -46,15 +46,6 @@
   3. Run the newly added test with `tools/diff_test_trace_processor.py <path to trace processor binary>`.
 4. Upload and land your change as normal.
 
-## {#new-annotation} Add a new annotation
-
-NOTE: all currently implemented annotations are based only on the name of the slice. It is straightforward to extend this to also consider ancestors and other similar properties; we plan on doing this in the future.
-
-1. Change the [`DescribeSlice`](/src/trace_processor/analysis/describe_slice.h) function as appropriate.
-  * The inputs are the table containing all the slices from the trace and the id of the slice which an embedder (e.g. the UI) is requesting a description for.
-  * The output is a `SliceDescription` which is simply a `pair<description, doc link>`.
-2. Upload and land your change as normal.
-
 ## Adding new derived events
 
 As derived events depend on metrics, the initial steps are same as that of developing a metric (see above).
diff --git a/docs/contributing/embedding.md b/docs/contributing/embedding.md
index dbf6c56..0d080c9 100644
--- a/docs/contributing/embedding.md
+++ b/docs/contributing/embedding.md
@@ -44,32 +44,6 @@
 
 WARNING: embedders should ensure that the path of any registered metric is consistent with the name used to execute the metric and output view in the SQL.
 
-### Annotations
-
-The `DescribeSlice` function is exposed to SQL through the `describe_slice` table. This table has the following schema:
-
-| Name        | Type   | Meaning                                                      |
-| :---------- | ------ | ------------------------------------------------------------ |
-| description | string | Provides the description for the given slice                 |
-| doc_link    | string | Provides a hyperlink to documentation which gives more context for the slice |
-
-The table also has a hidden column `slice_id` which needs to be set equal to the id of the slice for which to get the description. For example, to get the description and doc link for slice with id `5`:
-
-```sql
-select description, doc_link
-from describe_slice
-where slice_id = 5
-```
-
-The `describe_slice` table can also be _joined_ with the slice table to obtain descriptions for more than one slice. For example, to get the `ts`, `dur` and `description` for all `measure` slices:
-
-```sql
-select ts, dur, description
-from slice s
-join desribe_slice d on s.id = d.slice_id
-where name = 'measure'
-```
-
 ### Creating derived events
 
 As creating derived events is tied to the metrics subsystem, the `ComputeMetrics` function in the trace processor API should be called with the appropriate metrics. This will create the `<metric_name>_event` table/view which can then be queried using the `ExectueQuery` function.
diff --git a/src/tools/proto_merger/main.cc b/src/tools/proto_merger/main.cc
index 35eaee1..8ff2c1a 100644
--- a/src/tools/proto_merger/main.cc
+++ b/src/tools/proto_merger/main.cc
@@ -222,12 +222,27 @@
     return 1;
   }
 
+  std::string input_contents;
+  if (!base::ReadFile(input_include + "/" + input, &input_contents)) {
+    PERFETTO_ELOG("Failed to read input");
+    return 1;
+  }
+
+  static constexpr char kPremable[] =
+      "// --- PREAMBLE ENDS HERE - EVERYTHING BELOW AUTOGENERATED ---\n";
+  size_t input_premable_idx = input_contents.find(kPremable);
+  std::string input_preamble =
+      input_premable_idx == std::string::npos
+          ? ""
+          : input_contents.substr(0, input_premable_idx + strlen(kPremable));
+
   ImportResult input_proto = ImportProto(input, input_include);
-  ProtoFile input_file = ProtoFileFromDescriptor(*input_proto.file_descriptor);
+  ProtoFile input_file = ProtoFileFromDescriptor(std::move(input_preamble),
+                                                 *input_proto.file_descriptor);
 
   ImportResult upstream_proto = ImportProto(upstream, upstream_include);
   ProtoFile upstream_file =
-      ProtoFileFromDescriptor(*upstream_proto.file_descriptor);
+      ProtoFileFromDescriptor("", *upstream_proto.file_descriptor);
 
   Allowlist allowed;
   if (!allowlist.empty()) {
diff --git a/src/tools/proto_merger/proto_file.cc b/src/tools/proto_merger/proto_file.cc
index 5209e90..8b28627 100644
--- a/src/tools/proto_merger/proto_file.cc
+++ b/src/tools/proto_merger/proto_file.cc
@@ -263,8 +263,10 @@
 }  // namespace
 
 ProtoFile ProtoFileFromDescriptor(
+    std::string premable,
     const google::protobuf::FileDescriptor& desc) {
   ProtoFile file;
+  file.preamble = std::move(premable);
   for (int i = 0; i < desc.enum_type_count(); ++i) {
     file.enums.push_back(EnumFromDescriptor(*desc.enum_type(i)));
   }
diff --git a/src/tools/proto_merger/proto_file.h b/src/tools/proto_merger/proto_file.h
index 1939a50..a7056da 100644
--- a/src/tools/proto_merger/proto_file.h
+++ b/src/tools/proto_merger/proto_file.h
@@ -75,6 +75,8 @@
     std::vector<Field> deleted_fields;
   };
 
+  std::string preamble;
+
   std::vector<Message> messages;
   std::vector<Enum> enums;
 
@@ -83,7 +85,8 @@
 };
 
 // Creates a ProtoFile struct from a libprotobuf-full descriptor clas.
-ProtoFile ProtoFileFromDescriptor(const google::protobuf::FileDescriptor&);
+ProtoFile ProtoFileFromDescriptor(std::string premable,
+                                  const google::protobuf::FileDescriptor&);
 
 }  // namespace proto_merger
 }  // namespace perfetto
diff --git a/src/tools/proto_merger/proto_file_serializer.cc b/src/tools/proto_merger/proto_file_serializer.cc
index dcaceb0..dca5a07 100644
--- a/src/tools/proto_merger/proto_file_serializer.cc
+++ b/src/tools/proto_merger/proto_file_serializer.cc
@@ -197,6 +197,8 @@
 
 std::string ProtoFileToDotProto(const ProtoFile& proto_file) {
   std::string output;
+  output += proto_file.preamble;
+
   for (const auto& en : proto_file.enums) {
     output += SerializeEnum(0, en);
   }
diff --git a/src/tools/proto_merger/proto_merger.cc b/src/tools/proto_merger/proto_merger.cc
index 9b7cf55..65e20d8 100644
--- a/src/tools/proto_merger/proto_merger.cc
+++ b/src/tools/proto_merger/proto_merger.cc
@@ -339,6 +339,10 @@
                              const ProtoFile& upstream,
                              const Allowlist& allowlist,
                              ProtoFile& out) {
+  // The preamble is taken directly from upstream. This allows private stuff
+  // to be in the preamble without being present in upstream.
+  out.preamble = input.preamble;
+
   // Compute all the enums and messages present in the input but deleted in the
   // source of truth.
   out.deleted_enums = ComputeDeletedByName(input.enums, upstream.enums);
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 5c6644e..12d484a 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -237,7 +237,6 @@
       "../../protos/perfetto/trace/ftrace:zero",
       "../base",
       "../protozero",
-      "analysis",
       "db",
       "dynamic",
       "importers:importers_full",
diff --git a/src/trace_processor/analysis/BUILD.gn b/src/trace_processor/analysis/BUILD.gn
deleted file mode 100644
index 0846610..0000000
--- a/src/trace_processor/analysis/BUILD.gn
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2020 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("../../../gn/perfetto.gni")
-
-source_set("analysis") {
-  sources = [
-    "describe_slice.cc",
-    "describe_slice.h",
-  ]
-  deps = [
-    "../../../gn:default_deps",
-    "../../../include/perfetto/ext/base",
-    "../../../include/perfetto/trace_processor",
-    "../tables",
-  ]
-}
diff --git a/src/trace_processor/analysis/describe_slice.cc b/src/trace_processor/analysis/describe_slice.cc
deleted file mode 100644
index 7ad3533..0000000
--- a/src/trace_processor/analysis/describe_slice.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/analysis/describe_slice.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-util::Status DescribeSlice(const tables::SliceTable& table,
-                           tables::SliceTable::Id id,
-                           base::Optional<SliceDescription>* description) {
-  auto opt_row = table.id().IndexOf(id);
-  if (!opt_row)
-    return util::ErrStatus("Unable to find slice id");
-
-  uint32_t row = *opt_row;
-
-  base::StringView name = table.name().GetString(row);
-  if (name == "inflate") {
-    *description = SliceDescription{
-        "Constructing a View hierarchy from pre-processed XML via "
-        "LayoutInflater#layout. This includes constructing all of the View "
-        "objects in the hierarchy, and applying styled attributes.",
-        ""};
-    return util::OkStatus();
-  }
-
-  if (name == "measure") {
-    *description = SliceDescription{
-        "First of two phases in view hierarchy layout. Views are asked to size "
-        "themselves according to constraints supplied by their parent. Some "
-        "ViewGroups may measure a child more than once to help satisfy their "
-        "own constraints. Nesting ViewGroups that measure children more than "
-        "once can lead to excessive and repeated work.",
-        "https://developer.android.com/reference/android/view/"
-        "View.html#Layout"};
-    return util::OkStatus();
-  }
-
-  *description = base::nullopt;
-  return util::OkStatus();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/analysis/describe_slice.h b/src/trace_processor/analysis/describe_slice.h
deleted file mode 100644
index 9dedeb8..0000000
--- a/src/trace_processor/analysis/describe_slice.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_ANALYSIS_DESCRIBE_SLICE_H_
-#define SRC_TRACE_PROCESSOR_ANALYSIS_DESCRIBE_SLICE_H_
-
-#include <string>
-
-#include "perfetto/trace_processor/status.h"
-
-#include "src/trace_processor/tables/slice_tables.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-struct SliceDescription {
-  std::string description;
-  std::string doc_link;
-};
-
-// Provides a description and doc link (if available) for the given slice id in
-// the slice table. For a high level overview of this function's use, see
-// /docs/analysis.md.
-util::Status DescribeSlice(const tables::SliceTable&,
-                           tables::SliceTable::Id,
-                           base::Optional<SliceDescription>* description);
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_ANALYSIS_DESCRIBE_SLICE_H_
diff --git a/src/trace_processor/dynamic/BUILD.gn b/src/trace_processor/dynamic/BUILD.gn
index 82e7e06..869b044 100644
--- a/src/trace_processor/dynamic/BUILD.gn
+++ b/src/trace_processor/dynamic/BUILD.gn
@@ -20,8 +20,6 @@
     "connected_flow_generator.h",
     "descendant_generator.cc",
     "descendant_generator.h",
-    "describe_slice_generator.cc",
-    "describe_slice_generator.h",
     "dynamic_table_generator.cc",
     "dynamic_table_generator.h",
     "experimental_annotated_stack_generator.cc",
@@ -45,7 +43,6 @@
     "../../../gn:default_deps",
     "../../../gn:sqlite",
     "../../base",
-    "../analysis",
     "../containers",
     "../db",
     "../importers/proto:full",
diff --git a/src/trace_processor/dynamic/describe_slice_generator.cc b/src/trace_processor/dynamic/describe_slice_generator.cc
deleted file mode 100644
index a97d76e..0000000
--- a/src/trace_processor/dynamic/describe_slice_generator.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/trace_processor/dynamic/describe_slice_generator.h"
-
-#include "src/trace_processor/analysis/describe_slice.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-#include "src/trace_processor/types/trace_processor_context.h"
-#include "src/trace_processor/util/status_macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-DescribeSliceGenerator::InputValues GetDescribeSliceInputValues(
-    const std::vector<Constraint>& cs) {
-  using DST = tables::DescribeSliceTable;
-
-  auto slice_id_fn = [](const Constraint& c) {
-    return c.col_idx == static_cast<uint32_t>(DST::ColumnIndex::slice_id) &&
-           c.op == FilterOp::kEq;
-  };
-  auto slice_id_it = std::find_if(cs.begin(), cs.end(), slice_id_fn);
-
-  PERFETTO_CHECK(slice_id_it != cs.end());
-  // TODO(rsavitski): consider checking type of the SqlValue, as erroneous
-  // queries that pass a null here (or otherwise unexpected type) will crash.
-
-  uint32_t slice_id_value = static_cast<uint32_t>(slice_id_it->value.AsLong());
-  return DescribeSliceGenerator::InputValues{slice_id_value};
-}
-
-}  // namespace
-
-DescribeSliceGenerator::DescribeSliceGenerator(TraceProcessorContext* context)
-    : context_(context) {}
-
-DescribeSliceGenerator::~DescribeSliceGenerator() = default;
-
-base::Status DescribeSliceGenerator::ValidateConstraints(
-    const QueryConstraints& qc) {
-  using T = tables::DescribeSliceTable;
-
-  const auto& cs = qc.constraints();
-
-  auto slice_id_fn = [](const QueryConstraints::Constraint& c) {
-    return c.column == static_cast<int>(T::ColumnIndex::slice_id) &&
-           sqlite_utils::IsOpEq(c.op);
-  };
-  bool has_slice_id_cs =
-      std::find_if(cs.begin(), cs.end(), slice_id_fn) != cs.end();
-
-  return has_slice_id_cs
-             ? base::OkStatus()
-             : base::ErrStatus("Failed to find required constraints");
-}
-
-base::Status DescribeSliceGenerator::ComputeTable(
-    const std::vector<Constraint>& cs,
-    const std::vector<Order>&,
-    const BitVector&,
-    std::unique_ptr<Table>& table_return) {
-  auto input = GetDescribeSliceInputValues(cs);
-  const auto& slices = context_->storage->slice_table();
-
-  base::Optional<SliceDescription> opt_desc;
-  RETURN_IF_ERROR(
-      DescribeSlice(slices, SliceId{input.slice_id_value}, &opt_desc));
-
-  auto* pool = context_->storage->mutable_string_pool();
-  std::unique_ptr<tables::DescribeSliceTable> table(
-      new tables::DescribeSliceTable(pool, nullptr));
-
-  if (opt_desc) {
-    tables::DescribeSliceTable::Row row;
-    row.description = context_->storage->InternString(
-        base::StringView(opt_desc->description));
-    row.doc_link =
-        context_->storage->InternString(base::StringView(opt_desc->doc_link));
-    row.slice_id = input.slice_id_value;
-    table->Insert(row);
-  }
-  table_return = std::move(table);
-  return base::OkStatus();
-}
-
-Table::Schema DescribeSliceGenerator::CreateSchema() {
-  return tables::DescribeSliceTable::ComputeStaticSchema();
-}
-
-std::string DescribeSliceGenerator::TableName() {
-  return "describe_slice";
-}
-
-uint32_t DescribeSliceGenerator::EstimateRowCount() {
-  return 1;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/dynamic/describe_slice_generator.h b/src/trace_processor/dynamic/describe_slice_generator.h
deleted file mode 100644
index d4795af..0000000
--- a/src/trace_processor/dynamic/describe_slice_generator.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_DYNAMIC_DESCRIBE_SLICE_GENERATOR_H_
-#define SRC_TRACE_PROCESSOR_DYNAMIC_DESCRIBE_SLICE_GENERATOR_H_
-
-#include "src/trace_processor/dynamic/dynamic_table_generator.h"
-#include "src/trace_processor/storage/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Dynamic table for implementing the describe_slice table.
-// See /docs/analysis.md for details about the functionality and usage of this
-// table.
-class DescribeSliceGenerator : public DynamicTableGenerator {
- public:
-  struct InputValues {
-    uint32_t slice_id_value;
-  };
-
-  explicit DescribeSliceGenerator(TraceProcessorContext* context);
-  ~DescribeSliceGenerator() override;
-
-  Table::Schema CreateSchema() override;
-  std::string TableName() override;
-  uint32_t EstimateRowCount() override;
-  base::Status ValidateConstraints(const QueryConstraints&) override;
-  base::Status ComputeTable(const std::vector<Constraint>& cs,
-                            const std::vector<Order>& ob,
-                            const BitVector& cols_used,
-                            std::unique_ptr<Table>& table_return) override;
-
- private:
-  TraceProcessorContext* context_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DYNAMIC_DESCRIBE_SLICE_GENERATOR_H_
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
index b9daf96..f67a4f0 100644
--- a/src/trace_processor/tables/slice_tables.h
+++ b/src/trace_processor/tables/slice_tables.h
@@ -130,15 +130,6 @@
 
 PERFETTO_TP_TABLE(PERFETTO_TP_GRAPHICS_FRAME_SLICES_DEF);
 
-#define PERFETTO_TP_DESCRIBE_SLICE_TABLE(NAME, PARENT, C) \
-  NAME(DescribeSliceTable, "describe_slice")              \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                       \
-  C(uint32_t, slice_id, Column::Flag::kHidden)            \
-  C(StringPool::Id, description)                          \
-  C(StringPool::Id, doc_link)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_DESCRIBE_SLICE_TABLE);
-
 #define PERFETTO_TP_EXPECTED_FRAME_TIMELINE_SLICES_DEF(NAME, PARENT, C)  \
   NAME(ExpectedFrameTimelineSliceTable, "expected_frame_timeline_slice") \
   PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C)                                 \
diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc
index a16b65e..1a9ca11 100644
--- a/src/trace_processor/tables/table_destructors.cc
+++ b/src/trace_processor/tables/table_destructors.cc
@@ -75,7 +75,6 @@
 SchedSliceTable::~SchedSliceTable() = default;
 GpuSliceTable::~GpuSliceTable() = default;
 GraphicsFrameSliceTable::~GraphicsFrameSliceTable() = default;
-DescribeSliceTable::~DescribeSliceTable() = default;
 ThreadStateTable::~ThreadStateTable() = default;
 ExpectedFrameTimelineSliceTable::~ExpectedFrameTimelineSliceTable() = default;
 ActualFrameTimelineSliceTable::~ActualFrameTimelineSliceTable() = default;
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 42b5967..37a447a 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -33,7 +33,6 @@
 #include "src/trace_processor/dynamic/ancestor_generator.h"
 #include "src/trace_processor/dynamic/connected_flow_generator.h"
 #include "src/trace_processor/dynamic/descendant_generator.h"
-#include "src/trace_processor/dynamic/describe_slice_generator.h"
 #include "src/trace_processor/dynamic/experimental_annotated_stack_generator.h"
 #include "src/trace_processor/dynamic/experimental_counter_dur_generator.h"
 #include "src/trace_processor/dynamic/experimental_flamegraph_generator.h"
@@ -314,6 +313,15 @@
                nullptr, nullptr, &error);
   MaybeRegisterError(error);
 
+  // TODO(lalitm): delete this any time after ~Feb 2023 when no version of the
+  // UI will be querying this anymore (describe_slice backing code was removed
+  // at end of November).
+  sqlite3_exec(db,
+               "CREATE TABLE describe_slice(id INT, type TEXT, "
+               "slice_id INT, description TEXT, doc_link TEXT);",
+               nullptr, nullptr, &error);
+  MaybeRegisterError(error);
+
   sqlite3_exec(db,
                "CREATE VIEW thread_slice AS "
                "SELECT * FROM slice "
@@ -764,8 +772,6 @@
       new ExperimentalFlamegraphGenerator(&context_)));
   RegisterDynamicTable(std::unique_ptr<ExperimentalCounterDurGenerator>(
       new ExperimentalCounterDurGenerator(storage->counter_table())));
-  RegisterDynamicTable(std::unique_ptr<DescribeSliceGenerator>(
-      new DescribeSliceGenerator(&context_)));
   RegisterDynamicTable(std::unique_ptr<ExperimentalSliceLayoutGenerator>(
       new ExperimentalSliceLayoutGenerator(
           context_.storage.get()->mutable_string_pool(),
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 18a1785..567247f 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -307,6 +307,21 @@
       return true;
     }
 
+    // 2.5. A special case for Chrome's legacy disabled-by-default categories.
+    // We treat them as having a "slow" tag with one exception: they can be
+    // enabled by a pattern if the pattern starts with "disabled-by-default-"
+    // itself.
+    if (match_type == MatchType::kExact &&
+        !strncmp(category.name, kLegacySlowPrefix, strlen(kLegacySlowPrefix))) {
+      for (const auto& pattern : config.enabled_categories()) {
+        if (!strncmp(pattern.c_str(), kLegacySlowPrefix,
+                     strlen(kLegacySlowPrefix)) &&
+            NameMatchesPattern(pattern, category.name, MatchType::kPattern)) {
+          return true;
+        }
+      }
+    }
+
     // 3. Disabled categories.
     if (NameMatchesPatternList(config.disabled_categories(), category.name,
                                match_type)) {
diff --git a/src/tracing/test/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
index fdba858..2561cb8 100644
--- a/src/tracing/test/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -3559,6 +3559,16 @@
                             "B:disabled-by-default-cat.SlowDisabledEvent"));
   }
 
+  // Enable all legacy disabled-by-default categories by a pattern
+  {
+    perfetto::protos::gen::TrackEventConfig te_cfg;
+    te_cfg.add_disabled_categories("*");
+    te_cfg.add_enabled_categories("disabled-by-default-*");
+    auto slices = check_config(te_cfg);
+    EXPECT_THAT(slices,
+                ElementsAre("B:disabled-by-default-cat.SlowDisabledEvent"));
+  }
+
   // Enable everything including slow/debug categories.
   {
     perfetto::protos::gen::TrackEventConfig te_cfg;
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 7123ba3..b515d19 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -49,6 +49,7 @@
         "node-watch": "^0.7.1",
         "pixelmatch": "^5.2.1",
         "pngjs": "^6.0.0",
+        "prettier": "^2.8.0",
         "puppeteer": "^14.1.0",
         "rollup": "^2.38.5",
         "rollup-plugin-re": "^1.0.7",
@@ -7751,6 +7752,21 @@
         "node": ">= 0.8.0"
       }
     },
+    "node_modules/prettier": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz",
+      "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==",
+      "dev": true,
+      "bin": {
+        "prettier": "bin-prettier.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "url": "https://github.com/prettier/prettier?sponsor=1"
+      }
+    },
     "node_modules/pretty-format": {
       "version": "26.6.2",
       "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
@@ -15954,6 +15970,12 @@
       "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
       "dev": true
     },
+    "prettier": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz",
+      "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==",
+      "dev": true
+    },
     "pretty-format": {
       "version": "26.6.2",
       "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
diff --git a/ui/package.json b/ui/package.json
index 6128f2b..dbe9bc7 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -47,6 +47,7 @@
     "node-watch": "^0.7.1",
     "pixelmatch": "^5.2.1",
     "pngjs": "^6.0.0",
+    "prettier": "^2.8.0",
     "puppeteer": "^14.1.0",
     "rollup": "^2.38.5",
     "rollup-plugin-re": "^1.0.7",
diff --git a/ui/src/assets/analyze_page.scss b/ui/src/assets/analyze_page.scss
index bbfed10..4a700a3 100644
--- a/ui/src/assets/analyze_page.scss
+++ b/ui/src/assets/analyze_page.scss
@@ -26,7 +26,7 @@
     font-size: inherit;
     font-family: var(--monospace-font);
     line-height: 1.2em;
-    padding: .5em;
+    padding: 0.5em;
     overflow: auto;
     resize: vertical;
   }
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index 4d22451..52b7022 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -12,51 +12,42 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 :root {
-    --sidebar-width: 256px;
-    --topbar-height: 48px;
-    --monospace-font: 'Roboto Mono', monospace;
-    --track-shell-width: 250px;
-    --track-border-color: #00000025;
-    --anim-easing: cubic-bezier(0.4, 0.0, 0.2, 1);
-    --selection-stroke-color: #00344596;
-    --selection-fill-color: #8398e64d;
-    --overview-timeline-non-visible-color: #c8c8c8cc;
-    --details-content-height: 280px;
+  --sidebar-width: 256px;
+  --topbar-height: 48px;
+  --monospace-font: "Roboto Mono", monospace;
+  --track-shell-width: 250px;
+  --track-border-color: #00000025;
+  --anim-easing: cubic-bezier(0.4, 0, 0.2, 1);
+  --selection-stroke-color: #00344596;
+  --selection-fill-color: #8398e64d;
+  --overview-timeline-non-visible-color: #c8c8c8cc;
+  --details-content-height: 280px;
 }
 
-@mixin transition($time:0.1s) {
-    transition: opacity $time ease,
-                color $time ease,
-                background-color $time ease,
-                border-color $time ease,
-                width $time ease,
-                height $time ease,
-                max-width $time ease,
-                max-height $time ease,
-                margin $time ease,
-                transform $time ease,
-                box-shadow $time ease,
-                border-radius $time ease;
+@mixin transition($time: 0.1s) {
+  transition: opacity $time ease, color $time ease, background-color $time ease,
+    border-color $time ease, width $time ease, height $time ease,
+    max-width $time ease, max-height $time ease, margin $time ease,
+    transform $time ease, box-shadow $time ease, border-radius $time ease;
 }
 
 @mixin material-icon($content) {
-    direction: ltr;
-    display: inline-block;
-    font-family: 'Material Icons';
-    font-size: 24px;
-    font-style: normal;
-    font-weight: normal;
-    letter-spacing: normal;
-    line-height: 1;
-    text-transform: none;
-    white-space: nowrap;
-    word-wrap: normal;
-    -webkit-font-feature-settings: 'liga';
-    -webkit-font-smoothing: antialiased;
-    content: $content;
+  direction: ltr;
+  display: inline-block;
+  font-family: "Material Icons";
+  font-size: 24px;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-height: 1;
+  text-transform: none;
+  white-space: nowrap;
+  word-wrap: normal;
+  -webkit-font-feature-settings: "liga";
+  -webkit-font-smoothing: antialiased;
+  content: $content;
 }
 
-
 @mixin track_shell_title() {
   // line-height is deliberately 1px larger than font-size. Roboto seems to
   // overflow on the bottom on "g"s otherwise.
@@ -66,34 +57,35 @@
   overflow: hidden;
   text-align: left;
   overflow-wrap: break-word;
-  font-family: 'Roboto Condensed', sans-serif;
+  font-family: "Roboto Condensed", sans-serif;
   font-weight: 300;
   letter-spacing: -0.25px;
 }
 
 * {
-    box-sizing: border-box;
-    -webkit-tap-highlight-color: transparent;
-    touch-action: none;
+  box-sizing: border-box;
+  -webkit-tap-highlight-color: transparent;
+  touch-action: none;
 }
 
 html {
-    font-family: Roboto, verdana, sans-serif;
-    height: 100%;
-    width: 100%;
+  font-family: Roboto, verdana, sans-serif;
+  height: 100%;
+  width: 100%;
 }
 
 html,
 body,
-body>main {
-    height: 100%;
-    width: 100%;
-    padding: 0;
-    margin: 0;
-    overscroll-behavior: none;
+body > main {
+  height: 100%;
+  width: 100%;
+  padding: 0;
+  margin: 0;
+  overscroll-behavior: none;
 }
 
-pre, code {
+pre,
+code {
   font-family: var(--monospace-font);
 }
 
@@ -107,30 +99,30 @@
 h1,
 h2,
 h3 {
-    font-family: inherit;
-    font-size: inherit;
-    font-weight: inherit;
-    padding: 0;
-    margin: 0;
+  font-family: inherit;
+  font-size: inherit;
+  font-weight: inherit;
+  padding: 0;
+  margin: 0;
 }
 table {
-    user-select: text;
+  user-select: text;
 }
 
-body>main {
-    display: grid;
-    grid-template-areas:
-      "sidebar topbar"
-      "sidebar alerts"
-      "sidebar page";
-    grid-template-rows: auto auto 1fr;
-    grid-template-columns: auto 1fr;
-    color: #121212;
-    overflow: hidden;
+body > main {
+  display: grid;
+  grid-template-areas:
+    "sidebar topbar"
+    "sidebar alerts"
+    "sidebar page";
+  grid-template-rows: auto auto 1fr;
+  grid-template-columns: auto 1fr;
+  color: #121212;
+  overflow: hidden;
 }
 
 body.filedrag::after {
-  content: 'Drop the trace file to open it';
+  content: "Drop the trace file to open it";
   position: fixed;
   z-index: 99;
   top: 0;
@@ -160,22 +152,22 @@
 }
 
 .full-page-loading-screen {
-    position: absolute;
-    width: 100%;
-    height: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    flex-direction: row;
-    background: #3e4a5a url('assets/logo-3d.png') no-repeat fixed center;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-direction: row;
+  background: #3e4a5a url("assets/logo-3d.png") no-repeat fixed center;
 }
 
 .page {
-    grid-area: page;
-    position: relative;
-    display: flex;
-    flex-direction: column;
-    overflow: hidden;
+  grid-area: page;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
 }
 
 .split-panel {
@@ -189,8 +181,8 @@
 .alerts {
   grid-area: alerts;
   background-color: #f2f2f2;
-  >div {
-    font-family: 'Raleway', sans-serif;
+  > div {
+    font-family: "Raleway", sans-serif;
     font-weight: 400;
     letter-spacing: 0.25px;
     padding: 1rem;
@@ -200,7 +192,6 @@
       width: 24px;
       height: 24px;
     }
-
   }
 }
 
@@ -209,73 +200,69 @@
 }
 
 .query-table {
-    width: 100%;
-    font-size: 14px;
-    border: 0;
-    &.pivot-table{
-      thead, i {
-        cursor: pointer;
-        td.drop-location {
-          background-color: hsla(210, 38%, 95%, 1);
-        }
-        .total-aggregation {
-          white-space: pre;
-          font-weight: 600;
-          font-size: 12px
-        }
-      }
-      td {
-        height: 25px;
-      }
-      .disabled {
-        cursor: default;
-      }
-      .indent {
-        display: inline-block;
-        // 24px is the width of expand_more/expand_less icon to pad out cells
-        // without the button
-        width: 24px;
-      }
+  width: 100%;
+  font-size: 14px;
+  border: 0;
+  &.pivot-table {
+    thead,
+    i {
+      cursor: pointer;
     }
-    thead td {
-        position: sticky;
-        top: 0;
-        background-color: hsl(214, 22%, 90%);
-        color: #262f3c;
-        text-align: center;
-        padding: 1px 3px;
-        border-style: solid;
-        border-color: #fff;
-        border-right-width: 1px;
-        border-left-width: 1px;
+    thead td.reorderable-cell {
+      cursor: grab;
     }
-    tbody tr {
-        @include transition();
-        background-color: hsl(214, 22%, 100%);
-        font-family: var(--monospace-font);
-        &:nth-child(even) {
-            background-color: hsl(214, 22%, 95%);
-        }
-        td:first-child {
-            padding-left: 5px;
-        }
-        td:last-child {
-            padding-right: 5px;
-        }
-        &:hover {
-            background-color: hsl(214, 22%, 90%);
-        }
-        &[clickable] {
-          cursor: pointer;
-        }
+    td {
+      height: 25px;
     }
+    .disabled {
+      cursor: default;
+    }
+    .indent {
+      display: inline-block;
+      // 24px is the width of expand_more/expand_less icon to pad out cells
+      // without the button
+      width: 24px;
+    }
+  }
+  thead td {
+    position: sticky;
+    top: 0;
+    background-color: hsl(214, 22%, 90%);
+    color: #262f3c;
+    text-align: center;
+    padding: 1px 3px;
+    border-style: solid;
+    border-color: #fff;
+    border-right-width: 1px;
+    border-left-width: 1px;
+  }
+  tbody tr {
+    @include transition();
+    background-color: hsl(214, 22%, 100%);
+    font-family: var(--monospace-font);
+    &:nth-child(even) {
+      background-color: hsl(214, 22%, 95%);
+    }
+    td:first-child {
+      padding-left: 5px;
+    }
+    td:last-child {
+      padding-right: 5px;
+    }
+    &:hover {
+      background-color: hsl(214, 22%, 90%);
+    }
+    &[clickable] {
+      cursor: pointer;
+    }
+  }
 }
 
 .query-error {
-    padding: 20px 10px;
-    color: hsl(-10, 50%, 50%);
-    font-family: 'Roboto Condensed', sans-serif;
-    font-weight: 300;
+  padding: 20px 10px;
+  color: hsl(-10, 50%, 50%);
+  font-family: "Roboto Condensed", sans-serif;
+  font-weight: 300;
 }
 
 .dropdown {
@@ -312,7 +299,7 @@
     text-align: right;
     line-height: 1;
     display: block; // Required in order for inherited white-space property not
-                    // to screw up vertical rendering of the popup menu items.
+    // to screw up vertical rendering of the popup menu items.
 
     &:hover {
       background: #c7d0db;
@@ -325,98 +312,98 @@
 }
 
 .track {
+  display: grid;
+  grid-template-columns: auto 1fr;
+  grid-template-rows: 1fr 0;
+
+  &::after {
+    display: block;
+    content: "";
+    grid-column: 1 / span 2;
+    border-top: 1px solid var(--track-border-color);
+    margin-top: -1px;
+    z-index: 2;
+  }
+
+  .track-shell {
+    @include transition();
+    padding-left: 10px;
     display: grid;
-    grid-template-columns: auto 1fr;
-    grid-template-rows: 1fr 0;
+    cursor: grab;
+    grid-template-areas: "title buttons";
+    grid-template-columns: 1fr auto;
+    align-items: center;
+    width: var(--track-shell-width);
+    background: #fff;
+    border-right: 1px solid #c7d0db;
 
-    &::after {
-      display: block;
-      content: '';
-      grid-column: 1 / span 2;
-      border-top: 1px solid var(--track-border-color);
-      margin-top: -1px;
-      z-index: 2;
+    &.drag {
+      background-color: #eee;
+      box-shadow: 0 4px 12px -4px #999 inset;
+    }
+    &.drop-before {
+      box-shadow: 0 4px 2px -1px hsl(213, 40%, 50%) inset;
+    }
+    &.drop-after {
+      box-shadow: 0 -4px 2px -1px hsl(213, 40%, 50%) inset;
     }
 
-    .track-shell {
-        @include transition();
-        padding-left: 10px;
-        display: grid;
-        cursor: grab;
-        grid-template-areas: "title buttons";
-        grid-template-columns: 1fr auto;
-        align-items: center;
-        width: var(--track-shell-width);
-        background: #fff;
-        border-right: 1px solid #c7d0db;
-
-        &.drag {
-          background-color: #eee;
-          box-shadow: 0 4px 12px -4px #999 inset;
-        }
-        &.drop-before {
-          box-shadow: 0 4px 2px -1px hsl(213, 40%, 50%) inset;
-        }
-        &.drop-after {
-          box-shadow: 0 -4px 2px -1px hsl(213, 40%, 50%) inset;
-        }
-
-        &.selected {
-          background-color: #ebeef9;
-        }
-
-        &.alternating-thread-track {
-          background: hsl(214, 22%, 95%);
-        }
-
-        .chip {
-          background-color: #bed6ff;
-          border-radius: 3px;
-          font-size: smaller;
-          padding: 0 0.1rem;
-          margin-left: 1ch;
-        }
-
-        h1 {
-            grid-area: title;
-            color: hsl(213, 22%, 30%);
-            @include track_shell_title();
-        }
-        .track-buttons {
-          grid-area: buttons;
-          display: flex;
-          height: 100%;
-          align-items: center;
-        }
-        .track-button {
-          @include transition();
-          color: rgb(60, 86, 136);
-          cursor: pointer;
-          width: 22px;
-          font-size: 18px;
-          opacity: 0;
-        }
-
-        .track-button.show {
-          opacity: 1;
-        }
-        .track-button.full-height {
-          display: flex;
-          height: 100%;
-          align-items: center;
-
-          &:hover {
-            background-color: #ebeef9;
-          }
-        }
-
-        &:hover .track-button{
-          opacity: 1;
-        }
-        &.flash {
-          background-color: #ffe263;
-        }
+    &.selected {
+      background-color: #ebeef9;
     }
+
+    &.alternating-thread-track {
+      background: hsl(214, 22%, 95%);
+    }
+
+    .chip {
+      background-color: #bed6ff;
+      border-radius: 3px;
+      font-size: smaller;
+      padding: 0 0.1rem;
+      margin-left: 1ch;
+    }
+
+    h1 {
+      grid-area: title;
+      color: hsl(213, 22%, 30%);
+      @include track_shell_title();
+    }
+    .track-buttons {
+      grid-area: buttons;
+      display: flex;
+      height: 100%;
+      align-items: center;
+    }
+    .track-button {
+      @include transition();
+      color: rgb(60, 86, 136);
+      cursor: pointer;
+      width: 22px;
+      font-size: 18px;
+      opacity: 0;
+    }
+
+    .track-button.show {
+      opacity: 1;
+    }
+    .track-button.full-height {
+      display: flex;
+      height: 100%;
+      align-items: center;
+
+      &:hover {
+        background-color: #ebeef9;
+      }
+    }
+
+    &:hover .track-button {
+      opacity: 1;
+    }
+    &.flash {
+      background-color: #ffe263;
+    }
+  }
 }
 
 .scrolling-panel-container {
@@ -424,7 +411,7 @@
   overflow-x: hidden;
   overflow-y: auto;
   flex: 1 1 auto;
-  will-change: transform;  // Force layer creation.
+  will-change: transform; // Force layer creation.
   display: grid;
   grid-template-columns: 1fr;
   grid-template-rows: 1fr;
@@ -478,7 +465,7 @@
 }
 
 .panel {
-  position: relative;  // Otherwise canvas covers panel dom.
+  position: relative; // Otherwise canvas covers panel dom.
 
   &.sticky {
     position: sticky;
@@ -520,7 +507,7 @@
   align-content: center;
   background-color: hsl(213, 22%, 82%);
   color: hsl(213, 22%, 20%);
-  font-family: 'Roboto Condensed', sans-serif;
+  font-family: "Roboto Condensed", sans-serif;
   font-size: 15px;
   font-weight: 400;
   padding: 4px 10px;
@@ -529,10 +516,10 @@
   border-style: solid;
   border-width: 1px 0;
   .code {
-      font-family: var(--monospace-font);
-      font-size: 12px;
-      margin-left: 10px;
-      color: hsl(213, 22%, 40%);
+    font-family: var(--monospace-font);
+    font-size: 12px;
+    margin-left: 10px;
+    color: hsl(213, 22%, 40%);
   }
   span {
     white-space: nowrap;
@@ -581,7 +568,7 @@
   font-family: var(--monospace-font);
   padding: 10px 24px;
   z-index: 100;
-  background-color: rgba(27, 28, 29, 0.90);
+  background-color: rgba(27, 28, 29, 0.9);
   button {
     text-decoration: underline;
     color: hsl(45, 100%, 48%);
@@ -595,7 +582,7 @@
     top: 10px;
     width: 20px;
     height: 20px;
-    color: var(--stroke-color)
+    color: var(--stroke-color);
   }
   & > section {
     padding: 5px;
@@ -604,7 +591,9 @@
   div {
     margin: 2px 0;
   }
-  table, td, th {
+  table,
+  td,
+  th {
     border: 1px solid var(--stroke-color);
     text-align: center;
     padding: 4px;
@@ -623,16 +612,16 @@
   display: grid;
   grid-template-columns: auto 1fr;
   grid-template-rows: 1fr;
-  transition: background-color .4s, color .4s;
+  transition: background-color 0.4s, color 0.4s;
   height: 40px;
   &::after {
     display: block;
-    content: '';
+    content: "";
     grid-column: 1 / span 2;
     border-top: 1px solid var(--track-border-color);
     margin-top: -1px;
   }
-  &[collapsed=true] {
+  &[collapsed="true"] {
     background-color: var(--collapsed-transparent);
     .shell {
       border-right: 1px solid #c7d0db;
@@ -640,9 +629,9 @@
     }
     .track-button {
       color: rgb(60, 86, 136);
-    };
+    }
   }
-  &[collapsed=false] {
+  &[collapsed="false"] {
     background-color: var(--expanded-transparent);
     color: white;
     font-weight: bold;
@@ -665,7 +654,7 @@
     line-height: 1;
     width: var(--track-shell-width);
     min-height: 40px;
-    transition: background-color .4s;
+    transition: background-color 0.4s;
 
     .track-title {
       user-select: text;
@@ -728,16 +717,15 @@
   height: 10px;
 }
 
-
 .cookie-consent {
   position: absolute;
   z-index: 10;
   left: 10px;
   bottom: 10px;
   width: 550px;
-  background-color:#19212b;
+  background-color: #19212b;
   font-size: 14px;
-  color:rgb(180, 183, 186);
+  color: rgb(180, 183, 186);
   border-radius: 5px;
   padding: 20px;
 
@@ -745,7 +733,7 @@
     display: flex;
     justify-content: flex-end;
     margin-top: 10px;
-    font-size: 15px
+    font-size: 15px;
   }
 
   button {
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
index d8e9a37..b1044dd 100644
--- a/ui/src/assets/details.scss
+++ b/ui/src/assets/details.scss
@@ -18,7 +18,7 @@
 
   .handle {
     background-color: hsl(215, 1%, 95%);
-    border: 1px solid rgba(0,0,0,0.1);
+    border: 1px solid rgba(0, 0, 0, 0.1);
     border-bottom: none;
     cursor: row-resize;
     // Disable user selection since this handle is draggable to resize the
@@ -36,7 +36,7 @@
       overflow: hidden;
 
       .tab {
-        font-family: 'Roboto Condensed', sans-serif;
+        font-family: "Roboto Condensed", sans-serif;
         color: #3c4b5d;
         padding: 3px 10px 0 10px;
         margin-top: 3px;
@@ -69,12 +69,12 @@
       font-size: 24px;
       margin-right: 5px;
       margin-top: 1px;
-      &:hover{
+      &:hover {
         cursor: pointer;
       }
       &[disabled] {
         color: rgb(219, 219, 219);
-        &:hover{
+        &:hover {
           cursor: default;
         }
       }
@@ -86,7 +86,7 @@
     }
 
     .handle-title {
-      font-family: 'Roboto Condensed', sans-serif;
+      font-family: "Roboto Condensed", sans-serif;
       font-weight: 300;
       color: #3c4b5d;
       margin-left: 5px;
@@ -94,11 +94,10 @@
       font-size: 13px;
     }
   }
-
 }
 
 .details-panel {
-  font-family: 'Roboto Condensed', sans-serif;
+  font-family: "Roboto Condensed", sans-serif;
   font-weight: 300;
   color: #3c4b5d;
 
@@ -128,8 +127,9 @@
     &.aggregation {
       padding-top: 5px;
       display: grid;
-      grid-template-areas: "description range"
-                            "heading heading";
+      grid-template-areas:
+        "description range"
+        "heading heading";
       grid-template-columns: 1fr auto;
       .states {
         font-size: 11px;
@@ -146,7 +146,6 @@
             min-width: fit-content;
           }
         }
-
       }
       .time-range {
         text-align: right;
@@ -244,7 +243,8 @@
     word-wrap: break-word;
     padding: 0 10px;
     tr:hover {
-      td, th {
+      td,
+      th {
         background-color: hsl(214, 22%, 90%);
 
         &.no-highlight {
@@ -279,9 +279,9 @@
     font-size: 0.875rem;
     padding-left: 1rem;
     padding-right: 1rem;
-    padding-top: .5rem;
-    padding-bottom: .5rem;
-    border-radius: .25rem;
+    padding-top: 0.5rem;
+    padding-bottom: 0.5rem;
+    border-radius: 0.25rem;
     margin-top: 12px;
     margin-left: 10px;
   }
@@ -348,7 +348,7 @@
   display: flex;
   flex-direction: column;
   height: 100%;
-  font-family: 'Roboto Condensed', sans-serif;
+  font-family: "Roboto Condensed", sans-serif;
   font-weight: 300;
   color: #3c4b5d;
 
@@ -365,20 +365,20 @@
   }
 
   button {
-   background: #262f3c;
-   color: white;
-   border-radius: 10px;
-   font-size: 10px;
-   height: 22px;
-   line-height: 18px;
-   min-width: 7em;
-   margin: auto 0 auto 1rem;
+    background: #262f3c;
+    color: white;
+    border-radius: 10px;
+    font-size: 10px;
+    height: 22px;
+    line-height: 18px;
+    min-width: 7em;
+    margin: auto 0 auto 1rem;
   }
 
-  input[type=text] {
+  input[type="text"] {
     flex-grow: 1;
     border-radius: 4px;
-    border:1px solid #dcdcdc;
+    border: 1px solid #dcdcdc;
     padding: 3px;
     margin: 0 10px;
     &:focus {
@@ -401,7 +401,7 @@
   height: 100%;
   display: grid;
   grid-template-rows: auto 1fr;
-  font-family: 'Roboto Condensed', sans-serif;
+  font-family: "Roboto Condensed", sans-serif;
   user-select: text;
 
   header {
@@ -436,7 +436,7 @@
       display: flex;
       align-items: center;
 
-      box-shadow: 0 2px 6px rgba(25,25,25,0.2);
+      box-shadow: 0 2px 6px rgba(25, 25, 25, 0.2);
 
       .chips .chip {
         display: inline-block;
@@ -473,65 +473,79 @@
     color: grey;
   }
 
-    .rows {
-      position: relative;
-      direction: ltr;
+  .rows {
+    position: relative;
+    direction: ltr;
+    width: 100%;
+
+    .row {
+      @include transition();
+      position: absolute;
       width: 100%;
+      height: 20px;
+      line-height: 20px;
+      background-color: hsl(214, 22%, 100%);
 
-      .row {
-        @include transition();
-        position: absolute;
-        width: 100%;
-        height: 20px;
-        line-height: 20px;
-        background-color: hsl(214, 22%, 100%);
-
-        &.D { color: hsl(122, 20%, 40%); }
-        &.V { color: hsl(122, 20%, 30%); }
-        &.I { color: hsl(0, 0%, 20%); }
-        &.W { color: hsl(45, 60%, 45%); }
-        &.E { color: hsl(4, 90%, 58%); }
-        &.F { color: hsl(291, 64%, 42%); }
-        &.stale { color: #aaa; }
-        &:nth-child(even) {
-            background-color: hsl(214, 22%, 95%);
+      &.D {
+        color: hsl(122, 20%, 40%);
+      }
+      &.V {
+        color: hsl(122, 20%, 30%);
+      }
+      &.I {
+        color: hsl(0, 0%, 20%);
+      }
+      &.W {
+        color: hsl(45, 60%, 45%);
+      }
+      &.E {
+        color: hsl(4, 90%, 58%);
+      }
+      &.F {
+        color: hsl(291, 64%, 42%);
+      }
+      &.stale {
+        color: #aaa;
+      }
+      &:nth-child(even) {
+        background-color: hsl(214, 22%, 95%);
+      }
+      &:hover {
+        background-color: hsl(214, 22%, 90%);
+      }
+      .cell {
+        font-size: 11px;
+        font-family: var(--monospace-font);
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        padding-left: 10px;
+        padding-right: 10px;
+        display: inline-block;
+        &:first-child {
+          padding-left: 5px;
         }
-        &:hover {
-          background-color: hsl(214, 22%, 90%);
+        &:last-child {
+          padding-right: 5px;
         }
-        .cell {
-          font-size: 11px;
-          font-family: var(--monospace-font);
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          padding-left: 10px;
-          padding-right: 10px;
-          display: inline-block;
-          &:first-child {
-            padding-left: 5px;
-          }
-          &:last-child {
-            padding-right: 5px;
-          }
-          &:nth-child(1) {
-            width: 110px;
-            text-overflow: clip;
-            text-align: right;
-          }
-          &:nth-child(2) {
-            width: 20px;
-          }
-          &:nth-child(3) {
-            width: 15%;
-          }
-          &:nth-child(4) {
-            width: calc(100% - 110px - 20px - 15%);
-          }
-          &:only-child {
-            width: 100%;
-          }
+        &:nth-child(1) {
+          width: 110px;
+          text-overflow: clip;
+          text-align: right;
+        }
+        &:nth-child(2) {
+          width: 20px;
+        }
+        &:nth-child(3) {
+          width: 15%;
+        }
+        &:nth-child(4) {
+          width: calc(100% - 110px - 20px - 15%);
+        }
+        &:only-child {
+          width: 100%;
         }
       }
+    }
   }
 }
diff --git a/ui/src/assets/flags_page.scss b/ui/src/assets/flags_page.scss
index 3750dbd..a23c60f 100644
--- a/ui/src/assets/flags_page.scss
+++ b/ui/src/assets/flags_page.scss
@@ -33,7 +33,7 @@
     border: 1px solid rgb(218, 220, 224);
     border-radius: 3px;
     color: rgb(25, 103, 210);
-    font-size: .8125rem;
+    font-size: 0.8125rem;
     padding: 8px 12px;
     cursor: pointer;
     font-weight: 500;
@@ -54,9 +54,9 @@
     background: white;
     border: 1px solid rgb(25, 103, 210);
     color: rgb(25, 103, 210);
-    font-size: .8125rem;
+    font-size: 0.8125rem;
     height: 1.625rem;
-    letter-spacing: .01em;
+    letter-spacing: 0.01em;
     max-width: 150px;
     text-align-last: center;
     width: 100%;
@@ -70,4 +70,3 @@
     font-size: smaller;
   }
 }
-
diff --git a/ui/src/assets/hiring_banner.scss b/ui/src/assets/hiring_banner.scss
index 75a997e..a6807df 100644
--- a/ui/src/assets/hiring_banner.scss
+++ b/ui/src/assets/hiring_banner.scss
@@ -1,5 +1,5 @@
 .hiring-banner {
-  font-family: 'Raleway', sans-serif;
+  font-family: "Raleway", sans-serif;
   font-size: 12px;
   background: #db4634;
   box-shadow: 0 0 3px rgba(0, 0, 0, 30%);
diff --git a/ui/src/assets/home_page.scss b/ui/src/assets/home_page.scss
index f76137c..4d3f5a8 100644
--- a/ui/src/assets/home_page.scss
+++ b/ui/src/assets/home_page.scss
@@ -31,27 +31,29 @@
       font-size: 60px;
       margin: 25px;
       text-align: center;
-      font-family: 'Raleway', sans-serif;
+      font-family: "Raleway", sans-serif;
       font-weight: 100;
       color: #333;
     }
 
     .channel-select {
-      font-family: 'Roboto', sans-serif;
+      font-family: "Roboto", sans-serif;
       font-size: 1.2rem;
       font-weight: 200;
       margin-top: 3em;
       --chan-width: 100px;
       --chan-num: 2;
 
-      input[type=radio] {
+      input[type="radio"] {
         width: 0;
         height: 0;
         margin: 0;
         padding: 0;
         -moz-appearance: none;
         -webkit-appearance: none;
-        &:nth-of-type(1):checked ~ .highlight { margin-left: 0; }
+        &:nth-of-type(1):checked ~ .highlight {
+          margin-left: 0;
+        }
         &:nth-of-type(2):checked ~ .highlight {
           margin-left: 100px;
           background-color: hsl(54, 100%, 40%);
@@ -86,7 +88,7 @@
         z-index: 2;
         text-transform: uppercase;
         font-size: 16px;
-        font-family: 'Raleway';
+        font-family: "Raleway";
         font-weight: 400;
         letter-spacing: 0.3px;
       }
@@ -96,7 +98,10 @@
         height: 100%;
         position: absolute;
         background: hsla(122, 45%, 45%, 0.99);
-        background-image: linear-gradient(rgba(255, 255, 255, 0.2), transparent);
+        background-image: linear-gradient(
+          rgba(255, 255, 255, 0.2),
+          transparent
+        );
         top: 0;
         left: 0;
         z-index: 1;
@@ -110,17 +115,19 @@
         color: #da4534;
         font-weight: 400;
         @include transition();
-        &.show { opacity: 1; }
+        &.show {
+          opacity: 1;
+        }
       }
-    }  // .channel-select
-  }  // .home-page-center
+    } // .channel-select
+  } // .home-page-center
 
   .privacy {
     grid-area: footer;
     text-decoration: none;
-    font-family: 'Roboto', sans-serif;
+    font-family: "Roboto", sans-serif;
     font-weight: 200;
     color: #333;
     font-size: 15px;
   }
-}  // .home-page
+} // .home-page
diff --git a/ui/src/assets/metrics_page.scss b/ui/src/assets/metrics_page.scss
index e9ccf58..3ed881c 100644
--- a/ui/src/assets/metrics_page.scss
+++ b/ui/src/assets/metrics_page.scss
@@ -14,7 +14,7 @@
 
 .metrics-page {
   padding: 30px;
-  font-family: 'Raleway', sans-serif;
+  font-family: "Raleway", sans-serif;
   overflow-y: auto;
 
   .metric-run-button {
@@ -23,12 +23,12 @@
     border-radius: 4px;
     padding: 5px 10px;
     font-weight: bold;
-    font-family: 'Raleway';
+    font-family: "Raleway";
   }
 
   select {
     margin: 10px;
-    font-family: 'Raleway';
+    font-family: "Raleway";
     font-size: 1em;
     border: 1px solid black;
     background-color: #eee;
@@ -37,12 +37,12 @@
   pre {
     background-color: #eee;
     padding: 20px;
-    font-family: 'Roboto Mono';
+    font-family: "Roboto Mono";
     line-height: 1.5em;
     border-radius: 5px;
     overflow-x: auto;
     &.metric-error {
-      color: #EF6C00;
+      color: #ef6c00;
     }
   }
 }
diff --git a/ui/src/assets/modal.scss b/ui/src/assets/modal.scss
index eaea810..76d3cea 100644
--- a/ui/src/assets/modal.scss
+++ b/ui/src/assets/modal.scss
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 // The opacity changes are only transitional. Once the `modalFadeOut` animation
 // reaches the end, the Mithril component that renders .modal-backdrop
 // (and .modal-dialog) is fully destroyed and removed from the DOM.
@@ -20,13 +19,21 @@
 // hooking the onanimationend events to synchronize the Mithril removal with
 // the end of the CSS animation.
 @keyframes modalFadeOut {
-  from { opacity: 1; }
-  to { opacity: 0; }
+  from {
+    opacity: 1;
+  }
+  to {
+    opacity: 0;
+  }
 }
 
 @keyframes modalFadeIn {
-  from { opacity: 0; }
-  to { opacity: 1; }
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
 }
 
 .modal-backdrop {
@@ -71,7 +78,7 @@
     transform: translate(-50%, 0);
   }
 
-  >header {
+  > header {
     display: flex;
     justify-content: space-between;
     align-items: center;
@@ -79,7 +86,7 @@
     h2 {
       margin-top: 0;
       margin-bottom: 0;
-      font-family: 'Raleway', sans-serif;
+      font-family: "Raleway", sans-serif;
       font-weight: 600;
       font-size: 1.25rem;
       line-height: 1.25;
@@ -91,14 +98,14 @@
       background: transparent;
       border: 0;
     }
-  }  // header
+  } // header
 
   main {
     font-size: 1rem;
     margin-top: 2rem;
     margin-bottom: 2rem;
     line-height: 1.5;
-    color: rgba(0,0,0,.8);
+    color: rgba(0, 0, 0, 0.8);
 
     .small-font {
       font-size: 0.9rem;
@@ -108,16 +115,16 @@
   footer {
     display: flex;
     justify-content: space-around;
-  }  // footer
+  } // footer
 
   .modal-btn {
-    font-size: .875rem;
+    font-size: 0.875rem;
     padding-left: 1rem;
     padding-right: 1rem;
-    padding-top: .5rem;
-    padding-bottom: .5rem;
+    padding-top: 0.5rem;
+    padding-bottom: 0.5rem;
     background-color: #e6e6e6;
-    color: rgba(0,0,0,.8);
+    color: rgba(0, 0, 0, 0.8);
     border: 2px solid transparent;
     border-radius: 4px;
     cursor: pointer;
@@ -125,17 +132,23 @@
     overflow: visible;
     margin: 5px;
     transform: translateZ(0);
-    transition: border-color .25s var(--anim-easing),
-                background-color .25s var(--anim-easing);
+    transition: border-color 0.25s var(--anim-easing),
+      background-color 0.25s var(--anim-easing);
 
-    &:focus { border-color: #03A9F4;}
-    &:hover { background-color: #ececec; }
+    &:focus {
+      border-color: #03a9f4;
+    }
+    &:hover {
+      background-color: #ececec;
+    }
   }
 
   .modal-btn-primary {
     background-color: hsl(215deg, 22%, 19%);
     color: #fff;
-    &:hover { background-color: hsl(215deg, 22%, 35%) }
+    &:hover {
+      background-color: hsl(215deg, 22%, 35%);
+    }
   }
 }
 
@@ -160,7 +173,8 @@
   font-size: 13px;
 }
 
-.modal-logs, .modal-bash {
+.modal-logs,
+.modal-bash {
   white-space: pre-wrap;
   border: 1px solid #999;
   background: #eee;
diff --git a/ui/src/assets/perfetto.scss b/ui/src/assets/perfetto.scss
index 2b4dedb..c6d03b4 100644
--- a/ui/src/assets/perfetto.scss
+++ b/ui/src/assets/perfetto.scss
@@ -12,16 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-@import 'typefaces';
-@import 'common';
-@import 'home_page';
-@import 'analyze_page';
-@import 'metrics_page';
-@import 'sidebar';
-@import 'topbar';
-@import 'record';
-@import 'modal';
-@import 'details';
-@import 'trace_info_page';
-@import 'flags_page';
-@import 'hiring_banner';
+@import "typefaces";
+@import "common";
+@import "home_page";
+@import "analyze_page";
+@import "metrics_page";
+@import "sidebar";
+@import "topbar";
+@import "record";
+@import "modal";
+@import "details";
+@import "trace_info_page";
+@import "flags_page";
+@import "hiring_banner";
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index a9e6b90..529e57e 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -35,8 +35,9 @@
   background-color: #fff;
   display: grid;
   grid-template-rows: auto 1fr;
-  grid-template-areas: "header"
-                       "content";
+  grid-template-areas:
+    "header"
+    "content";
   overflow: hidden;
   z-index: 6;
 
@@ -52,7 +53,7 @@
     height: 100%;
     text-align: center;
     padding: 180px 30px;
-    font-family: 'Raleway', sans-serif;
+    font-family: "Raleway", sans-serif;
     font-size: 25px;
   }
 }
@@ -67,13 +68,12 @@
   }
 
   .record-modal-section {
-
     display: flex;
     flex-direction: row;
 
     .logo-wrapping {
       border-radius: 50%;
-      background-color: #F0F0F0;
+      background-color: #f0f0f0;
       width: 150px;
       height: 150px;
       display: inline-block;
@@ -81,7 +81,7 @@
       align-self: center;
 
       i.material-icons {
-        color: #0000FF;
+        color: #0000ff;
         font-size: 150px;
       }
     }
@@ -112,7 +112,7 @@
         padding-top: 15px;
         align-self: start;
         font-size: 1.2rem;
-        color: #0000FF;
+        color: #0000ff;
       }
 
       h4 {
@@ -125,7 +125,7 @@
         color: #000000;
       }
 
-      input[type=text] {
+      input[type="text"] {
         flex-grow: 1;
         border-radius: 4px;
         border: 1px solid #dcdcdc;
@@ -141,13 +141,15 @@
     }
   }
 
-  .record-modal-button, .record-modal-button-high, .record-modal-logo-button {
-    font-size: .875rem;
+  .record-modal-button,
+  .record-modal-button-high,
+  .record-modal-logo-button {
+    font-size: 0.875rem;
     padding-left: 1rem;
     padding-right: 1rem;
-    padding-top: .5rem;
-    padding-bottom: .5rem;
-    background-color: #0000FF;
+    padding-top: 0.5rem;
+    padding-bottom: 0.5rem;
+    background-color: #0000ff;
     color: #ffffff;
     cursor: pointer;
     -webkit-appearance: button;
@@ -160,13 +162,14 @@
     -webkit-backface-visibility: hidden;
     backface-visibility: hidden;
     transform: translateZ(0);
-    transition: transform .25s ease-out;
+    transition: transform 0.25s ease-out;
     align-self: end;
     text-align: center;
   }
 
-  .record-modal-button, .record-modal-button-high {
-    border-radius: .25rem;
+  .record-modal-button,
+  .record-modal-button-high {
+    border-radius: 0.25rem;
     border-style: none;
     border-width: 0;
   }
@@ -224,14 +227,14 @@
       width: auto;
       height: 50px;
       margin: 0;
-      >* {
+      > * {
         @include transition(0.2s);
         cursor: pointer;
         border-radius: 10px;
         margin: 10px;
         text-align: center;
         background-color: #eee;
-        font-family: 'Raleway', sans-serif;
+        font-family: "Raleway", sans-serif;
         font-size: 17px;
         @media (max-width: 1280px) {
           font-size: 1.6vw;
@@ -265,12 +268,14 @@
         align-items: center;
       }
 
-      label, select, button {
+      label,
+      select,
+      button {
         font-weight: 300;
         margin: 3px;
         color: #333;
         font-size: 17px;
-        font-family: 'Roboto', sans-serif;
+        font-family: "Roboto", sans-serif;
         align-items: center;
 
         &.error-label {
@@ -289,7 +294,8 @@
         border-radius: 20px;
         padding: 4px;
         height: 30px;
-        &:hover, &:active {
+        &:hover,
+        &:active {
           box-shadow: 0 0 4px 0 #ccc;
           background-color: #fafafa;
         }
@@ -306,7 +312,7 @@
     margin-bottom: 5px;
     background: #f9eeba;
     padding: 10px;
-    font-family: 'Roboto', sans-serif;
+    font-family: "Roboto", sans-serif;
     font-size: 14px;
     line-height: 20px;
   }
@@ -317,7 +323,8 @@
     border-radius: 0;
     border: 1px solid #eee;
     outline: none;
-    &:hover, &:active {
+    &:hover,
+    &:active {
       box-shadow: 0 0 6px #ccc;
     }
   }
@@ -326,14 +333,16 @@
 // The left-hand-side menu with 'Cpu', 'Memory' etc.
 .record-menu {
   grid-area: sidebar;
-  .rec { color: #ee3326; }
+  .rec {
+    color: #ee3326;
+  }
 
   background-color: #fcfcfc;
   border-right: 1px solid #eee;
   padding-bottom: 1em;
 
   header {
-    font-family: 'Roboto', sans-serif;
+    font-family: "Roboto", sans-serif;
     font-size: 14px;
     font-weight: 700;
     margin: 1em;
@@ -345,7 +354,9 @@
     padding: 0;
   }
 
-  a, a:link, a:visited {
+  a,
+  a:link,
+  a:visited {
     text-decoration: none;
   }
 
@@ -355,7 +366,7 @@
     padding: 0 1em;
     font-size: 15px;
     letter-spacing: 0.5px;
-    font-family: 'Raleway', sans-serif;
+    font-family: "Raleway", sans-serif;
     font-weight: 600;
     color: #666;
     display: grid;
@@ -377,7 +388,7 @@
     }
 
     .title {
-      transition: line-height .25s ease;
+      transition: line-height 0.25s ease;
       grid-area: title;
       line-height: 55px;
       display: block;
@@ -394,28 +405,30 @@
 
     &:hover {
       background-color: hsl(214, 0%, 90%);
-      .title { line-height: 50px; }
+      .title {
+        line-height: 50px;
+      }
       .sub {
         opacity: 1;
         transition-duration: 0.25s;
-        transition-delay: 0.0s;
+        transition-delay: 0s;
       }
     }
 
     &.active {
       background-color: hsl(214, 80%, 70%);
-      .title, .sub {
+      .title,
+      .sub {
         color: white;
       }
     }
-  }  // li
+  } // li
 
   &.disabled {
-    opacity: 0.50;
+    opacity: 0.5;
     pointer-events: none;
   }
-}  // record-menu
-
+} // record-menu
 
 .record-section {
   grid-area: section;
@@ -463,7 +476,7 @@
     margin-right: 10px;
     text-align: center;
     justify-items: center;
-    font-family: 'Raleway', sans-serif;
+    font-family: "Raleway", sans-serif;
     padding: 7px;
 
     &:hover:enabled {
@@ -516,7 +529,7 @@
       line-height: 36px;
       padding: 0 10px;
       font-size: 18px;
-      font-family: 'Roboto Condensed', sans-serif;
+      font-family: "Roboto Condensed", sans-serif;
       font-weight: 300;
       color: #666;
       flex-grow: 1;
@@ -529,7 +542,7 @@
       }
       &::placeholder {
         color: #b4b7ba;
-        font-family: 'Raleway', sans-serif;
+        font-family: "Raleway", sans-serif;
         font-weight: 400;
       }
     }
@@ -538,16 +551,20 @@
   // By default space all section elements by the same amount.
   --record-section-padding: 20px;
 
-  >* {
+  > * {
     padding-left: var(--record-section-padding);
     padding-right: var(--record-section-padding);
-    &:first-child { padding-top: 20px; }
-    &:last-child { padding-bottom: 20px; }
+    &:first-child {
+      padding-top: 20px;
+    }
+    &:last-child {
+      padding-bottom: 20px;
+    }
   }
 
-  >header {
+  > header {
     text-align: center;
-    font-family: 'Raleway', sans-serif;
+    font-family: "Raleway", sans-serif;
     font-size: 20px;
     padding: 15px 10px;
     color: #333;
@@ -577,7 +594,7 @@
       background-color: #f9f9f9;
     }
 
-    >img {
+    > img {
       transition: filter 0.2s ease, opacity 0.2s ease;
       grid-area: img;
       width: 210px;
@@ -588,25 +605,27 @@
     }
 
     &:hover {
-      >img { opacity: 1; }
-      >label {
+      > img {
+        opacity: 1;
+      }
+      > label {
         color: #333;
-        input[type=checkbox]::after {
+        input[type="checkbox"]::after {
           background: hsl(207, 60%, 60%);
         }
       }
-    }  // :hover
+    } // :hover
 
-    >label {
+    > label {
       grid-area: label;
       cursor: pointer;
-      font-family: 'Roboto' , sans-serif;
+      font-family: "Roboto", sans-serif;
       font-size: 20px;
       font-weight: 400;
       color: #999;
 
       // The per-probe on-off switch.
-      input[type=checkbox] {
+      input[type="checkbox"] {
         -moz-appearance: none;
         -webkit-appearance: none;
         cursor: pointer;
@@ -634,8 +653,8 @@
           height: 26px;
           border-radius: 100px;
           background: #f5f5f5;
-          box-shadow: 0 3px 3px rgba(0,0,0,0.15);
-          content: '';
+          box-shadow: 0 3px 3px rgba(0, 0, 0, 0.15);
+          content: "";
           transition: all 0.3s ease;
         }
         &:checked {
@@ -648,11 +667,11 @@
           left: 20px;
           background: #27303d;
         }
-      }  // checkbox
-    }  // label
+      } // checkbox
+    } // label
 
     // The content of the probe section.
-    >div {
+    > div {
       grid-area: descr;
       font-size: 14px;
       font-weight: 200;
@@ -676,35 +695,39 @@
         visibility: visible;
         max-height: 100vh;
       }
-      >label span { color: #4e80b7; }
-      >img {
+      > label span {
+        color: #4e80b7;
+      }
+      > img {
         filter: saturate(1);
         opacity: 1;
       }
     }
-  }  // probe
+  } // probe
 
   .toggle {
     transition: color 0.2s ease;
     padding-top: var(--record-section-padding);
 
     &:hover {
-      >img { opacity: 1; }
-      >label {
+      > img {
+        opacity: 1;
+      }
+      > label {
         color: #333;
-        input[type=checkbox]::after {
+        input[type="checkbox"]::after {
           background: hsl(207, 60%, 60%);
         }
       }
-    }  // :hover
+    } // :hover
 
-    >label {
+    > label {
       cursor: pointer;
       font-size: 14px;
       color: var(--record-text-color);
 
       // The per-probe on-off switch.
-      input[type=checkbox] {
+      input[type="checkbox"] {
         -moz-appearance: none;
         -webkit-appearance: none;
         cursor: pointer;
@@ -732,8 +755,8 @@
           height: 20px;
           border-radius: 100px;
           background: #f5f5f5;
-          box-shadow: 0 3px 3px rgba(0,0,0,0.15);
-          content: '';
+          box-shadow: 0 3px 3px rgba(0, 0, 0, 0.15);
+          content: "";
           transition: all 0.3s ease;
         }
         &:checked {
@@ -746,16 +769,16 @@
           left: 12px;
           background: #27303d;
         }
-      }  // checkbox
-    }  // label
+      } // checkbox
+    } // label
 
     // The content of the toggle section.
-    >div.descr {
+    > div.descr {
       padding-left: 36px;
       font-size: 12px;
       color: #666;
     }
-  }  // toggle
+  } // toggle
 
   // The three "Stop when full", "Ring buffer", "Long trace" buttons.
   .record-mode {
@@ -765,20 +788,20 @@
     grid-template-rows: 1fr;
     padding-top: 0;
 
-    input[type=radio] {
+    input[type="radio"] {
       appearance: none;
       -webkit-appearance: none;
       display: none;
     }
 
-    >* {
+    > * {
       @include transition(0.2s);
       cursor: pointer;
       border-radius: 15px;
       margin: 5px;
       text-align: center;
       background-color: #eee;
-      font-family: 'Raleway', sans-serif;
+      font-family: "Raleway", sans-serif;
       font-size: 20px;
       @media (max-width: 1280px) {
         font-size: 1.6vw;
@@ -799,7 +822,7 @@
         width: 100%;
       }
     }
-  }  // record-mode
+  } // record-mode
 
   // There are two types of sliders:
   // 1) The full-width one (default), e.g. the one used in the main recording
@@ -811,39 +834,41 @@
     display: grid;
     grid-template-columns: 40px 1fr 130px 0;
     grid-template-rows: 30px min-content 1fr;
-    grid-template-areas: "hdr hdr hdr hdr" "descr descr descr descr"
-    "icon slider label unit";
+    grid-template-areas:
+      "hdr hdr hdr hdr" "descr descr descr descr"
+      "icon slider label unit";
     margin-top: var(--record-section-padding);
 
     &.thin {
       grid-template-columns: 1fr 1fr 100px 0;
-      grid-template-areas: "hdr hdr hdr hdr" "descr descr descr descr"
-      "slider slider label unit";
+      grid-template-areas:
+        "hdr hdr hdr hdr" "descr descr descr descr"
+        "slider slider label unit";
     }
 
     &.greyed-out {
       opacity: 0.5;
     }
 
-    >* {
+    > * {
       height: 40px;
       line-height: 40px;
     }
 
-    >header {
+    > header {
       @include transition(0.3s);
       opacity: 0.6;
       color: #333;
       grid-area: hdr;
     }
 
-    &.thin >header {
+    &.thin > header {
       opacity: 1;
       color: var(--record-text-color);
       font-size: 14px;
     }
 
-    &.thin >header.descr {
+    &.thin > header.descr {
       grid-area: descr;
       font-size: 12px;
       color: #666;
@@ -856,19 +881,19 @@
       transition-duration: 0.15s;
     }
 
-    >i {
+    > i {
       grid-area: icon;
       font-size: 32px;
       color: #333;
     }
 
-    input[type=range] {
+    input[type="range"] {
       grid-area: slider;
       width: 100%;
       appearance: none;
       -webkit-appearance: none;
       scroll-snap-type: x mandatory;
-      background-color : transparent;
+      background-color: transparent;
       outline: none;
       margin-left: -10px;
       margin-top: -5px;
@@ -877,7 +902,7 @@
         margin: 10px;
         width: 100%;
         height: 10px;
-        background-color : #ddd;
+        background-color: #ddd;
         border-radius: 4px;
       }
 
@@ -902,11 +927,11 @@
       }
     }
 
-    &.thin input[type=range]::-webkit-slider-runnable-track {
+    &.thin input[type="range"]::-webkit-slider-runnable-track {
       height: 8px;
     }
 
-    &.thin input[type=range]::-webkit-slider-thumb {
+    &.thin input[type="range"]::-webkit-slider-thumb {
       width: 20px;
       border-radius: 100%;
     }
@@ -919,7 +944,7 @@
       padding: 0 5px;
       border-radius: 2px;
       background-color: rgba(255, 255, 255, 60%);
-      font-family: 'Roboto', sans-serif;
+      font-family: "Roboto", sans-serif;
       font-size: 16px;
       font-weight: 100;
       height: 35px;
@@ -932,14 +957,15 @@
         margin: 0;
       }
 
-      &:hover, &:focus {
+      &:hover,
+      &:focus {
         border-bottom-color: hsl(207, 90%, 54%);
-        background-color: hsl(207, 50%, 97%);;
+        background-color: hsl(207, 50%, 97%);
       }
 
       &:invalid {
         border-bottom-color: hsl(9, 90%, 54%);
-        background-color: hsl(9, 50%, 97%);;
+        background-color: hsl(9, 50%, 97%);
       }
     }
 
@@ -979,13 +1005,13 @@
         border-radius: 10px;
         border: 1px solid #eee;
         margin: 0 5px;
-        font-size: .8rem;
+        font-size: 0.8rem;
       }
 
       .checkboxes {
         list-style-type: none;
         padding: 0;
-        font-size: .9rem;
+        font-size: 0.9rem;
 
         li {
           margin: 6px 0;
@@ -1002,7 +1028,8 @@
     outline: none;
     -webkit-appearance: none;
 
-    option, optgroup {
+    option,
+    optgroup {
       @include transition();
       min-height: 25px;
       font-size: 12px;
@@ -1019,7 +1046,7 @@
       }
       &::before {
         display: none;
-        content: '';
+        content: "";
       }
     }
 
@@ -1093,7 +1120,9 @@
     outline: none;
     font-family: var(--monospace-font);
 
-    &::placeholder { color: #aaa; }
+    &::placeholder {
+      color: #aaa;
+    }
   }
 
   textarea.atrace-apps-list {
@@ -1102,11 +1131,12 @@
   }
 
   &.instructions {
-    label, select {
+    label,
+    select {
       font-weight: 100;
       color: #333;
       font-size: 16px;
-      font-family: 'Roboto', sans-serif;
+      font-family: "Roboto", sans-serif;
     }
 
     .note {
@@ -1114,7 +1144,7 @@
       background: #f9eeba;
       margin: var(--record-section-padding);
       padding: 10px;
-      font-family: 'Roboto', sans-serif;
+      font-family: "Roboto", sans-serif;
       font-size: 14px;
       line-height: 20px;
     }
@@ -1126,7 +1156,8 @@
       border: 1px solid #eee;
       outline: none;
 
-      &:hover, &:active {
+      &:hover,
+      &:active {
         box-shadow: 0 0 6px #ccc;
       }
     }
@@ -1137,14 +1168,14 @@
       align-items: center;
       width: auto;
       height: 70px;
-      >* {
+      > * {
         @include transition(0.2s);
         cursor: pointer;
         border-radius: 10px;
         text-align: center;
         margin: 3px;
         background-color: #eee;
-        font-family: 'Raleway', sans-serif;
+        font-family: "Raleway", sans-serif;
         flex-grow: 1;
         font-size: 17px;
         @media (max-width: 1280px) {
@@ -1171,7 +1202,7 @@
       border-radius: 10px;
       text-align: center;
       justify-items: center;
-      font-family: 'Raleway', sans-serif;
+      font-family: "Raleway", sans-serif;
       padding: 7px;
       background-color: hsl(88, 50%, 67%);
 
@@ -1195,16 +1226,17 @@
       background-color: #eee;
     }
   }
-}  // record-section
+} // record-section
 
 .inline-chip {
   @include transition();
-  &:hover, &:active {
+  &:hover,
+  &:active {
     box-shadow: 0 0 2px 0 #ccc;
     background-color: #fafafa;
   }
 
-  >i.material-icons {
+  > i.material-icons {
     color: rgb(60, 60, 60);
     font-size: 14px;
   }
@@ -1217,7 +1249,9 @@
   border-radius: 9px;
 }
 
-a.inline-chip, a.inline-chip:link, a.inline-chip:visited {
+a.inline-chip,
+a.inline-chip:link,
+a.inline-chip:visited {
   text-decoration: none;
   color: var(--record-text-color);
 }
@@ -1231,12 +1265,22 @@
   border-radius: 4px;
   box-shadow: 0 0 12px #999;
 
-  @keyframes ripple{
-    0% { transform: scale(1.00); }
-    30% { transform: scale(1.20); }
-    60% { transform: scale(1.00); }
-    80% { transform: scale(1.30); }
-    100% { transform: scale(1.20); }
+  @keyframes ripple {
+    0% {
+      transform: scale(1);
+    }
+    30% {
+      transform: scale(1.2);
+    }
+    60% {
+      transform: scale(1);
+    }
+    80% {
+      transform: scale(1.3);
+    }
+    100% {
+      transform: scale(1.2);
+    }
   }
 
   &::before {
@@ -1253,7 +1297,7 @@
     }
   }
 
-  >code {
+  > code {
     display: block;
     margin: 10px 5px 20px 20px;
     color: #ccc;
@@ -1269,7 +1313,7 @@
     max-height: 510px;
   }
 
-  >button {
+  > button {
     @include transition();
     display: inline-block;
     position: absolute;
@@ -1281,7 +1325,7 @@
     box-shadow: 0 0 2px rgba(255, 255, 255, 200);
     padding: 5px;
     font-size: 16px;
-    line-height: 13px;  // Deliberately smaller to center the icon.
+    line-height: 13px; // Deliberately smaller to center the icon.
     user-select: none;
 
     &:hover {
@@ -1290,13 +1334,13 @@
     }
   }
 
-  &:active:hover >button:not(:hover) {
+  &:active:hover > button:not(:hover) {
     animation: ripple linear 0.5s;
     background-color: #701d17;
     transform: scale(1.1);
   }
 
-  >button:active:hover {
+  > button:active:hover {
     transform: scale(0.9);
   }
-}  // code-snippet
+} // code-snippet
diff --git a/ui/src/assets/sidebar.scss b/ui/src/assets/sidebar.scss
index 0dabbda..b0a7092 100644
--- a/ui/src/assets/sidebar.scss
+++ b/ui/src/assets/sidebar.scss
@@ -13,291 +13,298 @@
 // limitations under the License.
 
 .sidebar {
-    --sidebar-padding-bottom: 40px;
-    --sidebar-timing: 0.15s;
-    grid-area: sidebar;
-    z-index: 4;
-    background-color: #262f3c;
-    overflow: hidden;
-    width: var(--sidebar-width);
-    display: flex;
-    position: relative;
-    flex-direction: column;
-    transition: margin-left var(--anim-easing) var(--sidebar-timing),
-                visibility linear var(--sidebar-timing);
-    >* {
-        border-bottom: 1px solid #404854;
+  --sidebar-padding-bottom: 40px;
+  --sidebar-timing: 0.15s;
+  grid-area: sidebar;
+  z-index: 4;
+  background-color: #262f3c;
+  overflow: hidden;
+  width: var(--sidebar-width);
+  display: flex;
+  position: relative;
+  flex-direction: column;
+  transition: margin-left var(--anim-easing) var(--sidebar-timing),
+    visibility linear var(--sidebar-timing);
+  > * {
+    border-bottom: 1px solid #404854;
+  }
+  input[type="file"] {
+    display: none;
+  }
+  > header {
+    font-family: "Roboto Condensed", sans-serif;
+    font-weight: 700;
+    font-size: 24px;
+    height: var(--topbar-height);
+    line-height: var(--topbar-height);
+    vertical-align: middle;
+    padding: 0 20px;
+    color: #fff;
+    overflow: visible;
+    .brand {
+      height: 40px;
+      margin-top: 4px;
     }
-    input[type=file] { display:none; }
-    >header {
-        font-family: 'Roboto Condensed', sans-serif;
-        font-weight: 700;
-        font-size: 24px;
-        height: var(--topbar-height);
-        line-height: var(--topbar-height);
-        vertical-align: middle;
-        padding: 0 20px;
-        color: #fff;
-        overflow: visible;
-        .brand {
-          height: 40px;
-          margin-top: 4px;
-        }
-        &::before {
-          z-index: 10;
-        }
-        &.canary::before, &.autopush::before {
-          display: block;
-          position: absolute;
-          font-size: 10px;
-          line-height: 10px;
-          font-family: 'Raleway', sans-serif;
-          left: 155px;
-          top: 7px;
-        }
-        &.canary::before {
-          content: 'CANARY';
-          color: #ffd700;
-        }
-        &.autopush::before {
-          content: 'AUTOPUSH';
-          color: #aed581;
-        }
+    &::before {
+      z-index: 10;
     }
-    .sidebar-button {
-      position: fixed;
-      z-index: 5;
-      background-color: #262f3c;
-      height: var(--topbar-height);
-      left: calc(var(--sidebar-width) - 50px);
-      border-radius: 0 5px 5px 0;
-      border-bottom: inherit;
-      visibility: visible;  // So stays visible when the sidebar is hidden.
-      transition: left var(--anim-easing) var(--sidebar-timing);
-      width: 48px;
-      overflow: hidden;
-      >button {
-        vertical-align: middle;
-      }
-    }
-    &.hide-sidebar {
-      visibility: hidden;
-      margin-left: calc(var(--sidebar-width) * -1);
-      .sidebar-button {
-        left: 0;
-        background-color: transparent;
-        border-radius: unset;
-        border-bottom: none;
-        color: #aaaaaa;
-      }
-    }
-    .sidebar-scroll {
-      overflow-y: auto;
-      flex: 1;
-      &::-webkit-scrollbar {
-        width: 0.5em;
-      }
-      &::-webkit-scrollbar-track {
-        background-color: #19212b;
-        border-radius: 2px;
-      }
-      &::-webkit-scrollbar-thumb {
-        background: #b4b7ba6e;
-        border-radius: 2px;
-      }
-      >.sidebar-scroll-container {
-        position: relative;
-        min-height: 100%;
-        padding-bottom: var(--sidebar-padding-bottom);
-
-        >section {
-            @include transition();
-            padding: 20px 0;
-            max-height: 80px;
-            .section-header {
-                cursor: pointer;
-                >h1,
-                >h2 {
-                    font-family: 'Raleway', sans-serif;
-                    letter-spacing: 0.25px;
-                    overflow: hidden;
-                    text-overflow: ellipsis;
-                    white-space: nowrap;
-                    margin: 0 24px;
-                }
-                >h1 {
-                    color: #fff;
-                    font-size: 15px;
-                    font-weight: 500;
-                }
-                >h2 {
-                    @include transition();
-                    color: rgba(255, 255, 255, 0.5);
-                    font-size: 12px;
-                    margin-top: 8px;
-                    font-weight: 400;
-                }
-                &:before {
-                  @include material-icon('expand_more');
-                  float: right;
-                  color: rgba(255, 255, 255, 0.3);
-                  margin-right: 12px;
-                  margin-top: -4px;
-                }
-            }
-            &:hover {
-                background-color: #373f4b;
-            }
-            &.expanded {
-                background-color: #19212b;
-                max-height: unset;
-                .section-header {
-                  h2 {
-                    opacity: 0;
-                  }
-
-                  &:before {
-                    content: 'expand_less';
-                  }
-                }
-
-                .section-content {
-                    pointer-events: inherit;
-                    opacity: 1;
-                }
-            }
-        }
-
-        .section-content {
-            pointer-events: none;
-            @include transition();
-            opacity: 0;
-            color: #b4b7ba;
-            a {
-                color: #b4b7ba;
-            }
-            ul {
-                list-style-type: none;
-                margin: 0;
-                padding: 0;
-            }
-            li {
-                @include transition();
-                a {
-                    line-height: 24px;
-                    font-size: 14px;
-                    font-weight: 400;
-                    font-family: 'Raleway', sans-serif;
-                    letter-spacing: 0.5px;
-                    padding: 5px 24px;
-                    text-decoration: none;
-                    display: block;
-                    &.pending {
-                      color: rgba(255, 255, 255, 0.3);
-                      &::after {
-                        content: ' ';
-                        display: inline-block;
-                        vertical-align: middle;
-                        box-sizing: border-box;
-                        width: 18px;
-                        height: 18px;
-                        margin-left: 10px;
-                        border-radius: 50%;
-                        border: 2px solid #b4b7ba;
-                        border-color: #b4b7ba transparent;
-                        animation: pending-spinner 1.25s linear infinite;
-                      }
-                      @keyframes pending-spinner {
-                        0% { transform: rotate(0deg); }
-                        100% { transform: rotate(360deg); }
-                      }
-                    }
-                    &[disabled] {
-                      text-decoration: line-through;
-                    }
-                }
-                .material-icons {
-                    margin-right: 10px;
-                }
-                &:hover {
-                    background-color: #373f4b;
-                }
-                .trace-file-name {
-                  white-space: break-spaces;
-                  font-family: 'Roboto Condensed', sans-serif;
-                  word-break: break-all;
-                  font-weight: 300;
-                  letter-spacing: 0;
-                  margin-top: -10px;
-                  color: #fff;
-                }
-            }
-        }
-      }
-    }
-
-    .sidebar-footer {
+    &.canary::before,
+    &.autopush::before {
+      display: block;
       position: absolute;
-      bottom: 0;
-      width: 100%;
-      padding: 2px 10px;
-      display: grid;
-      height: - var(--sidebar-padding-bottom);
-      grid-template-columns: repeat(4, min-content);
-      grid-gap: 10px;
+      font-size: 10px;
+      line-height: 10px;
+      font-family: "Raleway", sans-serif;
+      left: 155px;
+      top: 7px;
+    }
+    &.canary::before {
+      content: "CANARY";
+      color: #ffd700;
+    }
+    &.autopush::before {
+      content: "AUTOPUSH";
+      color: #aed581;
+    }
+  }
+  .sidebar-button {
+    position: fixed;
+    z-index: 5;
+    background-color: #262f3c;
+    height: var(--topbar-height);
+    left: calc(var(--sidebar-width) - 50px);
+    border-radius: 0 5px 5px 0;
+    border-bottom: inherit;
+    visibility: visible; // So stays visible when the sidebar is hidden.
+    transition: left var(--anim-easing) var(--sidebar-timing);
+    width: 48px;
+    overflow: hidden;
+    > button {
+      vertical-align: middle;
+    }
+  }
+  &.hide-sidebar {
+    visibility: hidden;
+    margin-left: calc(var(--sidebar-width) * -1);
+    .sidebar-button {
+      left: 0;
+      background-color: transparent;
+      border-radius: unset;
+      border-bottom: none;
+      color: #aaaaaa;
+    }
+  }
+  .sidebar-scroll {
+    overflow-y: auto;
+    flex: 1;
+    &::-webkit-scrollbar {
+      width: 0.5em;
+    }
+    &::-webkit-scrollbar-track {
+      background-color: #19212b;
+      border-radius: 2px;
+    }
+    &::-webkit-scrollbar-thumb {
+      background: #b4b7ba6e;
+      border-radius: 2px;
+    }
+    > .sidebar-scroll-container {
+      position: relative;
+      min-height: 100%;
+      padding-bottom: var(--sidebar-padding-bottom);
 
-      > button {
-        color: hsl(217, 39%, 94%);
-        i {
-          font-size: 24px;
+      > section {
+        @include transition();
+        padding: 20px 0;
+        max-height: 80px;
+        .section-header {
+          cursor: pointer;
+          > h1,
+          > h2 {
+            font-family: "Raleway", sans-serif;
+            letter-spacing: 0.25px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            margin: 0 24px;
+          }
+          > h1 {
+            color: #fff;
+            font-size: 15px;
+            font-weight: 500;
+          }
+          > h2 {
+            @include transition();
+            color: rgba(255, 255, 255, 0.5);
+            font-size: 12px;
+            margin-top: 8px;
+            font-weight: 400;
+          }
+          &:before {
+            @include material-icon("expand_more");
+            float: right;
+            color: rgba(255, 255, 255, 0.3);
+            margin-right: 12px;
+            margin-top: -4px;
+          }
         }
-
         &:hover {
-          color: hsl(45, 100%, 48%);
+          background-color: #373f4b;
+        }
+        &.expanded {
+          background-color: #19212b;
+          max-height: unset;
+          .section-header {
+            h2 {
+              opacity: 0;
+            }
+
+            &:before {
+              content: "expand_less";
+            }
+          }
+
+          .section-content {
+            pointer-events: inherit;
+            opacity: 1;
+          }
         }
       }
 
-      > .dbg-info-square {
-        width: 24px;
-        height: 22px;
-        line-height: 22px;
-        margin: 1px 0;
-        background: #12161b;
-        color: #4e71b3;
-        border-radius: 5px;
-        font-size: 12px;
-        text-align: center;
-        &.green {
-          background: #7aca75;
-          color: #12161b;
-        }
-        &.amber {
-          background: #FFC107;
-          color: #333;
-        }
-        &.red {
-          background: #d32f2f;
-          color: #fff;
-        }
-        > div {
-          font-size: 10px;
-          line-height: 11px;
-        }
-      }
-
-      .version {
-        position: absolute;
-        right: 8px;
-        bottom: 3px;
-        font-size: 12px;
-        font-family: 'Roboto Condensed', sans-serif;
+      .section-content {
+        pointer-events: none;
+        @include transition();
+        opacity: 0;
+        color: #b4b7ba;
         a {
-          color: rgba(255, 255, 255, 0.5);
-          text-decoration: none;
+          color: #b4b7ba;
         }
-        margin-top: 11px;
+        ul {
+          list-style-type: none;
+          margin: 0;
+          padding: 0;
+        }
+        li {
+          @include transition();
+          a {
+            line-height: 24px;
+            font-size: 14px;
+            font-weight: 400;
+            font-family: "Raleway", sans-serif;
+            letter-spacing: 0.5px;
+            padding: 5px 24px;
+            text-decoration: none;
+            display: block;
+            &.pending {
+              color: rgba(255, 255, 255, 0.3);
+              &::after {
+                content: " ";
+                display: inline-block;
+                vertical-align: middle;
+                box-sizing: border-box;
+                width: 18px;
+                height: 18px;
+                margin-left: 10px;
+                border-radius: 50%;
+                border: 2px solid #b4b7ba;
+                border-color: #b4b7ba transparent;
+                animation: pending-spinner 1.25s linear infinite;
+              }
+              @keyframes pending-spinner {
+                0% {
+                  transform: rotate(0deg);
+                }
+                100% {
+                  transform: rotate(360deg);
+                }
+              }
+            }
+            &[disabled] {
+              text-decoration: line-through;
+            }
+          }
+          .material-icons {
+            margin-right: 10px;
+          }
+          &:hover {
+            background-color: #373f4b;
+          }
+          .trace-file-name {
+            white-space: break-spaces;
+            font-family: "Roboto Condensed", sans-serif;
+            word-break: break-all;
+            font-weight: 300;
+            letter-spacing: 0;
+            margin-top: -10px;
+            color: #fff;
+          }
+        }
       }
     }
+  }
+
+  .sidebar-footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    padding: 2px 10px;
+    display: grid;
+    height: -var(--sidebar-padding-bottom);
+    grid-template-columns: repeat(4, min-content);
+    grid-gap: 10px;
+
+    > button {
+      color: hsl(217, 39%, 94%);
+      i {
+        font-size: 24px;
+      }
+
+      &:hover {
+        color: hsl(45, 100%, 48%);
+      }
+    }
+
+    > .dbg-info-square {
+      width: 24px;
+      height: 22px;
+      line-height: 22px;
+      margin: 1px 0;
+      background: #12161b;
+      color: #4e71b3;
+      border-radius: 5px;
+      font-size: 12px;
+      text-align: center;
+      &.green {
+        background: #7aca75;
+        color: #12161b;
+      }
+      &.amber {
+        background: #ffc107;
+        color: #333;
+      }
+      &.red {
+        background: #d32f2f;
+        color: #fff;
+      }
+      > div {
+        font-size: 10px;
+        line-height: 11px;
+      }
+    }
+
+    .version {
+      position: absolute;
+      right: 8px;
+      bottom: 3px;
+      font-size: 12px;
+      font-family: "Roboto Condensed", sans-serif;
+      a {
+        color: rgba(255, 255, 255, 0.5);
+        text-decoration: none;
+      }
+      margin-top: 11px;
+    }
+  }
 }
 
 // Hide the footer when running integration tests, as the version code and the
diff --git a/ui/src/assets/topbar.scss b/ui/src/assets/topbar.scss
index 27dd63c..561c9364 100644
--- a/ui/src/assets/topbar.scss
+++ b/ui/src/assets/topbar.scss
@@ -12,189 +12,191 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 @mixin omnibox-width() {
-    width: 90%;
-    max-width: 600px;
+  width: 90%;
+  max-width: 600px;
 }
 
 .topbar {
-    grid-area: topbar;
-    position: relative;
-    z-index: 3;
-    overflow: visible;
-    background-color: hsl(215, 1%, 95%);
-    box-shadow: 0 -3px 14px 2px #bbb;
-    min-height: var(--topbar-height);
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    .omnibox {
-        @include omnibox-width();
-        @include transition(0.25s);
-        display: grid;
-        grid-template-areas: "icon input stepthrough";
-        grid-template-columns: 34px auto max-content;
-        border-radius: 20px;
-        background-color: #fcfcfc;
-        border: 0;
-        line-height: 34px;
-        &:before {
-            @include material-icon('search');
-            margin: 5px;
-            color: #aaa;
-            grid-area: icon;
-        }
-        input {
-            grid-area: input;
-            border: 0;
-            padding: 0 10px;
-            font-size: 18px;
-            font-family: 'Roboto Condensed', sans-serif;
-            font-weight: 300;
-            color: #666;
-            background-color: transparent;
-            &:focus {
-                outline: none;
-            }
-            &::placeholder {
-                color: #b4b7ba;
-                font-family: 'Raleway', sans-serif;
-                font-weight: 400;
-            }
-        }
-        &.command-mode {
-            background-color: #111;
-            border-radius: 0;
-            width: 100%;
-            max-width: 100%;
-            margin-top: 0;
-            border-left: 1px solid #404854;
-            height: var(--topbar-height);
-            input {
-                color: #9ddc67;
-                font-family: var(--monospace-font);
-                padding-left: 0;
-            }
-            &:before {
-                content: 'attach_money';
-                color: #9ddc67;
-                font-size: 26px;
-                padding-top: 5px;
-            }
-        }
-        &.message-mode {
-            background-color: hsl(0, 0%, 89%);
-            border-radius: 4px;
-            input::placeholder {
-                font-weight: 400;
-                font-family: var(--monospace-font);
-                color: hsl(213, 40%, 50%);
-            }
-            &:before {
-                content: 'bubble_chart';
-            }
-        }
-        .stepthrough {
-          grid-area: stepthrough;
-          display: flex;
-          font: inherit;
-          font-size: 14px;
-          font-family: 'Roboto Condensed', sans-serif;
-          font-weight: 300;
-          color: #aaa;
-          .current {
-            padding-right: 10px;
-          }
-          .material-icons.left {
-            border-right: rgb(218, 217, 217) solid 1px;
-          }
-        }
+  grid-area: topbar;
+  position: relative;
+  z-index: 3;
+  overflow: visible;
+  background-color: hsl(215, 1%, 95%);
+  box-shadow: 0 -3px 14px 2px #bbb;
+  min-height: var(--topbar-height);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .omnibox {
+    @include omnibox-width();
+    @include transition(0.25s);
+    display: grid;
+    grid-template-areas: "icon input stepthrough";
+    grid-template-columns: 34px auto max-content;
+    border-radius: 20px;
+    background-color: #fcfcfc;
+    border: 0;
+    line-height: 34px;
+    &:before {
+      @include material-icon("search");
+      margin: 5px;
+      color: #aaa;
+      grid-area: icon;
     }
-    .progress {
-        position: absolute;
-        bottom: 0;
-        height: 1px;
-        width: 100%;
+    input {
+      grid-area: input;
+      border: 0;
+      padding: 0 10px;
+      font-size: 18px;
+      font-family: "Roboto Condensed", sans-serif;
+      font-weight: 300;
+      color: #666;
+      background-color: transparent;
+      &:focus {
+        outline: none;
       }
-      .progress-anim {
-        &:before {
-            content: '';
-            position: absolute;
-            background-color: hsl(219, 50%, 50%);
-            top: 0;
-            left: 0;
-            bottom: 0;
-            will-change: left, right;
-            animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
-        }
-        &:after {
-            content: '';
-            position: absolute;
-            background-color: hsl(219, 50%, 50%);
-            top: 0;
-            left: 0;
-            bottom: 0;
-            will-change: left, right;
-            animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
-            animation-delay: 1.15s;
-        }
+      &::placeholder {
+        color: #b4b7ba;
+        font-family: "Raleway", sans-serif;
+        font-weight: 400;
+      }
     }
-    @keyframes indeterminate {
-        0% {
-            left: -35%;
-            right: 100%;
-        }
-        60% {
-            left: 100%;
-            right: -90%;
-        }
-        100% {
-            left: 100%;
-            right: -90%;
-        }
+    &.command-mode {
+      background-color: #111;
+      border-radius: 0;
+      width: 100%;
+      max-width: 100%;
+      margin-top: 0;
+      border-left: 1px solid #404854;
+      height: var(--topbar-height);
+      input {
+        color: #9ddc67;
+        font-family: var(--monospace-font);
+        padding-left: 0;
+      }
+      &:before {
+        content: "attach_money";
+        color: #9ddc67;
+        font-size: 26px;
+        padding-top: 5px;
+      }
     }
-    @keyframes indeterminate-short {
-        0% {
-            left: -35%;
-            right: 100%;
-        }
-        60% {
-            left: 100%;
-            right: -90%;
-        }
-        100% {
-            left: 100%;
-            right: -90%;
-        }
+    &.message-mode {
+      background-color: hsl(0, 0%, 89%);
+      border-radius: 4px;
+      input::placeholder {
+        font-weight: 400;
+        font-family: var(--monospace-font);
+        color: hsl(213, 40%, 50%);
+      }
+      &:before {
+        content: "bubble_chart";
+      }
+    }
+    .stepthrough {
+      grid-area: stepthrough;
+      display: flex;
+      font: inherit;
+      font-size: 14px;
+      font-family: "Roboto Condensed", sans-serif;
+      font-weight: 300;
+      color: #aaa;
+      .current {
+        padding-right: 10px;
+      }
+      .material-icons.left {
+        border-right: rgb(218, 217, 217) solid 1px;
+      }
+    }
+  }
+  .progress {
+    position: absolute;
+    bottom: 0;
+    height: 1px;
+    width: 100%;
+  }
+  .progress-anim {
+    &:before {
+      content: "";
+      position: absolute;
+      background-color: hsl(219, 50%, 50%);
+      top: 0;
+      left: 0;
+      bottom: 0;
+      will-change: left, right;
+      animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395)
+        infinite;
+    }
+    &:after {
+      content: "";
+      position: absolute;
+      background-color: hsl(219, 50%, 50%);
+      top: 0;
+      left: 0;
+      bottom: 0;
+      will-change: left, right;
+      animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
+        infinite;
+      animation-delay: 1.15s;
+    }
+  }
+  @keyframes indeterminate {
+    0% {
+      left: -35%;
+      right: 100%;
+    }
+    60% {
+      left: 100%;
+      right: -90%;
+    }
+    100% {
+      left: 100%;
+      right: -90%;
+    }
+  }
+  @keyframes indeterminate-short {
+    0% {
+      left: -35%;
+      right: 100%;
+    }
+    60% {
+      left: 100%;
+      right: -90%;
+    }
+    100% {
+      left: 100%;
+      right: -90%;
+    }
+  }
+
+  .notification-btn {
+    @include transition(0.25s);
+    font-size: 16px;
+    padding: 8px 10px;
+    margin: 0 10px;
+    border-radius: 2px;
+    background: hsl(210, 10%, 73%);
+    &:hover {
+      background: hsl(210, 10%, 83%);
     }
 
-    .notification-btn {
-        @include transition(0.25s);
-        font-size: 16px;
-        padding: 8px 10px;
-        margin: 0 10px;
-        border-radius: 2px;
-        background: hsl(210, 10%, 73%);
-        &:hover {
-            background: hsl(210, 10%, 83%);
-        }
-
-        &.preferred {
-            background: hsl(210, 98%, 53%);
-            color: #fff;
-            &:hover {
-                background: hsl(210, 98%, 63%);
-            }
-        }
+    &.preferred {
+      background: hsl(210, 98%, 53%);
+      color: #fff;
+      &:hover {
+        background: hsl(210, 98%, 63%);
+      }
     }
+  }
 }
 
 .error {
-    position: absolute;
-    right: 10px;
-    color: #EF6C00;
-    &:hover {
-        cursor:pointer;
-    }
+  position: absolute;
+  right: 10px;
+  color: #ef6c00;
+  &:hover {
+    cursor: pointer;
+  }
 }
 
 .helpful-hint {
@@ -213,7 +215,7 @@
 }
 
 .hint-text {
-  padding-bottom: 5px
+  padding-bottom: 5px;
 }
 
 .hint-dismiss-button {
diff --git a/ui/src/assets/trace_info_page.scss b/ui/src/assets/trace_info_page.scss
index a91dcf9..69baaaf 100644
--- a/ui/src/assets/trace_info_page.scss
+++ b/ui/src/assets/trace_info_page.scss
@@ -25,7 +25,7 @@
     border-radius: 8px;
 
     &.errors {
-      background-color: #F3E5F5;
+      background-color: #f3e5f5;
     }
 
     .metric-error {
@@ -36,7 +36,7 @@
     }
 
     h2 {
-      font-family: 'Raleway', sans-serif;
+      font-family: "Raleway", sans-serif;
       font-weight: 400;
       letter-spacing: 0.25px;
       font-size: 2rem;
diff --git a/ui/src/assets/typefaces.scss b/ui/src/assets/typefaces.scss
index a8661b9..8d82dac 100644
--- a/ui/src/assets/typefaces.scss
+++ b/ui/src/assets/typefaces.scss
@@ -1,94 +1,112 @@
 @font-face {
-  font-family: 'Material Icons';
+  font-family: "Material Icons";
   font-style: normal;
   font-weight: 400;
   font-display: block;
-  src: url(assets/MaterialIcons.woff2) format('woff2');
+  src: url(assets/MaterialIcons.woff2) format("woff2");
 }
 
 /* latin */
 @font-face {
-  font-family: 'Raleway';
+  font-family: "Raleway";
   font-style: normal;
   font-weight: 100;
-  src: url(assets/Raleway-Thin.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/Raleway-Thin.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Raleway';
+  font-family: "Raleway";
   font-style: normal;
   font-weight: 400;
-  src: url(assets/Raleway-Regular.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/Raleway-Regular.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto';
+  font-family: "Roboto";
   font-style: normal;
   font-weight: 100;
-  src: url(assets/Roboto-100.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/Roboto-100.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto';
+  font-family: "Roboto";
   font-style: normal;
   font-weight: 300;
-  src: url(assets/Roboto-300.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/Roboto-300.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto';
+  font-family: "Roboto";
   font-style: normal;
   font-weight: 400;
-  src: url(assets/Roboto-400.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/Roboto-400.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto';
+  font-family: "Roboto";
   font-style: normal;
   font-weight: 500;
-  src: url(assets/Roboto-500.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/Roboto-500.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto Condensed';
+  font-family: "Roboto Condensed";
   font-style: normal;
   font-weight: 300;
-  src: url(assets/RobotoCondensed-Light.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/RobotoCondensed-Light.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto Condensed';
+  font-family: "Roboto Condensed";
   font-style: normal;
   font-weight: 400;
-  src: url(assets/RobotoCondensed-Regular.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/RobotoCondensed-Regular.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto Mono';
+  font-family: "Roboto Mono";
   font-style: normal;
   font-weight: 400;
-  src: url(assets/RobotoMono-Regular.woff2) format('woff2');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+  src: url(assets/RobotoMono-Regular.woff2) format("woff2");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
+    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
+    U+FEFF, U+FFFD;
 }
 
 .material-icons {
-  font-family: 'Material Icons';
+  font-family: "Material Icons";
   font-weight: normal;
   font-style: normal;
   font-size: 24px;
@@ -100,6 +118,6 @@
   white-space: nowrap;
   word-wrap: normal;
   direction: ltr;
-  -webkit-font-feature-settings: 'liga';
+  -webkit-font-feature-settings: "liga";
   -webkit-font-smoothing: antialiased;
 }
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 7121016..4b21f57 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -19,7 +19,6 @@
 import {globals} from '../frontend/globals';
 import {
   Aggregation,
-  aggregationEquals,
   AggregationFunction,
   TableColumn,
   tableColumnEquals,
@@ -1046,6 +1045,17 @@
     state.flamegraphModalDismissed = true;
   },
 
+  addPivotTableAggregation(
+      state: StateDraft, args: {aggregation: Aggregation, after: number}) {
+    state.nonSerializableState.pivotTableRedux.selectedAggregations.splice(
+        args.after, 0, args.aggregation);
+  },
+
+  removePivotTableAggregation(state: StateDraft, args: {index: number}) {
+    state.nonSerializableState.pivotTableRedux.selectedAggregations.splice(
+        args.index, 1);
+  },
+
   setPivotTableQueryRequested(
       state: StateDraft, args: {queryRequested: boolean}) {
     state.nonSerializableState.pivotTableRedux.queryRequested =
@@ -1069,15 +1079,6 @@
     }
   },
 
-  setPivotTableAggregationSelected(
-      state: StateDraft, args: {column: Aggregation, selected: boolean}) {
-    toggleEnabled(
-        aggregationEquals,
-        state.nonSerializableState.pivotTableRedux.selectedAggregations,
-        args.column,
-        args.selected);
-  },
-
   setPivotTableAggregationFunction(
       state: StateDraft, args: {index: number, function: AggregationFunction}) {
     state.nonSerializableState.pivotTableRedux.selectedAggregations[args.index]
diff --git a/ui/src/controller/cpu_profile_controller.ts b/ui/src/controller/cpu_profile_controller.ts
index 8bf031d..db695ac 100644
--- a/ui/src/controller/cpu_profile_controller.ts
+++ b/ui/src/controller/cpu_profile_controller.ts
@@ -115,7 +115,7 @@
             WHERE symbol.symbol_set_id = spf.symbol_set_id
             LIMIT 1
           ),
-          spf.name
+          COALESCE(spf.deobfuscated_name, spf.name)
         ) AS name,
         spm.name AS mapping
       FROM cpu_profile_stack_sample AS samples
diff --git a/ui/src/frontend/pivot_table_redux.ts b/ui/src/frontend/pivot_table_redux.ts
index 68d2881..c2d11e8 100644
--- a/ui/src/frontend/pivot_table_redux.ts
+++ b/ui/src/frontend/pivot_table_redux.ts
@@ -283,37 +283,28 @@
         readableColumnName(aggregation.column)})`;
   }
 
-  aggregationPopupItem(aggregation: Aggregation, nameOverride?: string):
-      PopupMenuItem {
+  aggregationPopupItem(
+      aggregation: Aggregation, index: number,
+      nameOverride?: string): PopupMenuItem {
     return {
       itemType: 'regular',
       text: nameOverride ?? readableColumnName(aggregation.column),
       callback: () => {
-        globals.dispatch(Actions.setPivotTableAggregationSelected({
-          column: {
-            aggregationFunction: aggregation.aggregationFunction,
-            column: aggregation.column,
-          },
-          selected: true,
-        }));
+        globals.dispatch(
+            Actions.addPivotTableAggregation({aggregation, after: index}));
         globals.dispatch(
             Actions.setPivotTableQueryRequested({queryRequested: true}));
       },
     };
   }
 
-  aggregationPopupTableGroup(
-      table: string, columns: string[], used: Set<string>): PopupMenuItem
-      |undefined {
+  aggregationPopupTableGroup(table: string, columns: string[], index: number):
+      PopupMenuItem|undefined {
     const items = [];
     for (const column of columns) {
       const tableColumn: TableColumn = {kind: 'regular', table, column};
-      if (used.has(columnKey(tableColumn))) {
-        continue;
-      }
-
       items.push(this.aggregationPopupItem(
-          {aggregationFunction: 'SUM', column: tableColumn}));
+          {aggregationFunction: 'SUM', column: tableColumn}, index));
     }
 
     if (items.length === 0) {
@@ -371,34 +362,28 @@
       popupItems.push({
         itemType: 'regular',
         text: 'Remove',
-        callback() {
-          globals.dispatch(Actions.setPivotTableAggregationSelected(
-              {column: aggregation, selected: false}));
+        callback: () => {
+          globals.dispatch(Actions.removePivotTableAggregation({index}));
           globals.dispatch(
               Actions.setPivotTableQueryRequested({queryRequested: true}));
         },
       });
     }
 
-    const usedAggregations: Set<string> = new Set();
     let hasCount = false;
-
     for (const agg of state.selectedAggregations.values()) {
       if (agg.aggregationFunction === 'COUNT') {
         hasCount = true;
-        continue;
       }
-
-      usedAggregations.add(columnKey(agg.column));
     }
 
     if (!hasCount) {
       popupItems.push(this.aggregationPopupItem(
-          COUNT_AGGREGATION, 'Add count aggregation'));
+          COUNT_AGGREGATION, index, 'Add count aggregation'));
     }
 
     const sliceAggregationsItem = this.aggregationPopupTableGroup(
-        'slice', sliceAggregationColumns, usedAggregations);
+        'slice', sliceAggregationColumns, index);
     if (sliceAggregationsItem !== undefined) {
       popupItems.push(sliceAggregationsItem);
     }