blob: ed3a650f3fd0179fca6f29093cd8667597484415 [file] [log] [blame]
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from recipe_engine import recipe_api
class SymbolizeApi(recipe_api.RecipeApi):
"""Symbolizes logs."""
OUTPUT_JSON = "symbolizer-output.json"
def __call__(
self,
symbolizer_tool,
data,
name="symbolize logs",
build_id_dirs=(),
debug_symbol_url=None,
symbolizer_output=None,
json_output=None,
):
"""Invokes zircon's symbolization script to symbolize the given data.
Args:
symbolizer_tool (Path): The path to the symbolizer tool.
data (String): Step output.
build_id_dirs (seq(Path)): A list of build-id directories.
debug_symbol_url (str): A GCS URL hosting debug symbols.
symbolizer_output (Path): The path to save the symbolizer stdout to.
json_output (Path): The path to save the symbolizer json trigger
information to.
Returns:
Symbolizer output, split into lines.
"""
assert (
build_id_dirs or debug_symbol_url
), "one of a build-id directory or debug_symbol_url must be supplied"
symbolizer_cmd = [symbolizer_tool]
for build_id_dir in build_id_dirs:
symbolizer_cmd.extend(["--build-id-dir", build_id_dir])
if debug_symbol_url:
# The symbolize tool accepts a "symbol-server" argument which
# in reality is a GCS URL hosting debug symbols indexed by build ID.
symbolizer_cmd.extend(["--symbol-server", debug_symbol_url])
symbolizer_cmd.extend(
["--symbol-cache", self.m.path["cache"].join("symbol")]
)
if json_output:
# We intentionally avoid using a json output placeholder here because
# doing so would require loading the entire (possibly massive) symbolizer
# output json into memory, which can cause OOMs.
symbolizer_cmd.extend(["--dumpfile-output", json_output])
try:
return self.m.step(
name,
symbolizer_cmd,
stdin=self.m.raw_io.input(data=data),
stdout=self.m.raw_io.output(leak_to=symbolizer_output),
step_test_data=lambda: self.m.raw_io.test_api.stream_output(data),
infra_step=True,
# Very lenient timeout, just to ensure that we get a step
# failure and can obtain logs in case the symbolizer encounters
# a hang.
timeout=30 * 60,
).stdout
except self.m.step.StepFailure:
step = self.m.step.active_result
# Log stdin and stdout for easier debugging.
step.presentation.logs["stdin"] = data.splitlines()
# We could use the `add_output_log` arg to raw_io.output() to add
# this log, but it results in a less concise log name, and isn't
# supported for input placeholders, so stdout and stdin would be
# logged in different ways.
step.presentation.logs["stdout"] = step.stdout.splitlines()
raise