Merge "Add more logging why a DS was disconnected."
diff --git a/src/profiling/memory/client_api_factory_standalone.cc b/src/profiling/memory/client_api_factory_standalone.cc
index f21ce0d..b49da1f 100644
--- a/src/profiling/memory/client_api_factory_standalone.cc
+++ b/src/profiling/memory/client_api_factory_standalone.cc
@@ -149,6 +149,9 @@
         }
       });
   task_runner.Run();
+  // We currently do not Quit the task_runner, but if we ever do it will be
+  // very hard to debug if we don't exit here.
+  exit(0);
 }
 
 // This is called by AHeapProfile_initSession (client_api.cc) to construct a
diff --git a/src/trace_processor/importers/json/json_trace_parser.cc b/src/trace_processor/importers/json/json_trace_parser.cc
index eabd57d..85de296 100644
--- a/src/trace_processor/importers/json/json_trace_parser.cc
+++ b/src/trace_processor/importers/json/json_trace_parser.cc
@@ -25,6 +25,7 @@
 #include "perfetto/ext/base/string_utils.h"
 #include "perfetto/ext/base/string_view.h"
 #include "perfetto/ext/base/utils.h"
+#include "src/trace_processor/importers/common/event_tracker.h"
 #include "src/trace_processor/importers/common/flow_tracker.h"
 #include "src/trace_processor/importers/common/process_tracker.h"
 #include "src/trace_processor/importers/common/slice_tracker.h"
@@ -148,6 +149,61 @@
       MaybeAddFlow(track_id, value);
       break;
     }
+    case 'C': {  // TRACE_EVENT_COUNTER
+      auto args = value["args"];
+      if (!args.isObject()) {
+        context_->storage->IncrementStats(stats::json_parser_failure);
+        break;
+      }
+
+      std::string counter_name_prefix = name.ToStdString();
+      if (value.isMember("id")) {
+        counter_name_prefix += " id: " + value["id"].asString();
+      }
+
+      for (auto it = args.begin(); it != args.end(); ++it) {
+        std::string counter_name = counter_name_prefix + " " + it.name();
+        StringId counter_name_id =
+            context_->storage->InternString(base::StringView(counter_name));
+        TrackId track_id = context_->track_tracker->InternProcessCounterTrack(
+            counter_name_id, utid);
+        context_->event_tracker->PushCounter(timestamp, it->asDouble(),
+                                             track_id);
+      }
+      break;
+    }
+    case 'i': {  // TRACE_EVENT_INSTANT
+      base::StringView scope;
+      if (value.isMember("s")) {
+        scope = value["s"].asCString();
+      }
+
+      TrackId track_id;
+      if (scope == "g") {
+        track_id = context_->track_tracker
+                       ->GetOrCreateLegacyChromeGlobalInstantTrack();
+      } else if (scope == "p") {
+        if (!opt_pid) {
+          context_->storage->IncrementStats(stats::json_parser_failure);
+          break;
+        }
+        UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
+        track_id =
+            context_->track_tracker->InternLegacyChromeProcessInstantTrack(
+                upid);
+      } else if (scope == "t" || scope.data() == nullptr) {
+        if (!opt_tid) {
+          context_->storage->IncrementStats(stats::json_parser_failure);
+          break;
+        }
+        track_id = context_->track_tracker->InternThreadTrack(utid);
+      } else {
+        context_->storage->IncrementStats(stats::json_parser_failure);
+        break;
+      }
+      context_->slice_tracker->Scoped(timestamp, track_id, cat_id, name_id, 0);
+      break;
+    }
     case 's': {  // TRACE_EVENT_FLOW_START
       TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
       auto opt_source_id =
diff --git a/src/trace_processor/trace_sorter.cc b/src/trace_processor/trace_sorter.cc
index 760bf75..c1bc9e5 100644
--- a/src/trace_processor/trace_sorter.cc
+++ b/src/trace_processor/trace_sorter.cc
@@ -185,13 +185,14 @@
   if (PERFETTO_UNLIKELY(bypass_next_stage_for_testing_))
     return;
 
+  int64_t timestamp = ttp.timestamp;
   if (queue_idx == 0) {
     // queues_[0] is for non-ftrace packets.
-    parser_->ParseTracePacket(ttp.timestamp, std::move(ttp));
+    parser_->ParseTracePacket(timestamp, std::move(ttp));
   } else {
     // Ftrace queues start at offset 1. So queues_[1] = cpu[0] and so on.
     uint32_t cpu = static_cast<uint32_t>(queue_idx - 1);
-    parser_->ParseFtracePacket(cpu, ttp.timestamp, std::move(ttp));
+    parser_->ParseFtracePacket(cpu, timestamp, std::move(ttp));
   }
 }
 
diff --git a/src/trace_processor/trace_sorter.h b/src/trace_processor/trace_sorter.h
index abcf01a..a93cd26 100644
--- a/src/trace_processor/trace_sorter.h
+++ b/src/trace_processor/trace_sorter.h
@@ -91,8 +91,10 @@
 
   inline void PushSystraceLine(std::unique_ptr<SystraceLine> systrace_line) {
     DCHECK_ftrace_batch_cpu(kNoBatch);
+
+    int64_t timestamp = systrace_line->ts;
     AppendNonFtraceAndMaybeExtractEvents(TimestampedTracePiece(
-        systrace_line->ts, packet_idx_++, std::move(systrace_line)));
+        timestamp, packet_idx_++, std::move(systrace_line)));
   }
 
   inline void PushTrackEventPacket(int64_t timestamp,
@@ -115,20 +117,20 @@
     // global ordering and doing that in batches only after all ftrace events
     // for a bundle are pushed.
   }
