diff --git a/Android.bp b/Android.bp index 4560a48a2e..a5d2cc284e 100644 --- a/Android.bp +++ b/Android.bp @@ -12246,11 +12246,13 @@ filegroup { "src/trace_processor/importers/common/process_track_translation_table.cc", "src/trace_processor/importers/common/process_tracker.cc", "src/trace_processor/importers/common/sched_event_tracker.cc", + "src/trace_processor/importers/common/scoped_active_trace_file.cc", "src/trace_processor/importers/common/slice_tracker.cc", "src/trace_processor/importers/common/slice_translation_table.cc", "src/trace_processor/importers/common/stack_profile_tracker.cc", "src/trace_processor/importers/common/system_info_tracker.cc", "src/trace_processor/importers/common/thread_state_tracker.cc", + "src/trace_processor/importers/common/trace_file_tracker.cc", "src/trace_processor/importers/common/trace_parser.cc", "src/trace_processor/importers/common/track_tracker.cc", "src/trace_processor/importers/common/virtual_memory_mapping.cc", diff --git a/BUILD b/BUILD index 390743b255..fa7d599930 100644 --- a/BUILD +++ b/BUILD @@ -1536,6 +1536,8 @@ perfetto_filegroup( "src/trace_processor/importers/common/sched_event_state.h", "src/trace_processor/importers/common/sched_event_tracker.cc", "src/trace_processor/importers/common/sched_event_tracker.h", + "src/trace_processor/importers/common/scoped_active_trace_file.cc", + "src/trace_processor/importers/common/scoped_active_trace_file.h", "src/trace_processor/importers/common/slice_tracker.cc", "src/trace_processor/importers/common/slice_tracker.h", "src/trace_processor/importers/common/slice_translation_table.cc", @@ -1546,6 +1548,8 @@ perfetto_filegroup( "src/trace_processor/importers/common/system_info_tracker.h", "src/trace_processor/importers/common/thread_state_tracker.cc", "src/trace_processor/importers/common/thread_state_tracker.h", + "src/trace_processor/importers/common/trace_file_tracker.cc", + "src/trace_processor/importers/common/trace_file_tracker.h", "src/trace_processor/importers/common/trace_parser.cc", "src/trace_processor/importers/common/track_tracker.cc", "src/trace_processor/importers/common/track_tracker.h", diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc index 7cee7945cc..70bffd5b2b 100644 --- a/src/trace_processor/forwarding_trace_parser.cc +++ b/src/trace_processor/forwarding_trace_parser.cc @@ -67,7 +67,13 @@ std::optional GetMinimumSortingMode( return TraceSorter::SortingMode::kFullSort; case kProtoTraceType: + case kSymbolsTraceType: return ConvertSortingMode(context.config.sorting_mode); + + case kAndroidDumpstateTraceType: + case kAndroidBugreportTraceType: + PERFETTO_FATAL( + "This trace type should be handled at the ZipParser level"); } PERFETTO_FATAL("For GCC"); } @@ -82,34 +88,31 @@ ForwardingTraceParser::~ForwardingTraceParser() {} base::Status ForwardingTraceParser::Init(const TraceBlobView& blob) { PERFETTO_CHECK(!reader_); - TraceType trace_type; { auto scoped_trace = context_->storage->TraceExecutionTimeIntoStats( stats::guess_trace_type_duration_ns); - trace_type = GuessTraceType(blob.data(), blob.size()); - context_->trace_type = trace_type; + trace_type_ = GuessTraceType(blob.data(), blob.size()); } - - if (trace_type == kUnknownTraceType) { + if (trace_type_ == kUnknownTraceType) { // If renaming this error message don't remove the "(ERR:fmt)" part. // The UI's error_dialog.ts uses it to make the dialog more graceful. return base::ErrStatus("Unknown trace type provided (ERR:fmt)"); } base::StatusOr> reader_or = - context_->reader_registry->CreateTraceReader(trace_type); + context_->reader_registry->CreateTraceReader(trace_type_); if (!reader_or.ok()) { return reader_or.status(); } reader_ = std::move(*reader_or); - PERFETTO_DLOG("%s detected", ToString(trace_type)); - UpdateSorterForTraceType(trace_type); + PERFETTO_DLOG("%s trace detected", TraceTypeToString(trace_type_)); + UpdateSorterForTraceType(trace_type_); // TODO(b/334978369) Make sure kProtoTraceType and kSystraceTraceType are // parsed first so that we do not get issues with // SetPidZeroIsUpidZeroIdleProcess() - if (trace_type == kProtoTraceType || trace_type == kSystraceTraceType) { + if (trace_type_ == kProtoTraceType || trace_type_ == kSystraceTraceType) { context_->process_tracker->SetPidZeroIsUpidZeroIdleProcess(); } diff --git a/src/trace_processor/forwarding_trace_parser.h b/src/trace_processor/forwarding_trace_parser.h index 34bb1a2b4a..fa902790d5 100644 --- a/src/trace_processor/forwarding_trace_parser.h +++ b/src/trace_processor/forwarding_trace_parser.h @@ -37,11 +37,14 @@ class ForwardingTraceParser : public ChunkedTraceReader { base::Status Parse(TraceBlobView) override; [[nodiscard]] base::Status NotifyEndOfFile() override; + TraceType trace_type() const { return trace_type_; } + private: base::Status Init(const TraceBlobView&); void UpdateSorterForTraceType(TraceType trace_type); TraceProcessorContext* const context_; std::unique_ptr reader_; + TraceType trace_type_ = kUnknownTraceType; }; } // namespace perfetto::trace_processor diff --git a/src/trace_processor/importers/android_bugreport/BUILD.gn b/src/trace_processor/importers/android_bugreport/BUILD.gn index 7c848f24e6..045a609209 100644 --- a/src/trace_processor/importers/android_bugreport/BUILD.gn +++ b/src/trace_processor/importers/android_bugreport/BUILD.gn @@ -52,6 +52,7 @@ source_set("android_bugreport") { "../../storage", "../../tables:tables_python", "../../types", + "../../util:trace_type", "../../util:zip_reader", "../common", ] diff --git a/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc b/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc index fc98a6b6e8..abded5f57a 100644 --- a/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc +++ b/src/trace_processor/importers/android_bugreport/android_bugreport_reader.cc @@ -30,8 +30,10 @@ #include "src/trace_processor/importers/android_bugreport/android_dumpstate_reader.h" #include "src/trace_processor/importers/android_bugreport/android_log_reader.h" #include "src/trace_processor/importers/common/clock_tracker.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" #include "src/trace_processor/types/trace_processor_context.h" #include "src/trace_processor/util/status_macros.h" +#include "src/trace_processor/util/trace_type.h" #include "src/trace_processor/util/zip_reader.h" namespace perfetto::trace_processor { @@ -105,6 +107,9 @@ util::Status AndroidBugreportReader::ParseImpl() { base::Status AndroidBugreportReader::ParseDumpstateTxt( std::vector logcat_events) { PERFETTO_CHECK(dumpstate_file_); + ScopedActiveTraceFile trace_file = context_->trace_file_tracker->StartNewFile( + dumpstate_file_->name(), kAndroidDumpstateTraceType, + dumpstate_file_->uncompressed_size()); AndroidDumpstateReader reader(context_, br_year_, std::move(logcat_events)); return dumpstate_file_->DecompressLines( [&](const std::vector& lines) { @@ -134,6 +139,10 @@ AndroidBugreportReader::ParsePersistentLogcat() { // Push all events into the AndroidLogParser. It will take care of string // interning into the pool. Appends entries into `log_events`. for (const auto& log_file : log_files) { + ScopedActiveTraceFile trace_file = + context_->trace_file_tracker->StartNewFile( + log_file.second->name(), kAndroidLogcatTraceType, + log_file.second->uncompressed_size()); RETURN_IF_ERROR(log_file.second->DecompressLines( [&](const std::vector& lines) { for (const auto& line : lines) { diff --git a/src/trace_processor/importers/common/BUILD.gn b/src/trace_processor/importers/common/BUILD.gn index 9cde6e32db..1a222925be 100644 --- a/src/trace_processor/importers/common/BUILD.gn +++ b/src/trace_processor/importers/common/BUILD.gn @@ -54,6 +54,8 @@ source_set("common") { "sched_event_state.h", "sched_event_tracker.cc", "sched_event_tracker.h", + "scoped_active_trace_file.cc", + "scoped_active_trace_file.h", "slice_tracker.cc", "slice_tracker.h", "slice_translation_table.cc", @@ -64,6 +66,8 @@ source_set("common") { "system_info_tracker.h", "thread_state_tracker.cc", "thread_state_tracker.h", + "trace_file_tracker.cc", + "trace_file_tracker.h", "trace_parser.cc", "track_tracker.cc", "track_tracker.h", @@ -90,6 +94,7 @@ source_set("common") { "../../types", "../../util:build_id", "../../util:profiler_util", + "../../util:trace_type", "../fuchsia:fuchsia_record", "../perf:record", "../systrace:systrace_line", diff --git a/src/trace_processor/importers/common/scoped_active_trace_file.cc b/src/trace_processor/importers/common/scoped_active_trace_file.cc new file mode 100644 index 0000000000..7249261c03 --- /dev/null +++ b/src/trace_processor/importers/common/scoped_active_trace_file.cc @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 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/importers/common/scoped_active_trace_file.h" + +#include +#include +#include + +#include "perfetto/ext/base/string_view.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" +#include "src/trace_processor/storage/trace_storage.h" +#include "src/trace_processor/tables/metadata_tables_py.h" +#include "src/trace_processor/types/trace_processor_context.h" + +namespace perfetto::trace_processor { +ScopedActiveTraceFile::~ScopedActiveTraceFile() { + if (is_valid_) { + context_->trace_file_tracker->EndFile(row_); + } +} + +void ScopedActiveTraceFile::SetName(const std::string& name) { + row_.set_name(context_->storage->InternString(base::StringView(name))); +} + +void ScopedActiveTraceFile::SetTraceType(TraceType type) { + row_.set_trace_type(context_->storage->InternString(TraceTypeToString(type))); +} + +void ScopedActiveTraceFile::SetSize(size_t size) { + row_.set_size(static_cast(size)); +} + +void ScopedActiveTraceFile::AddSize(size_t size) { + row_.set_size(static_cast(size) + row_.size()); +} + +} // namespace perfetto::trace_processor diff --git a/src/trace_processor/importers/common/scoped_active_trace_file.h b/src/trace_processor/importers/common/scoped_active_trace_file.h new file mode 100644 index 0000000000..0006fcfda0 --- /dev/null +++ b/src/trace_processor/importers/common/scoped_active_trace_file.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2024 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_IMPORTERS_COMMON_SCOPED_ACTIVE_TRACE_FILE_H_ +#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCOPED_ACTIVE_TRACE_FILE_H_ + +#include + +#include "src/trace_processor/tables/metadata_tables_py.h" +#include "src/trace_processor/util/trace_type.h" + +namespace perfetto::trace_processor { + +class TraceProcessorContext; + +// RAII like object that represents a file currently being parsed. When +// instances of this object go out of scope they will notify the +// TraceFileTracker that we are done parsing the file. +// This class also acts a handler for setting file related properties. +class ScopedActiveTraceFile { + public: + ~ScopedActiveTraceFile(); + + ScopedActiveTraceFile(const ScopedActiveTraceFile&) = delete; + ScopedActiveTraceFile& operator=(const ScopedActiveTraceFile&) = delete; + + ScopedActiveTraceFile(ScopedActiveTraceFile&& o) + : context_(o.context_), row_(o.row_), is_valid_(o.is_valid_) { + o.is_valid_ = false; + } + + ScopedActiveTraceFile& operator=(ScopedActiveTraceFile&& o) { + context_ = o.context_; + row_ = o.row_; + is_valid_ = o.is_valid_; + o.is_valid_ = false; + return *this; + } + + void SetTraceType(TraceType type); + + // For streamed files this method can be called for each chunk to update the + // file size incrementally. + void AddSize(size_t delta); + + private: + friend class TraceFileTracker; + ScopedActiveTraceFile(TraceProcessorContext* context, + tables::TraceFileTable::RowReference row) + : context_(context), row_(row), is_valid_(true) {} + + // Sets the file name. If this method is not called (sometimes we do not know + // the file name, e.g. streaming data) the name is set to null. + void SetName(const std::string& name); + void SetSize(size_t size); + + TraceProcessorContext* context_; + tables::TraceFileTable::RowReference row_; + bool is_valid_; +}; + +} // namespace perfetto::trace_processor + +#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_SCOPED_ACTIVE_TRACE_FILE_H_ diff --git a/src/trace_processor/importers/common/trace_file_tracker.cc b/src/trace_processor/importers/common/trace_file_tracker.cc new file mode 100644 index 0000000000..e51371a021 --- /dev/null +++ b/src/trace_processor/importers/common/trace_file_tracker.cc @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2024 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/importers/common/trace_file_tracker.h" + +#include +#include +#include + +#include "src/trace_processor/importers/common/metadata_tracker.h" +#include "src/trace_processor/storage/metadata.h" +#include "src/trace_processor/storage/trace_storage.h" +#include "src/trace_processor/tables/metadata_tables_py.h" +#include "src/trace_processor/types/trace_processor_context.h" +#include "src/trace_processor/util/trace_type.h" + +namespace perfetto::trace_processor { + +ScopedActiveTraceFile TraceFileTracker::StartNewFile() { + tables::TraceFileTable::Row row; + if (!ancestors_.empty()) { + row.parent_id = ancestors_.back(); + } + + row.size = 0; + row.trace_type = + context_->storage->InternString(TraceTypeToString(kUnknownTraceType)); + + auto ref = + context_->storage->mutable_trace_file_table()->Insert(row).row_reference; + + ancestors_.push_back(ref.id()); + return ScopedActiveTraceFile(context_, std::move(ref)); +} + +ScopedActiveTraceFile TraceFileTracker::StartNewFile(const std::string& name, + TraceType type, + size_t size) { + auto file = StartNewFile(); + file.SetName(name); + file.SetTraceType(type); + file.SetSize(size); + return file; +} + +void TraceFileTracker::EndFile( + const tables::TraceFileTable::ConstRowReference& row) { + PERFETTO_CHECK(!ancestors_.empty()); + PERFETTO_CHECK(ancestors_.back() == row.id()); + + // First file (root) + if (row.id().value == 0) { + context_->metadata_tracker->SetMetadata(metadata::trace_size_bytes, + Variadic::Integer(row.size())); + context_->metadata_tracker->SetMetadata(metadata::trace_type, + Variadic::String(row.trace_type())); + } + ancestors_.pop_back(); +} + +} // namespace perfetto::trace_processor diff --git a/src/trace_processor/importers/common/trace_file_tracker.h b/src/trace_processor/importers/common/trace_file_tracker.h new file mode 100644 index 0000000000..0e2f5f9973 --- /dev/null +++ b/src/trace_processor/importers/common/trace_file_tracker.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 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_IMPORTERS_COMMON_TRACE_FILE_TRACKER_H_ +#define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_FILE_TRACKER_H_ + +#include +#include + +#include "src/trace_processor/importers/common/scoped_active_trace_file.h" +#include "src/trace_processor/tables/metadata_tables_py.h" +#include "src/trace_processor/util/trace_type.h" + +namespace perfetto::trace_processor { + +class TraceProcessorContext; + +// This class keeps track of the file currently being parsed and metadata about +// it. Files can be nested into other files (zip or gzip files) and this class +// also keeps track of those relations. +class TraceFileTracker { + public: + explicit TraceFileTracker(TraceProcessorContext* context) + : context_(context) {} + + // Notifies the start of a new file that we are about to parse. It returns a + // RAII like object that will notify the end of processing when it goes out of + // scope. + // NOTE: Files must be ended in reverse order of being started. + ScopedActiveTraceFile StartNewFile(); + + // Convenience version of the above that should be used when all the file + // properties are known upfront. + ScopedActiveTraceFile StartNewFile(const std::string& name, + TraceType type, + size_t size); + + private: + void EndFile(const tables::TraceFileTable::ConstRowReference& row); + + friend class ScopedActiveTraceFile; + TraceProcessorContext* const context_; + std::vector ancestors_; +}; + +} // namespace perfetto::trace_processor + +#endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_TRACE_FILE_TRACKER_H_ diff --git a/src/trace_processor/importers/fuchsia/fuchsia_parser_unittest.cc b/src/trace_processor/importers/fuchsia/fuchsia_parser_unittest.cc index 7406408739..ec29509daf 100644 --- a/src/trace_processor/importers/fuchsia/fuchsia_parser_unittest.cc +++ b/src/trace_processor/importers/fuchsia/fuchsia_parser_unittest.cc @@ -16,6 +16,8 @@ #include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h" +#include + #include "perfetto/base/logging.h" #include "perfetto/ext/base/string_view.h" #include "perfetto/protozero/scattered_heap_buffer.h" @@ -23,6 +25,7 @@ #include "src/trace_processor/importers/common/args_tracker.h" #include "src/trace_processor/importers/common/args_translation_table.h" +#include "src/trace_processor/importers/common/chunked_trace_reader.h" #include "src/trace_processor/importers/common/clock_tracker.h" #include "src/trace_processor/importers/common/cpu_tracker.h" #include "src/trace_processor/importers/common/event_tracker.h" @@ -286,8 +289,9 @@ class FuchsiaTraceParserTest : public ::testing::Test { const size_t num_bytes = trace_bytes_.size() * sizeof(uint64_t); std::unique_ptr raw_trace(new uint8_t[num_bytes]); memcpy(raw_trace.get(), trace_bytes_.data(), num_bytes); - context_.chunk_reader.reset(new FuchsiaTraceTokenizer(&context_)); - auto status = context_.chunk_reader->Parse(TraceBlobView( + context_.chunk_readers.push_back( + std::make_unique(&context_)); + auto status = context_.chunk_readers.back()->Parse(TraceBlobView( TraceBlob::TakeOwnership(std::move(raw_trace), num_bytes))); ResetTraceBuffers(); diff --git a/src/trace_processor/importers/proto/network_trace_module_unittest.cc b/src/trace_processor/importers/proto/network_trace_module_unittest.cc index 30fcf01140..317120eb21 100644 --- a/src/trace_processor/importers/proto/network_trace_module_unittest.cc +++ b/src/trace_processor/importers/proto/network_trace_module_unittest.cc @@ -56,13 +56,14 @@ class NetworkTraceModuleTest : public testing::Test { } util::Status TokenizeAndParse() { - context_.chunk_reader.reset(new ProtoTraceReader(&context_)); + context_.chunk_readers.push_back( + std::make_unique(&context_)); trace_->Finalize(); std::vector v = trace_.SerializeAsArray(); trace_.Reset(); - auto status = context_.chunk_reader->Parse( + auto status = context_.chunk_readers.back()->Parse( TraceBlobView(TraceBlob::CopyFrom(v.data(), v.size()))); context_.sorter->ExtractEventsForced(); context_.slice_tracker->FlushPendingSlices(); diff --git a/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc index 8a83b5f76a..e549fa5654 100644 --- a/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc +++ b/src/trace_processor/importers/proto/proto_trace_parser_impl_unittest.cc @@ -279,8 +279,8 @@ class ProtoTraceParserTest : public ::testing::Test { context_.clock_tracker.reset(clock_); context_.flow_tracker.reset(new FlowTracker(&context_)); context_.proto_trace_parser.reset(new ProtoTraceParserImpl(&context_)); - context_.sorter.reset(new TraceSorter(&context_, - TraceSorter::SortingMode::kFullSort)); + context_.sorter.reset( + new TraceSorter(&context_, TraceSorter::SortingMode::kFullSort)); context_.descriptor_pool_.reset(new DescriptorPool()); RegisterDefaultModules(&context_); @@ -296,8 +296,9 @@ class ProtoTraceParserTest : public ::testing::Test { std::vector trace_bytes = trace_.SerializeAsArray(); std::unique_ptr raw_trace(new uint8_t[trace_bytes.size()]); memcpy(raw_trace.get(), trace_bytes.data(), trace_bytes.size()); - context_.chunk_reader.reset(new ProtoTraceReader(&context_)); - auto status = context_.chunk_reader->Parse(TraceBlobView( + context_.chunk_readers.push_back( + std::make_unique(&context_)); + auto status = context_.chunk_readers.back()->Parse(TraceBlobView( TraceBlob::TakeOwnership(std::move(raw_trace), trace_bytes.size()))); ResetTraceBuffers(); diff --git a/src/trace_processor/importers/zip/BUILD.gn b/src/trace_processor/importers/zip/BUILD.gn index 659d3d9ec8..0262e02cd6 100644 --- a/src/trace_processor/importers/zip/BUILD.gn +++ b/src/trace_processor/importers/zip/BUILD.gn @@ -20,7 +20,6 @@ source_set("full") { deps = [ "../../../../gn:default_deps", "../../../../include/perfetto/ext/base:base", - "../../../../protos/perfetto/trace:zero", "../../../trace_processor:storage_minimal", "../../types", "../../util:trace_type", diff --git a/src/trace_processor/importers/zip/zip_trace_reader.cc b/src/trace_processor/importers/zip/zip_trace_reader.cc index f5895ca95f..074aea4e5f 100644 --- a/src/trace_processor/importers/zip/zip_trace_reader.cc +++ b/src/trace_processor/importers/zip/zip_trace_reader.cc @@ -32,28 +32,13 @@ #include "perfetto/trace_processor/trace_blob_view.h" #include "src/trace_processor/forwarding_trace_parser.h" #include "src/trace_processor/importers/android_bugreport/android_bugreport_reader.h" -#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" #include "src/trace_processor/types/trace_processor_context.h" #include "src/trace_processor/util/status_macros.h" #include "src/trace_processor/util/trace_type.h" #include "src/trace_processor/util/zip_reader.h" -#include "protos/perfetto/trace/trace_packet.pbzero.h" - namespace perfetto::trace_processor { -namespace { - -bool HasSymbols(const TraceBlobView& blob) { - bool has_symbols = false; - ProtoTraceTokenizer().Tokenize(blob.copy(), [&](TraceBlobView raw) { - protos::pbzero::TracePacket::Decoder packet(raw.data(), raw.size()); - has_symbols = packet.has_module_symbols(); - return base::ErrStatus("break"); - }); - return has_symbols; -} - -} // namespace ZipTraceReader::ZipTraceReader(TraceProcessorContext* context) : context_(context) {} @@ -65,10 +50,10 @@ bool ZipTraceReader::Entry::operator<(const Entry& rhs) const { // exception. We actually need those are the very end (once whe have all the // Frames). Alternatively we could build a map address -> symbol during // tokenization and use this during parsing to resolve symbols. - if (has_symbols) { + if (trace_type == kSymbolsTraceType) { return false; } - if (rhs.has_symbols) { + if (rhs.trace_type == kSymbolsTraceType) { return true; } @@ -102,10 +87,20 @@ base::Status ZipTraceReader::NotifyEndOfFile() { std::sort(entries.begin(), entries.end()); for (Entry& e : entries) { - parsers_.push_back(std::make_unique(context_)); - auto& parser = *parsers_.back(); + ScopedActiveTraceFile trace_file = + context_->trace_file_tracker->StartNewFile(e.name, e.trace_type, + e.uncompressed_data.size()); + + auto chunk_reader = std::make_unique(context_); + auto& parser = *chunk_reader; + context_->chunk_readers.push_back(std::move(chunk_reader)); + RETURN_IF_ERROR(parser.Parse(std::move(e.uncompressed_data))); RETURN_IF_ERROR(parser.NotifyEndOfFile()); + + // Make sure the ForwardingTraceParser determined the same trace type as we + // did. + PERFETTO_CHECK(parser.trace_type() == e.trace_type); } return base::OkStatus(); } @@ -128,8 +123,6 @@ ZipTraceReader::ExtractEntries(std::vector files) { TraceBlobView(TraceBlob::CopyFrom(buffer.data(), buffer.size())); entry.trace_type = GuessTraceType(entry.uncompressed_data.data(), entry.uncompressed_data.size()); - entry.has_symbols = entry.trace_type == TraceType::kProtoTraceType && - HasSymbols(entry.uncompressed_data); entries.push_back(std::move(entry)); } return std::move(entries); diff --git a/src/trace_processor/importers/zip/zip_trace_reader.h b/src/trace_processor/importers/zip/zip_trace_reader.h index 29857bf245..b6620aef22 100644 --- a/src/trace_processor/importers/zip/zip_trace_reader.h +++ b/src/trace_processor/importers/zip/zip_trace_reader.h @@ -58,8 +58,6 @@ class ZipTraceReader : public ChunkedTraceReader { // data needed to correctly parse other traces. TraceType trace_type; TraceBlobView uncompressed_data; - // True for proto trace_types whose fist message is a ModuleSymbols packet - bool has_symbols = false; // Comparator used to determine the order in which files in the ZIP will be // read. bool operator<(const Entry& rhs) const; @@ -71,11 +69,6 @@ class ZipTraceReader : public ChunkedTraceReader { TraceProcessorContext* const context_; util::ZipReader zip_reader_; - // For every file in the ZIP we will create a `ForwardingTraceParser`instance - // and send that file to it for tokenization. The instances are kept around - // here as some tokenizers might keep state that is later needed after - // sorting. - std::vector> parsers_; }; } // namespace perfetto::trace_processor diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h index 4ec0a99566..74862f1270 100644 --- a/src/trace_processor/storage/trace_storage.h +++ b/src/trace_processor/storage/trace_storage.h @@ -626,6 +626,13 @@ class TraceStorage { return &profiler_smaps_table_; } + const tables::TraceFileTable& trace_file_table() const { + return trace_file_table_; + } + tables::TraceFileTable* mutable_trace_file_table() { + return &trace_file_table_; + } + const tables::StackSampleTable& stack_sample_table() const { return stack_sample_table_; } @@ -1156,6 +1163,8 @@ class TraceStorage { android_game_intervention_list_table_{&string_pool_}; tables::ProfilerSmapsTable profiler_smaps_table_{&string_pool_}; + tables::TraceFileTable trace_file_table_{&string_pool_}; + // Symbol tables (mappings from frames to symbol names) tables::SymbolTable symbol_table_{&string_pool_}; tables::HeapGraphObjectTable heap_graph_object_table_{&string_pool_}; diff --git a/src/trace_processor/tables/metadata_tables.py b/src/trace_processor/tables/metadata_tables.py index 06057abc0d..c6db97d349 100644 --- a/src/trace_processor/tables/metadata_tables.py +++ b/src/trace_processor/tables/metadata_tables.py @@ -443,6 +443,37 @@ ''', })) +TRACE_FILE_TABLE = Table( + python_module=__file__, + class_name='TraceFileTable', + sql_name='__intrinsic_trace_file', + columns=[ + C('parent_id', CppOptional(CppSelfTableId())), + C('name', CppOptional(CppString())), + C('size', CppInt64()), + C('trace_type', CppString()), + ], + tabledoc=TableDoc( + doc=''' + Metadata related to the trace file parsed. Note the order in which + the files appear in this table corresponds to the order in which + they are read and sent to the tokenization stage. + ''', + group='Misc', + columns={ + 'parent_id': + ''' + Parent file. E.g. files contained in a zip file will point to + the zip file. + ''', + 'name': + '''File name, if known, NULL otherwise''', + 'size': + '''Size in bytes''', + 'trace_type': + '''Trace type''', + })) + # Keep this list sorted. ALL_TABLES = [ ARG_TABLE, @@ -457,4 +488,5 @@ PROCESS_TABLE, RAW_TABLE, THREAD_TABLE, + TRACE_FILE_TABLE, ] diff --git a/src/trace_processor/tables/table_destructors.cc b/src/trace_processor/tables/table_destructors.cc index 81648222a6..229c724d70 100644 --- a/src/trace_processor/tables/table_destructors.cc +++ b/src/trace_processor/tables/table_destructors.cc @@ -64,6 +64,7 @@ ProcessTable::~ProcessTable() = default; FiledescriptorTable::~FiledescriptorTable() = default; ClockSnapshotTable::~ClockSnapshotTable() = default; MachineTable::~MachineTable() = default; +TraceFileTable::~TraceFileTable() = default; // profiler_tables_py.h StackProfileMappingTable::~StackProfileMappingTable() = default; diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc index 0c40faf24f..f4da05f92c 100644 --- a/src/trace_processor/trace_database_integrationtest.cc +++ b/src/trace_processor/trace_database_integrationtest.cc @@ -31,6 +31,8 @@ #include "perfetto/trace_processor/basic_types.h" #include "perfetto/trace_processor/iterator.h" #include "perfetto/trace_processor/status.h" +#include "perfetto/trace_processor/trace_blob.h" +#include "perfetto/trace_processor/trace_blob_view.h" #include "perfetto/trace_processor/trace_processor.h" #include "protos/perfetto/common/descriptor.pbzero.h" #include "protos/perfetto/trace_processor/trace_processor.pbzero.h" @@ -811,5 +813,22 @@ TEST_F(TraceProcessorIntegrationTest, CreateTableDuplicateNames) { ASSERT_THAT(it.Status().message(), HasSubstr("duplicate_b")); } +TEST_F(TraceProcessorIntegrationTest, InvalidTrace) { + constexpr char kBadData[] = "\0\0\0\0"; + EXPECT_FALSE(Processor() + ->Parse(TraceBlobView( + TraceBlob::CopyFrom(kBadData, sizeof(kBadData)))) + .ok()); + Processor()->NotifyEndOfFile(); +} + +TEST_F(TraceProcessorIntegrationTest, NoNotifyEndOfFileCalled) { + constexpr char kProtoData[] = "\x0a"; + EXPECT_TRUE(Processor() + ->Parse(TraceBlobView( + TraceBlob::CopyFrom(kProtoData, sizeof(kProtoData)))) + .ok()); +} + } // namespace } // namespace perfetto::trace_processor diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc index 239cf7842e..0da469324f 100644 --- a/src/trace_processor/trace_processor_context.cc +++ b/src/trace_processor/trace_processor_context.cc @@ -15,6 +15,7 @@ */ #include "src/trace_processor/types/trace_processor_context.h" +#include #include #include "src/trace_processor/forwarding_trace_parser.h" @@ -38,6 +39,7 @@ #include "src/trace_processor/importers/common/slice_tracker.h" #include "src/trace_processor/importers/common/slice_translation_table.h" #include "src/trace_processor/importers/common/stack_profile_tracker.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" #include "src/trace_processor/importers/common/track_tracker.h" #include "src/trace_processor/importers/ftrace/ftrace_module.h" #include "src/trace_processor/importers/proto/android_track_event.descriptor.h" @@ -105,6 +107,8 @@ TraceProcessorContext::TraceProcessorContext(const InitArgs& args) [this](TrackId track_id, SliceId slice_id) { flow_tracker->ClosePendingEventsOnTrack(track_id, slice_id); }); + + trace_file_tracker = std::make_unique(this); } TraceProcessorContext::TraceProcessorContext() = default; diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc index 2d537b4ab6..5aae20b095 100644 --- a/src/trace_processor/trace_processor_impl.cc +++ b/src/trace_processor/trace_processor_impl.cc @@ -47,6 +47,7 @@ #include "src/trace_processor/importers/android_bugreport/android_log_reader.h" #include "src/trace_processor/importers/common/clock_tracker.h" #include "src/trace_processor/importers/common/metadata_tracker.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" #include "src/trace_processor/importers/common/trace_parser.h" #include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h" #include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h" @@ -297,34 +298,6 @@ void InsertIntoTraceMetricsTable(sqlite3* db, const std::string& metric_name) { } } -const char* TraceTypeToString(TraceType trace_type) { - switch (trace_type) { - case kUnknownTraceType: - return "unknown"; - case kProtoTraceType: - return "proto"; - case kJsonTraceType: - return "json"; - case kFuchsiaTraceType: - return "fuchsia"; - case kSystraceTraceType: - return "systrace"; - case kGzipTraceType: - return "gzip"; - case kCtraceTraceType: - return "ctrace"; - case kNinjaLogTraceType: - return "ninja_log"; - case kZipFile: - return "zip"; - case kPerfDataTraceType: - return "perf_data"; - case kAndroidLogcatTraceType: - return "android_logcat"; - } - PERFETTO_FATAL("For GCC"); -} - sql_modules::NameToModule GetStdlibModules() { sql_modules::NameToModule modules; for (const auto& file_to_sql : stdlib::kFileToSql) { @@ -446,14 +419,6 @@ void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) { void TraceProcessorImpl::Flush() { TraceProcessorStorageImpl::Flush(); - - context_.metadata_tracker->SetMetadata( - metadata::trace_size_bytes, - Variadic::Integer(static_cast(bytes_parsed_))); - const StringId trace_type_id = - context_.storage->InternString(TraceTypeToString(context_.trace_type)); - context_.metadata_tracker->SetMetadata(metadata::trace_type, - Variadic::String(trace_type_id)); BuildBoundsTable(engine_->sqlite_engine()->db(), context_.storage->GetTraceTimestampBoundsNs()); } @@ -855,6 +820,7 @@ void TraceProcessorImpl::InitPerfettoSqlEngine() { RegisterStaticTable(storage->mutable_thread_table()); RegisterStaticTable(storage->mutable_process_table()); RegisterStaticTable(storage->mutable_filedescriptor_table()); + RegisterStaticTable(storage->mutable_trace_file_table()); RegisterStaticTable(storage->mutable_slice_table()); RegisterStaticTable(storage->mutable_flow_table()); diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc index c09a934569..7478dd9438 100644 --- a/src/trace_processor/trace_processor_storage_impl.cc +++ b/src/trace_processor/trace_processor_storage_impl.cc @@ -40,6 +40,7 @@ #include "src/trace_processor/importers/common/slice_tracker.h" #include "src/trace_processor/importers/common/slice_translation_table.h" #include "src/trace_processor/importers/common/stack_profile_tracker.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" #include "src/trace_processor/importers/common/track_tracker.h" #include "src/trace_processor/importers/perf/dso_tracker.h" #include "src/trace_processor/importers/proto/chrome_track_event.descriptor.h" @@ -53,6 +54,7 @@ #include "src/trace_processor/sorter/trace_sorter.h" #include "src/trace_processor/trace_reader_registry.h" #include "src/trace_processor/util/descriptors.h" +#include "src/trace_processor/util/trace_type.h" namespace perfetto::trace_processor { @@ -60,6 +62,8 @@ TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) : context_({cfg, std::make_shared(cfg)}) { context_.reader_registry->RegisterTraceReader( kProtoTraceType); + context_.reader_registry->RegisterTraceReader( + kSymbolsTraceType); context_.proto_trace_parser = std::make_unique(&context_); RegisterDefaultModules(&context_); @@ -73,8 +77,12 @@ base::Status TraceProcessorStorageImpl::Parse(TraceBlobView blob) { if (unrecoverable_parse_error_) return base::ErrStatus( "Failed unrecoverably while parsing in a previous Parse call"); - if (!context_.chunk_reader) - context_.chunk_reader.reset(new ForwardingTraceParser(&context_)); + if (!parser_) { + active_file_ = context_.trace_file_tracker->StartNewFile(); + auto parser = std::make_unique(&context_); + parser_ = parser.get(); + context_.chunk_readers.push_back(std::move(parser)); + } auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats( stats::parse_trace_duration_ns); @@ -91,7 +99,8 @@ base::Status TraceProcessorStorageImpl::Parse(TraceBlobView blob) { Variadic::String(id_for_uuid)); } - base::Status status = context_.chunk_reader->Parse(std::move(blob)); + active_file_->AddSize(blob.size()); + base::Status status = parser_->Parse(std::move(blob)); unrecoverable_parse_error_ |= !status.ok(); return status; } @@ -106,14 +115,17 @@ void TraceProcessorStorageImpl::Flush() { } base::Status TraceProcessorStorageImpl::NotifyEndOfFile() { - if (!context_.chunk_reader) { + if (!parser_) { return base::OkStatus(); } if (unrecoverable_parse_error_) { return base::ErrStatus("Unrecoverable parsing error already occurred"); } Flush(); - RETURN_IF_ERROR(context_.chunk_reader->NotifyEndOfFile()); + RETURN_IF_ERROR(parser_->NotifyEndOfFile()); + PERFETTO_CHECK(active_file_.has_value()); + active_file_->SetTraceType(parser_->trace_type()); + active_file_.reset(); // NotifyEndOfFile might have pushed packets to the sorter. Flush(); for (std::unique_ptr& module : context_.modules) { @@ -134,6 +146,8 @@ base::Status TraceProcessorStorageImpl::NotifyEndOfFile() { } void TraceProcessorStorageImpl::DestroyContext() { + // End any active files. Eg. when NotifyEndOfFile is not called. + active_file_.reset(); TraceProcessorContext context; context.storage = std::move(context_.storage); @@ -148,6 +162,9 @@ void TraceProcessorStorageImpl::DestroyContext() { context_ = std::move(context); + // This is now a dangling pointer, reset it. + parser_ = nullptr; + // TODO(chinglinyu): also need to destroy secondary contextes. } diff --git a/src/trace_processor/trace_processor_storage_impl.h b/src/trace_processor/trace_processor_storage_impl.h index 0b03eb5d9d..bab8961b3e 100644 --- a/src/trace_processor/trace_processor_storage_impl.h +++ b/src/trace_processor/trace_processor_storage_impl.h @@ -18,16 +18,20 @@ #define SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_IMPL_H_ #include +#include #include "perfetto/ext/base/hash.h" #include "perfetto/trace_processor/basic_types.h" #include "perfetto/trace_processor/status.h" #include "perfetto/trace_processor/trace_processor_storage.h" +#include "src/trace_processor/importers/common/trace_file_tracker.h" #include "src/trace_processor/types/trace_processor_context.h" namespace perfetto { namespace trace_processor { +class ForwardingTraceParser; + class TraceProcessorStorageImpl : public TraceProcessorStorage { public: explicit TraceProcessorStorageImpl(const Config&); @@ -46,6 +50,8 @@ class TraceProcessorStorageImpl : public TraceProcessorStorage { TraceProcessorContext context_; bool unrecoverable_parse_error_ = false; size_t hash_input_size_remaining_ = 4096; + ForwardingTraceParser* parser_ = nullptr; + std::optional active_file_; }; } // namespace trace_processor diff --git a/src/trace_processor/trace_reader_registry.cc b/src/trace_processor/trace_reader_registry.cc index b2fb87ff7c..b0712957e2 100644 --- a/src/trace_processor/trace_reader_registry.cc +++ b/src/trace_processor/trace_reader_registry.cc @@ -29,6 +29,7 @@ const char kNoZlibErr[] = bool RequiresZlibSupport(TraceType type) { switch (type) { case kGzipTraceType: + case kAndroidBugreportTraceType: case kCtraceTraceType: case kZipFile: return true; @@ -40,7 +41,9 @@ bool RequiresZlibSupport(TraceType type) { case kJsonTraceType: case kFuchsiaTraceType: case kProtoTraceType: + case kSymbolsTraceType: case kAndroidLogcatTraceType: + case kAndroidDumpstateTraceType: return false; } PERFETTO_FATAL("For GCC"); @@ -59,11 +62,11 @@ TraceReaderRegistry::CreateTraceReader(TraceType type) { } if (RequiresZlibSupport(type) && !util::IsGzipSupported()) { - return base::ErrStatus("%s support is disabled. %s", ToString(type), - kNoZlibErr); + return base::ErrStatus("%s support is disabled. %s", + TraceTypeToString(type), kNoZlibErr); } - return base::ErrStatus("%s support is disabled", ToString(type)); + return base::ErrStatus("%s support is disabled", TraceTypeToString(type)); } } // namespace perfetto::trace_processor diff --git a/src/trace_processor/types/trace_processor_context.h b/src/trace_processor/types/trace_processor_context.h index cfa6e7818f..909959c3c6 100644 --- a/src/trace_processor/types/trace_processor_context.h +++ b/src/trace_processor/types/trace_processor_context.h @@ -63,6 +63,7 @@ class SchedEventTracker; class SliceTracker; class SliceTranslationTable; class StackProfileTracker; +class TraceFileTracker; class TraceReaderRegistry; class TraceSorter; class TraceStorage; @@ -93,7 +94,10 @@ class TraceProcessorContext { std::unique_ptr reader_registry; - std::unique_ptr chunk_reader; + // We might create multiple `ChunkedTraceReader` instances (e.g. one for each + // file in a ZIP ). The instances are kept around here as some tokenizers + // might keep state that is later needed after sorting. + std::vector> chunk_readers; // The sorter is used to sort trace data by timestamp and is shared among // multiple machines. @@ -123,6 +127,7 @@ class TraceProcessorContext { std::unique_ptr stack_profile_tracker; std::unique_ptr metadata_tracker; std::unique_ptr cpu_tracker; + std::unique_ptr trace_file_tracker; // These fields are stored as pointers to Destructible objects rather than // their actual type (a subclass of Destructible), as the concrete subclass @@ -181,8 +186,6 @@ class TraceProcessorContext { // 4KB of the trace. bool uuid_found_in_trace = false; - TraceType trace_type = kUnknownTraceType; - std::optional machine_id() const; // Manages the contexts for reading trace data emitted from remote machines. diff --git a/src/trace_processor/util/BUILD.gn b/src/trace_processor/util/BUILD.gn index cb53395f80..b857bd03fd 100644 --- a/src/trace_processor/util/BUILD.gn +++ b/src/trace_processor/util/BUILD.gn @@ -277,6 +277,7 @@ source_set("trace_type") { deps = [ "../../../gn:default_deps", "../../../include/perfetto/ext/base", + "../../../protos/perfetto/trace:non_minimal_zero", "../importers/android_bugreport:android_log_event", ] } diff --git a/src/trace_processor/util/trace_type.cc b/src/trace_processor/util/trace_type.cc index fbc1c90e3e..c4a5762a87 100644 --- a/src/trace_processor/util/trace_type.cc +++ b/src/trace_processor/util/trace_type.cc @@ -26,6 +26,9 @@ #include "perfetto/ext/base/string_view.h" #include "src/trace_processor/importers/android_bugreport/android_log_event.h" +#include "protos/perfetto/trace/trace.pbzero.h" +#include "protos/perfetto/trace/trace_packet.pbzero.h" + namespace perfetto::trace_processor { namespace { // Fuchsia traces have a magic number as documented here: @@ -38,6 +41,13 @@ constexpr char kZipMagic[] = {'P', 'K', '\x03', '\x04'}; constexpr char kGzipMagic[] = {'\x1f', '\x8b'}; +constexpr uint8_t kTracePacketTag = + protozero::proto_utils::MakeTagLengthDelimited( + protos::pbzero::Trace::kPacketFieldNumber); +constexpr uint16_t kModuleSymbolsTag = + protozero::proto_utils::MakeTagLengthDelimited( + protos::pbzero::TracePacket::kModuleSymbolsFieldNumber); + inline bool isspace(unsigned char c) { return ::isspace(c); } @@ -64,32 +74,68 @@ base::StringView FindLine(const uint8_t* data, size_t size) { return base::StringView(); } +bool IsProtoTraceWithSymbols(const uint8_t* ptr, size_t size) { + const uint8_t* const end = ptr + size; + + uint64_t tag; + const uint8_t* next = protozero::proto_utils::ParseVarInt(ptr, end, &tag); + + if (next == ptr || tag != kTracePacketTag) { + return false; + } + + ptr = next; + uint64_t field_length; + next = protozero::proto_utils::ParseVarInt(ptr, end, &field_length); + if (next == ptr) { + return false; + } + ptr = next; + + if (field_length == 0) { + return false; + } + + next = protozero::proto_utils::ParseVarInt(ptr, end, &tag); + if (next == ptr) { + return false; + } + + return tag == kModuleSymbolsTag; +} + } // namespace -const char* ToString(TraceType trace_type) { +const char* TraceTypeToString(TraceType trace_type) { switch (trace_type) { case kJsonTraceType: - return "JSON trace"; + return "json"; case kProtoTraceType: - return "proto trace"; + return "proto"; + case kSymbolsTraceType: + return "symbols"; case kNinjaLogTraceType: - return "ninja log"; + return "ninja_log"; case kFuchsiaTraceType: - return "fuchsia trace"; + return "fuchsia"; case kSystraceTraceType: - return "systrace trace"; + return "systrace"; case kGzipTraceType: - return "gzip trace"; + return "gzip"; case kCtraceTraceType: - return "ctrace trace"; + return "ctrace"; case kZipFile: - return "ZIP file"; + return "zip"; case kPerfDataTraceType: - return "perf data"; + return "perf"; case kAndroidLogcatTraceType: - return "Android logcat"; + return "android_logcat"; + case kAndroidDumpstateTraceType: + return "android_dumpstate"; + case kAndroidBugreportTraceType: + return "android_bugreport"; case kUnknownTraceType: - return "unknown trace"; + return "unknown"; } PERFETTO_FATAL("For GCC"); } @@ -157,6 +203,9 @@ TraceType GuessTraceType(const uint8_t* data, size_t size) { if (base::StartsWith(start, " ")) return kSystraceTraceType; + if (IsProtoTraceWithSymbols(data, size)) + return kSymbolsTraceType; + if (base::StartsWith(start, "\x0a")) return kProtoTraceType; diff --git a/src/trace_processor/util/trace_type.h b/src/trace_processor/util/trace_type.h index 4e31f45875..7e730fc4d9 100644 --- a/src/trace_processor/util/trace_type.h +++ b/src/trace_processor/util/trace_type.h @@ -23,22 +23,25 @@ namespace perfetto::trace_processor { enum TraceType { - kUnknownTraceType, - kProtoTraceType, - kJsonTraceType, + kAndroidBugreportTraceType, + kAndroidDumpstateTraceType, + kAndroidLogcatTraceType, + kCtraceTraceType, kFuchsiaTraceType, - kSystraceTraceType, kGzipTraceType, - kCtraceTraceType, + kJsonTraceType, kNinjaLogTraceType, - kZipFile, kPerfDataTraceType, - kAndroidLogcatTraceType, + kProtoTraceType, + kSymbolsTraceType, + kSystraceTraceType, + kUnknownTraceType, + kZipFile, }; constexpr size_t kGuessTraceMaxLookahead = 64; TraceType GuessTraceType(const uint8_t* data, size_t size); -const char* ToString(TraceType type); +const char* TraceTypeToString(TraceType type); } // namespace perfetto::trace_processor diff --git a/test/trace_processor/diff_tests/parser/android/tests_bugreport.py b/test/trace_processor/diff_tests/parser/android/tests_bugreport.py index 790b529848..d67867dbb2 100644 --- a/test/trace_processor/diff_tests/parser/android/tests_bugreport.py +++ b/test/trace_processor/diff_tests/parser/android/tests_bugreport.py @@ -59,3 +59,19 @@ def test_android_bugreport_dumpsys(self): WHERE service = 'color_display'; """, out=Path('android_bugreport_dumpsys_test.out')) + + def test_android_bugreport_trace_types(self): + return DiffTestBlueprint( + trace=DataPath('bugreport-crosshatch-SPB5.zip'), + query=""" + SELECT * + FROM __intrinsic_trace_file + ORDER BY id + """, + out=Csv(""" + "id","type","parent_id","name","size","trace_type" + 0,"__intrinsic_trace_file","[NULL]","[NULL]",6220586,"zip" + 1,"__intrinsic_trace_file",0,"FS/data/misc/logd/logcat.01",2169697,"android_logcat" + 2,"__intrinsic_trace_file",0,"FS/data/misc/logd/logcat",2152073,"android_logcat" + 3,"__intrinsic_trace_file",0,"bugreport-crosshatch-SPB5.210812.002-2021-08-24-23-35-40.txt",43132864,"android_dumpstate" + """)) \ No newline at end of file diff --git a/test/trace_processor/diff_tests/parser/zip/tests.py b/test/trace_processor/diff_tests/parser/zip/tests.py index 7846046ce2..51ce024c51 100644 --- a/test/trace_processor/diff_tests/parser/zip/tests.py +++ b/test/trace_processor/diff_tests/parser/zip/tests.py @@ -58,3 +58,19 @@ def test_perf_proto_sym(self): "main,D,E" "main,E" ''')) + + def test_tokenization_order(self): + return DiffTestBlueprint( + trace=DataPath('zip/perf_track_sym.zip'), + query=''' + SELECT * + FROM __intrinsic_trace_file + ORDER BY id + ''', + out=Csv(''' + "id","type","parent_id","name","size","trace_type" + 0,"__intrinsic_trace_file","[NULL]","[NULL]",94651,"zip" + 1,"__intrinsic_trace_file",0,"c.trace.pb",379760,"proto" + 2,"__intrinsic_trace_file",0,"b.simpleperf.data",554911,"perf" + 3,"__intrinsic_trace_file",0,"a.symbols.pb",186149,"symbols" + ''')) \ No newline at end of file