Skip to content

Commit 1cb6d0a

Browse files
committed
devlib.collector: Add PerfettoCollector
Add a Collector for accessing Google's Perfetto tracing infrastructure. The Collector takes a path to an on-device config file, starts tracing in the background using the perfetto binary and then stops by killing the tracing process. Signed-off-by: Kajetan Puchalski <[email protected]>
1 parent 0a91007 commit 1cb6d0a

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

devlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
from devlib.derived.fps import DerivedGfxInfoStats, DerivedSurfaceFlingerStats
4747

4848
from devlib.collector.ftrace import FtraceCollector
49+
from devlib.collector.perfetto import PerfettoCollector
4950
from devlib.collector.perf import PerfCollector
5051
from devlib.collector.serial_trace import SerialTraceCollector
5152
from devlib.collector.dmesg import DmesgCollector

devlib/collector/perfetto.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Copyright 2023 ARM Limited
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
16+
import os
17+
import time
18+
import subprocess
19+
from shlex import quote
20+
21+
from devlib.collector import (CollectorBase, CollectorOutput,
22+
CollectorOutputEntry)
23+
from devlib.exception import TargetStableError, HostError
24+
from devlib.utils.misc import check_output, which, memoized
25+
26+
OUTPUT_PERFETTO_TRACE = 'trace.perfetto-trace'
27+
28+
class PerfettoCollector(CollectorBase):
29+
30+
def __init__(self, target, config=None):
31+
super().__init__(target)
32+
self.target_output_file = target.path.join(self.target.working_directory, OUTPUT_PERFETTO_TRACE)
33+
self.bg_cmd = None
34+
self.config = config
35+
36+
if not self.target.is_installed('perfetto'):
37+
raise TargetStableError('No perfetto found on device.')
38+
self.target_binary = 'perfetto'
39+
40+
def start(self):
41+
cmd = "cat {} | {} --txt -c - -o {}".format(
42+
quote(self.config), quote(self.target_binary), quote(self.target_output_file)
43+
)
44+
# start tracing
45+
if self.bg_cmd is None:
46+
self.bg_cmd = self.target.background(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
47+
else:
48+
raise TargetStableError('Perfetto collector is not re-entrant')
49+
50+
51+
def stop(self):
52+
# stop tracing
53+
self.bg_cmd.cancel()
54+
self.bg_cmd = None
55+
56+
def set_output(self, output_path):
57+
if os.path.isdir(output_path):
58+
output_path = os.path.join(output_path, os.path.basename(self.target_output_file))
59+
self.output_path = output_path
60+
61+
def get_data(self):
62+
if self.output_path is None:
63+
raise RuntimeError("Output path was not set.")
64+
self.target.pull(self.target_output_file, self.output_path)
65+
output = CollectorOutput()
66+
if not os.path.isfile(self.output_path):
67+
self.logger.warning('Perfetto trace not pulled from device.')
68+
else:
69+
output.append(CollectorOutputEntry(self.output_path, 'file'))
70+
return output
71+

0 commit comments

Comments
 (0)