log_printer.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. from __future__ import unicode_literals
  2. from __future__ import absolute_import
  3. import sys
  4. from itertools import cycle
  5. from .multiplexer import Multiplexer, STOP
  6. from . import colors
  7. from .utils import split_buffer
  8. class LogPrinter(object):
  9. def __init__(self, containers, attach_params=None):
  10. self.containers = containers
  11. self.attach_params = attach_params or {}
  12. self.generators = self._make_log_generators()
  13. def run(self):
  14. mux = Multiplexer(self.generators)
  15. for line in mux.loop():
  16. sys.stdout.write(line.encode(sys.__stdout__.encoding or 'utf8'))
  17. def _make_log_generators(self):
  18. color_fns = cycle(colors.rainbow())
  19. generators = []
  20. for container in self.containers:
  21. color_fn = color_fns.next()
  22. generators.append(self._make_log_generator(container, color_fn))
  23. return generators
  24. def _make_log_generator(self, container, color_fn):
  25. prefix = color_fn(container.name + " | ")
  26. # Attach to container before log printer starts running
  27. line_generator = split_buffer(self._attach(container), '\n')
  28. for line in line_generator:
  29. yield prefix + line.decode('utf-8')
  30. exit_code = container.wait()
  31. yield color_fn("%s exited with code %s\n" % (container.name, exit_code))
  32. yield STOP
  33. def _attach(self, container):
  34. params = {
  35. 'stdout': True,
  36. 'stderr': True,
  37. 'stream': True,
  38. }
  39. params.update(self.attach_params)
  40. params = dict((name, 1 if value else 0) for (name, value) in list(params.items()))
  41. return container.attach(**params)