pkg_size: create a simple CLI tool to dump a system size report
pkg_size dumps the sizes of the packages contained within a built root.
It will also push gauge data (package size) per package and per
invocation (total root size) to the build api metrics append-only queue
via append_metrics_log. This data is to be used for build metrics trend
reporting.
BUG=chromium:1000449
TEST=cros_sdk -- '$HOME/trunk/chromite/run_tests'
Cq-Depend: chromium:1834120
Change-Id: I735057f9bcfe4de367a8df888e76a09836e371d1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/1801037
Tested-by: Will Bradley <wbbradley@chromium.org>
Commit-Queue: Will Bradley <wbbradley@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Alex Klein <saklein@chromium.org>
diff --git a/scripts/emit_metric.py b/scripts/emit_metric.py
index 9e58dba..928365c 100644
--- a/scripts/emit_metric.py
+++ b/scripts/emit_metric.py
@@ -14,16 +14,19 @@
def main(argv):
"""Emit a metric event."""
parser = commandline.ArgumentParser(description=__doc__)
- parser.add_argument('op', choices=metrics.VALID_OPS,
+ parser.add_argument('op', choices=sorted(metrics.VALID_OPS),
help='Which metric event operator to emit.')
parser.add_argument('name',
help='The name of the metric event as you would like it '
'to appear downstream in data stores.')
- parser.add_argument('key', nargs='?',
- help='A unique key for this invocation to ensure that '
- 'start and stop timers can be matched.')
+ parser.add_argument('arg', nargs='?',
+ help='An accessory argument dependent upon the "op".')
opts = parser.parse_args(argv)
+ if opts.arg and not metrics.OP_EXPECTS_ARG[opts.op]:
+ # We do not expect to get an |arg| for this |op|.
+ parser.error('Unexpected arg "%s" given for op "%s"' % (opts.arg,
+ opts.op))
+
timestamp = metrics.current_milli_time()
- key = opts.key or opts.name
- metrics.append_metrics_log(timestamp, opts.name, opts.op, key=key)
+ metrics.append_metrics_log(timestamp, opts.name, opts.op, arg=opts.arg)
diff --git a/scripts/pkg_size b/scripts/pkg_size
new file mode 120000
index 0000000..b7045c5
--- /dev/null
+++ b/scripts/pkg_size
@@ -0,0 +1 @@
+wrapper.py
\ No newline at end of file
diff --git a/scripts/pkg_size.py b/scripts/pkg_size.py
new file mode 100644
index 0000000..1a7e845
--- /dev/null
+++ b/scripts/pkg_size.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The Package Size Reporting CLI entry point."""
+
+from __future__ import print_function
+
+import json
+
+from chromite.lib import commandline
+from chromite.lib import portage_util
+from chromite.utils import metrics
+
+
+def _get_parser():
+ """Create an argument parser for this script."""
+ parser = commandline.ArgumentParser(description=__doc__)
+ parser.add_argument('--root', required=True, type='path',
+ help='Specify the rootfs to investigate.')
+ parser.add_argument('--image-type',
+ help='Specify the type of image being investigated. '
+ 'e.g. [base, dev, test]')
+ parser.add_argument('--partition-name',
+ help='Specify the partition name. '
+ 'e.g. [rootfs, stateful]')
+ parser.add_argument('packages', nargs='*',
+ help='Names of packages to investigate. Must be '
+ 'specified as category/package-version.')
+ return parser
+
+
+def generate_package_size_report(db, root, image_type, partition_name,
+ installed_packages):
+ """Collect package sizes and generate a report."""
+ results = {}
+ total_size = 0
+ package_sizes = portage_util.GeneratePackageSizes(db, root,
+ installed_packages)
+ timestamp = metrics.current_milli_time()
+ for package_cpv, size in package_sizes:
+ results[package_cpv] = size
+ metrics.append_metrics_log(timestamp,
+ 'package_size.%s.%s.%s' % (image_type,
+ partition_name,
+ package_cpv),
+ metrics.OP_GAUGE,
+ arg=size)
+ total_size += size
+
+ metrics.append_metrics_log(timestamp,
+ 'total_size.%s.%s' % (image_type, partition_name),
+ metrics.OP_GAUGE,
+ arg=total_size)
+ return {'root': root, 'package_sizes': results, 'total_size': total_size}
+
+
+def main(argv):
+ """Find and report approximate size info for a particular built package."""
+ commandline.RunInsideChroot()
+
+ parser = _get_parser()
+ opts = parser.parse_args(argv)
+ opts.Freeze()
+
+ db = portage_util.PortageDB(root=opts.root)
+
+ if opts.packages:
+ installed_packages = portage_util.GenerateInstalledPackages(db, opts.root,
+ opts.packages)
+ else:
+ installed_packages = db.InstalledPackages()
+
+ results = generate_package_size_report(db, opts.root, opts.image_type,
+ opts.partition_name,
+ installed_packages)
+ print(json.dumps(results))