Repository: GoogleCloudPlatform/PerfKitBenchmarker

Issue:
Not everything that goes to the console make it into the log
It looks like the final summary results dont get put into the log file.



Discussion:
Those are [written directly to stdout](https://github.com/GoogleCloudPlatform/PerfKitBenchmarker/blob/master/perfkitbenchmarker/publisher.py#L185-L203).  We could either change it emit via `logging`, or log the results at a low level (`DEBUG`?)  prior to printing the results.


Resolving patch:
diff --git a/perfkitbenchmarker/pkb.py b/perfkitbenchmarker/pkb.py
--- a/perfkitbenchmarker/pkb.py
+++ b/perfkitbenchmarker/pkb.py
@@ -73,6 +73,7 @@
 STAGE_PREPARE = 'prepare'
 STAGE_RUN = 'run'
 STAGE_CLEANUP = 'cleanup'
+LOG_FILE_NAME = 'pkb.log'
 REQUIRED_INFO = ['scratch_disk', 'num_machines']
 # List of functions taking a benchmark_spec. Will be called before benchmark.Run
 # with two parameters: the benchmark and benchmark_spec.
@@ -332,7 +333,7 @@ def RunBenchmarks(publish=True):
   vm_util.GenTempDir()
   log_util.ConfigureLogging(
       stderr_log_level=log_util.LOG_LEVELS[FLAGS.log_level],
-      log_path=vm_util.PrependTempDir('pkb.log'),
+      log_path=vm_util.PrependTempDir(LOG_FILE_NAME),
       run_uri=FLAGS.run_uri)
 
   unknown_benchmarks = ListUnknownBenchmarks()
@@ -376,11 +377,15 @@ def RunBenchmarks(publish=True):
     if collector.samples:
       collector.PublishSamples()
 
+    logging.info('Complete logs can be found at: %s',
+                 vm_util.PrependTempDir(LOG_FILE_NAME))
+
   if FLAGS.run_stage not in [STAGE_ALL, STAGE_CLEANUP]:
     logging.info(
         'To run again with this setup, please use --run_uri=%s', FLAGS.run_uri)
 
 
+
 def _GenerateBenchmarkDocumentation():
   """Generates benchmark documentation to show in --help."""
   benchmark_docs = []
diff --git a/perfkitbenchmarker/publisher.py b/perfkitbenchmarker/publisher.py
--- a/perfkitbenchmarker/publisher.py
+++ b/perfkitbenchmarker/publisher.py
@@ -15,6 +15,7 @@
 """Classes to collect and publish performance samples to various sinks."""
 
 import abc
+import io
 import itertools
 import json
 import logging
@@ -227,12 +228,18 @@ def _FormatMetadata(self, metadata):
                     for k, v in sorted(metadata.iteritems()))
 
   def PublishSamples(self, samples):
+    # result will store the formatted text, then be emitted to self.stream and
+    # logged.
+    result = io.BytesIO()
     dashes = '-' * 25
-    self.stream.write('\n' + dashes +
-                      'PerfKitBenchmarker Results Summary' +
-                      dashes + '\n')
+    result.write('\n' + dashes +
+                 'PerfKitBenchmarker Results Summary' +
+                 dashes + '\n')
 
     if not samples:
+      logging.debug('Pretty-printing results to %s:\n%s', self.stream,
+                    result.getvalue())
+      self.stream.write(result.getvalue())
       return
 
     key = operator.itemgetter('test')
@@ -251,27 +258,31 @@ def PublishSamples(self, samples):
 
       benchmark_meta = {k: v for k, v in test_samples[0]['metadata'].iteritems()
                         if k in locally_constant_keys}
-      self.stream.write('{0}:\n'.format(benchmark.upper()))
+      result.write('{0}:\n'.format(benchmark.upper()))
 
       if benchmark_meta:
-        self.stream.write('  {0}\n'.format(
+        result.write('  {0}\n'.format(
             self._FormatMetadata(benchmark_meta)))
 
       for sample in test_samples:
         meta = {k: v for k, v in sample['metadata'].iteritems()
                 if k not in all_constant_meta}
-        self.stream.write('  {0:<30s} {1:>15f} {2:<30s}'.format(
+        result.write('  {0:<30s} {1:>15f} {2:<30s}'.format(
             sample['metric'], sample['value'], sample['unit']))
         if meta:
-          self.stream.write(' ({0})'.format(self._FormatMetadata(meta)))
-        self.stream.write('\n')
+          result.write(' ({0})'.format(self._FormatMetadata(meta)))
+        result.write('\n')
 
     global_meta = {k: v for k, v in samples[0]['metadata'].iteritems()
                    if k in globally_constant_keys}
-    self.stream.write('\n' + dashes + '\n')
-    self.stream.write('For all tests: {0}\n'.format(
+    result.write('\n' + dashes + '\n')
+    result.write('For all tests: {0}\n'.format(
         self._FormatMetadata(global_meta)))
 
+    value = result.getvalue()
+    logging.debug('Pretty-printing results to %s:\n%s', self.stream, value)
+    self.stream.write(value)
+
 
 class LogPublisher(SamplePublisher):
   """Writes samples to a Python Logger.


Test patch: