Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
475 changes: 475 additions & 0 deletions Android.bp

Large diffs are not rendered by default.

115 changes: 115 additions & 0 deletions BUILD

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions protos/perfetto/config/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ perfetto_proto_library("@TYPE@") {
"gpu:@TYPE@",
"inode_file:@TYPE@",
"interceptors:@TYPE@",
"linux:@TYPE@",
"power:@TYPE@",
"priority_boost:@TYPE@",
"process_stats:@TYPE@",
Expand Down
4 changes: 4 additions & 0 deletions protos/perfetto/config/data_source_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import "protos/perfetto/config/test_config.proto";
import "protos/perfetto/config/track_event/track_event_config.proto";
import "protos/perfetto/config/system_info/system_info_config.proto";
import "protos/perfetto/config/chrome/histogram_samples.proto";
import "protos/perfetto/config/linux/journald_config.proto";
import "protos/perfetto/config/qnx/qnx_config.proto";

// The configuration that is passed to each data source when starting tracing.
Expand Down Expand Up @@ -305,6 +306,9 @@ message DataSourceConfig {
// Data source name: android.aflags
optional AndroidAflagsConfig android_aflags_config = 140 [lazy = true];

// Data source name: linux.systemd_journald
optional SystemdJournaldConfig journald_config = 141 [lazy = true];

// Data source name: qnx.kernel
optional QnxConfig qnx_config = 150 [lazy = true];

Expand Down
19 changes: 19 additions & 0 deletions protos/perfetto/config/linux/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (C) 2026 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/proto_library.gni")

perfetto_proto_library("@TYPE@") {
sources = [ "journald_config.proto" ]
}
33 changes: 33 additions & 0 deletions protos/perfetto/config/linux/journald_config.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (C) 2026 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.

syntax = "proto2";

package perfetto.protos;

// Configuration for the "linux.systemd_journald" data source.
// Next field id: 4
message SystemdJournaldConfig {
// Minimum syslog priority level to capture (inclusive).
// 0=EMERG, 1=ALERT, 2=CRIT, 3=ERR, 4=WARNING, 5=NOTICE, 6=INFO, 7=DEBUG.
// Default (0 / unset): capture all priorities (equivalent to 7).
optional uint32 min_prio = 1;

// If non-empty, only capture journal entries whose SYSLOG_IDENTIFIER
// matches one of these strings.
repeated string filter_identifiers = 2;

// If non-empty, only capture journal entries from these systemd unit names.
repeated string filter_units = 3;
}
1 change: 1 addition & 0 deletions protos/perfetto/trace/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ perfetto_proto_library("non_minimal_@TYPE@") {
"generic_kernel:@TYPE@",
"gpu:@TYPE@",
"interned_data:@TYPE@",
"linux:@TYPE@",
"perfetto:@TYPE@",
"power:@TYPE@",
"profiling:@TYPE@",
Expand Down
19 changes: 19 additions & 0 deletions protos/perfetto/trace/linux/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (C) 2026 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/proto_library.gni")

perfetto_proto_library("@TYPE@") {
sources = [ "journald_event.proto" ]
}
66 changes: 66 additions & 0 deletions protos/perfetto/trace/linux/journald_event.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (C) 2026 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.

syntax = "proto2";

package perfetto.protos;

// A journald log event packet, collected from the Linux systemd journal.
// Emitted by the "linux.systemd_journald" data source in traced_probes.
// Next field id: 13, statistics starting at 20
message SystemdJournaldEvent {
// _PID: PID of the process that wrote the log entry (trusted).
optional uint32 pid = 1;

// _TID: thread ID of the logging thread (trusted, set by journald for
// native journal protocol entries). Absent for syslog, stdout-piped, and
// kernel entries.
optional uint32 tid = 2;

// _UID: user ID of the process (trusted).
optional uint32 uid = 3;

// _GID: group ID of the process (trusted).
optional uint32 gid = 4;

// PRIORITY: syslog priority level 0 (EMERG) .. 7 (DEBUG).
optional uint32 prio = 5;

// SYSLOG_IDENTIFIER: program name / tag, set by the logging application.
optional string tag = 6;

// MESSAGE: the human-readable log message text.
optional string message = 7;

// _COMM: short process name as known to the kernel (trusted).
optional string comm = 8;

// _EXE: full executable path (trusted).
optional string exe = 9;

// _SYSTEMD_UNIT: the systemd unit that owns this process (trusted).
optional string systemd_unit = 10;

// _HOSTNAME: hostname of the machine (trusted).
optional string hostname = 11;

// _TRANSPORT: how the entry was received by journald (trusted).
// Values: "audit", "driver", "syslog", "journal", "stdout", "kernel".
optional string transport = 12;

// These statistics emitted once on Flush()
optional uint64 num_total = 20;
optional uint64 num_failed = 21;
optional uint64 num_skipped = 22;
}
5 changes: 4 additions & 1 deletion protos/perfetto/trace/trace_packet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import "protos/perfetto/trace/chrome/chrome_trace_event.proto";
import "protos/perfetto/trace/chrome/chrome_trigger.proto";
import "protos/perfetto/trace/chrome/v8.proto";
import "protos/perfetto/trace/clock_snapshot.proto";
import "protos/perfetto/trace/linux/journald_event.proto";
import "protos/perfetto/trace/etw/etw_event_bundle.proto";
import "protos/perfetto/trace/evdev.proto";
import "protos/perfetto/trace/filesystem/inode_file_map.proto";
Expand Down Expand Up @@ -120,7 +121,7 @@ package perfetto.protos;
// See the [Buffers and Dataflow](/docs/concepts/buffers.md) doc for details.
//
// Next reserved id: 14 (up to 15).
// Next id: 132.
// Next id: 133.
message TracePacket {
// Encapsulates the state and configuration of the ProtoVM instances running
// when the trace was snapshotted. This allows TP to re-instantiate the VMs
Expand Down Expand Up @@ -313,6 +314,8 @@ message TracePacket {

AndroidUserList user_list = 123;

SystemdJournaldEvent journald_event = 132;

// This field is only used for testing.
// In previous versions of this proto this field had the id 268435455
// This caused many problems:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,29 @@
#include "src/trace_processor/importers/android_bugreport/android_log_event_parser.h"

#include <cstdint>
#include <optional>
#include <utility>

#include "src/trace_processor/importers/android_bugreport/android_log_event.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/tables/android_tables_py.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/log_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"

namespace perfetto::trace_processor {

AndroidLogEventParser::~AndroidLogEventParser() = default;

void AndroidLogEventParser::Parse(int64_t ts, AndroidLogEvent event) {
tables::AndroidLogTable::Row row;
tables::LogTable::Row row;
row.ts = ts;
row.utid = context_->process_tracker->UpdateThread(event.tid, event.pid);
row.utid = std::make_optional(
context_->process_tracker->UpdateThread(event.tid, event.pid));
row.prio = event.prio;
row.tag = event.tag;
row.log_source = context_->storage->InternString("android_logcat");
row.tag = std::make_optional(event.tag);
row.msg = event.msg;
context_->storage->mutable_android_log_table()->Insert(std::move(row));
context_->storage->mutable_log_table()->Insert(std::move(row));
}

} // namespace perfetto::trace_processor
5 changes: 5 additions & 0 deletions src/trace_processor/importers/common/args_tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "src/trace_processor/tables/android_tables_py.h"
#include "src/trace_processor/tables/counter_tables_py.h"
#include "src/trace_processor/tables/flow_tables_py.h"
#include "src/trace_processor/tables/log_tables_py.h"
#include "src/trace_processor/tables/memory_tables_py.h"
#include "src/trace_processor/tables/metadata_tables_py.h"
#include "src/trace_processor/tables/profiler_tables_py.h"
Expand Down Expand Up @@ -266,6 +267,10 @@ class ArgsTracker {
return AddArgsTo(context_->storage->mutable_trace_import_logs_table(), id);
}

BoundInserter AddArgsTo(tables::LogTable::Id id) {
return AddArgsTo(context_->storage->mutable_log_table(), id);
}

// Returns a CompactArgSet which contains the args inserted into this
// ArgsTracker. Requires that every arg in this tracker was inserted for the
// "arg_set_id" column given by |column| at the given |row_number|.
Expand Down
5 changes: 5 additions & 0 deletions src/trace_processor/importers/proto/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ source_set("full") {
"heap_graph_tracker.h",
"jit_tracker.cc",
"jit_tracker.h",
"linux_probes_module.cc",
"linux_probes_module.h",
"linux_probes_parser.cc",
"linux_probes_parser.h",
"metadata_module.cc",
"metadata_module.h",
"pigweed_detokenizer.cc",
Expand Down Expand Up @@ -211,6 +215,7 @@ source_set("full") {
"../../../../protos/perfetto/trace/gpu:gpu_interned_data_zero",
"../../../../protos/perfetto/trace/gpu:zero",
"../../../../protos/perfetto/trace/interned_data:zero",
"../../../../protos/perfetto/trace/linux:zero",
"../../../../protos/perfetto/trace/power:zero",
"../../../../protos/perfetto/trace/profiling:zero",
"../../../../protos/perfetto/trace/ps:zero",
Expand Down
3 changes: 3 additions & 0 deletions src/trace_processor/importers/proto/additional_modules.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "src/trace_processor/importers/proto/deobfuscation_module.h"
#include "src/trace_processor/importers/proto/graphics_event_module.h"
#include "src/trace_processor/importers/proto/heap_graph_module.h"
#include "src/trace_processor/importers/proto/linux_probes_module.h"
#include "src/trace_processor/importers/proto/metadata_module.h"
#include "src/trace_processor/importers/proto/network_trace_module.h"
#include "src/trace_processor/importers/proto/pixel_modem_module.h"
Expand All @@ -57,6 +58,8 @@ void RegisterAdditionalModules(ProtoImporterModuleContext* module_context,
new AndroidKernelWakelocksModule(module_context, context));
module_context->modules.emplace_back(
new AndroidProbesModule(module_context, context));
module_context->modules.emplace_back(
new LinuxProbesModule(module_context, context));
module_context->modules.emplace_back(
new NetworkTraceModule(module_context, context));
module_context->modules.emplace_back(
Expand Down
12 changes: 10 additions & 2 deletions src/trace_processor/importers/proto/android_probes_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include "src/trace_processor/storage/metadata.h"
#include "src/trace_processor/storage/stats.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/tables/android_tables_py.h"
#include "src/trace_processor/tables/log_tables_py.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/types/variadic.h"

Expand Down Expand Up @@ -477,8 +479,14 @@ void AndroidProbesParser::ParseAndroidLogEvent(int64_t ts,

// Log events are NOT required to be sorted by trace_time. The virtual table
// will take care of sorting on-demand.
context_->storage->mutable_android_log_table()->Insert(
{ts, utid, prio, tag_id, msg_id});
tables::LogTable::Row row;
row.ts = ts;
row.utid = tid ? std::make_optional(utid) : std::nullopt;
row.prio = static_cast<uint32_t>(prio);
row.log_source = context_->storage->InternString("android_logcat");
row.tag = evt.has_tag() ? std::make_optional(tag_id) : std::nullopt;
row.msg = msg_id;
context_->storage->mutable_log_table()->Insert(row);
}

void AndroidProbesParser::ParseAndroidLogStats(protozero::ConstBytes blob) {
Expand Down
60 changes: 60 additions & 0 deletions src/trace_processor/importers/proto/linux_probes_module.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2025 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/proto/linux_probes_module.h"

#include <cstdint>
#include <optional>

#include "perfetto/base/logging.h"
#include "perfetto/protozero/field.h"
#include "perfetto/trace_processor/ref_counted.h"
#include "protos/perfetto/common/builtin_clock.pbzero.h"
#include "protos/perfetto/trace/linux/journald_event.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "src/trace_processor/importers/common/clock_tracker.h"
#include "src/trace_processor/importers/common/parser_types.h"
#include "src/trace_processor/importers/proto/blob_packet_writer.h"
#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/sorter/trace_sorter.h"
#include "src/trace_processor/types/trace_processor_context.h"

namespace perfetto::trace_processor {

using perfetto::protos::pbzero::TracePacket;

LinuxProbesModule::LinuxProbesModule(ProtoImporterModuleContext* module_context,
TraceProcessorContext* context)
: ProtoImporterModule(module_context), parser_(context) {
RegisterForField(TracePacket::kJournaldEventFieldNumber);
}

void LinuxProbesModule::ParseTracePacketData(
const protos::pbzero::TracePacket_Decoder& decoder,
int64_t ts,
const TracePacketData&,
uint32_t field_id) {
switch (field_id) {
case TracePacket::kJournaldEventFieldNumber:
parser_.ParseSystemdJournaldEvent(ts, decoder.journald_event());
return;
default:
PERFETTO_FATAL("Unexpected field_id in LinuxProbesModule");
}
}

} // namespace perfetto::trace_processor
Loading
Loading