blob: fa709054a7056c54a5f01872b5e77c3dcdcbdd4f [file] [log] [blame]
# 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.
"""Utility to extract parts of a trace based on a SQL expression"""
import sys
import logging
from .model import TraceAnalysisSession, FileTraceContext
from .sql import identifier_quote
from ._native import dump_events_to_fd
from .util import ureg
log = logging.getLogger(__name__)
def run_subset(*,
trace_file_name,
filter_expression,
absolute_time=False,
out_file=None):
"""Run the subset command-line utility"""
trace_session = TraceAnalysisSession()
time_basis_override = 0 if absolute_time else None
trace_session.mount_trace(["trace"],
FileTraceContext(
trace_file_name,
time_basis_override=time_basis_override),
temp_hack_lenient_metadata=True)
q = "SELECT type FROM trace.found_event_types"
found_event_types = trace_session.sql_query1(q).tolist()
if not found_event_types:
log.warning("no events found in trace?!")
return
def _query_for_event_type(event_type):
return "SELECT _pos FROM trace.raw_events.{} WHERE ({})".format(
identifier_quote(event_type), filter_expression)
queries = [_query_for_event_type(event_type)
for event_type in found_event_types]
valid_queries = []
for event_type, query in zip(found_event_types, queries):
try:
trace_session.parse_sql_query(query)
except Exception as ex:
log.warning("query %r does not work for event type %r: "
"filtering out this event type", query, event_type)
log.warning("query error was %r", ex)
continue
valid_queries.append(query)
if not valid_queries:
log.warning("no events could, syntactically, match filter!")
return
q = " UNION ALL ".join(
"({})".format(query) for query in valid_queries) + " ORDER BY _pos"
cursor = trace_session.sql_query(q,
output_format="rows",
want_schema=True)
trace_info = trace_session.get_mounted_trace(["trace"])
nr_cpus = trace_info.metadata.get("nr_cpus")
out_file = out_file or sys.stdout
if nr_cpus is not None:
out_file.write("cpus={}\n".format(nr_cpus))
out_file.flush()
mapping = trace_info.mapped_trace.mapping
for row, _is_eof in cursor:
pos_array, pos_schema = row["_pos"]
assert pos_schema.unit == ureg().bytes
dump_events_to_fd(mapping, pos_array, out_file.fileno())
out_file.flush()