-
-  // As with |PushFtraceEvent|, doesn't immediately sort the affected queues.
-  // TODO(rsavitski): if a trace has a mix of normal & "compact" events (being
-  // pushed through this function), the ftrace batches will no longer be fully
-  // sorted by timestamp. In such situations, we will have to sort at the end of
-  // the batch. We can do better as both sub-sequences are sorted however.
-  // Consider adding extra queues, or pushing them in a merge-sort fashion
-  // instead.
   inline void PushInlineFtraceEvent(uint32_t cpu,
                                     int64_t timestamp,
                                     InlineSchedSwitch inline_sched_switch) {
     set_ftrace_batch_cpu_for_DCHECK(cpu);
     GetQueue(cpu + 1)->Append(
         TimestampedTracePiece(timestamp, packet_idx_++, inline_sched_switch));
+
+    // As with |PushFtraceEvent|, doesn't immediately sort the affected queues.
+    // TODO(rsavitski): if a trace has a mix of normal & "compact" events (being
+    // pushed through this function), the ftrace batches will no longer be fully
+    // sorted by timestamp. In such situations, we will have to sort at the end
+    // of the batch. We can do better as both sub-sequences are sorted however.
+    // Consider adding extra queues, or pushing them in a merge-sort fashion
+    // instead.
   }
   inline void PushInlineFtraceEvent(uint32_t cpu,
                                     int64_t timestamp,
diff --git a/test/trace_processor/parsing/counters_json_counters.out b/test/trace_processor/parsing/counters_json_counters.out
new file mode 100644
index 0000000..dfe4747
--- /dev/null
+++ b/test/trace_processor/parsing/counters_json_counters.out
@@ -0,0 +1,4 @@
+"name","ts","value"
+"ctr cats",0,0.000000
+"ctr cats",10000,10.000000
+"ctr cats",20000,0.000000
diff --git a/test/trace_processor/parsing/index b/test/trace_processor/parsing/index
index 4b2ca9a..65ef807 100644
--- a/test/trace_processor/parsing/index
+++ b/test/trace_processor/parsing/index
@@ -142,3 +142,7 @@
 
 # Floating point numbers
 ../../data/decimal_timestamp.json slices.sql decimal_timestamp_slices.out
+
+# JSON instants and counters
+../../data/counters.json json_counters.sql counters_json_counters.out
+../../data/instants.json json_instants.sql instants_json_instants.out
diff --git a/test/trace_processor/parsing/instants_json_instants.out b/test/trace_processor/parsing/instants_json_instants.out
new file mode 100644
index 0000000..2fb9fb4
--- /dev/null
+++ b/test/trace_processor/parsing/instants_json_instants.out
@@ -0,0 +1,5 @@
+"ts","slice_name","tid","pid"
+1234523300,"Thread",2347,"[NULL]"
+1235523300,"Global","[NULL]","[NULL]"
+1236523300,"Process","[NULL]",2320
+1237523300,"None",6790,"[NULL]"
diff --git a/test/trace_processor/parsing/json_counters.sql b/test/trace_processor/parsing/json_counters.sql
new file mode 100644
index 0000000..604c2c1
--- /dev/null
+++ b/test/trace_processor/parsing/json_counters.sql
@@ -0,0 +1,6 @@
+select
+  process_counter_track.name,
+  counter.ts,
+  counter.value
+from counter
+join process_counter_track on (counter.track_id = process_counter_track.id);
\ No newline at end of file
diff --git a/test/trace_processor/parsing/json_instants.sql b/test/trace_processor/parsing/json_instants.sql
new file mode 100644
index 0000000..d76ef89
--- /dev/null
+++ b/test/trace_processor/parsing/json_instants.sql
@@ -0,0 +1,12 @@
+select
+  slice.ts,
+  slice.name as slice_name,
+  thread.tid,
+  process.pid
+from slice
+join track on (slice.track_id = track.id)
+left join thread_track on (slice.track_id = thread_track.id)
+left join thread on (thread_track.utid = thread.utid)
+left join process_track on (slice.track_id = process_track.id)
+left join process on (process_track.upid = process.upid)
+where dur = 0;
\ No newline at end of file
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 878f1f6..6575bea 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -234,8 +234,8 @@
     # Example traces for regression tests.
     Dependency(
         'test/data.zip',
-        'https://storage.googleapis.com/perfetto/test-data-20210513-224349.zip',
-        '3dcc146f4ce38d17fd1f8c4c65af07e7cf7c5c4cb8aa4c7bf73ec3a095d997d1',
+        'https://storage.googleapis.com/perfetto/test-data-20210518-223638.zip',
+        'a9119ae4828fae92c9ec8449e3fd91d753e60b60fa59611fb8e6c0dd6ed69b13',
         'all', 'all',
     ),
 
diff --git a/ui/release/channels.json b/ui/release/channels.json
index ffb232f..54a79d2 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -6,7 +6,7 @@
     },
     {
       "name": "canary",
-      "rev": "a284e65f883e7c543c2619115be1ee0fbe5644a3"
+      "rev": "dac610dd857535ee840a1cdcc2a5103e59a99388"
     },
     {
       "name": "autopush",
diff --git a/ui/src/controller/track_decider.ts b/ui/src/controller/track_decider.ts
index 26f343b..9db1325 100644
--- a/ui/src/controller/track_decider.ts
+++ b/ui/src/controller/track_decider.ts
@@ -569,7 +569,9 @@
           process.pid as pid
         from process_track
         left join process using(upid)
-        where process_track.name not like "% Timeline"
+        where
+            process_track.name is null or
+            process_track.name not like "% Timeline"
         group by
           process_track.upid,
           process_track.name