log_printer.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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
  6. from . import colors
  7. class LogPrinter(object):
  8. def __init__(self, containers, attach_params=None):
  9. self.containers = containers
  10. self.attach_params = attach_params or {}
  11. self.generators = self._make_log_generators()
  12. def run(self):
  13. mux = Multiplexer(self.generators)
  14. for line in mux.loop():
  15. sys.stdout.write(line)
  16. def _make_log_generators(self):
  17. color_fns = cycle(colors.rainbow())
  18. generators = []
  19. for container in self.containers:
  20. color_fn = color_fns.next()
  21. generators.append(self._make_log_generator(container, color_fn))
  22. return generators
  23. def _make_log_generator(self, container, color_fn):
  24. prefix = color_fn(container.name + " | ")
  25. websocket = self._attach(container)
  26. return (prefix + line for line in split_buffer(read_websocket(websocket), '\n'))
  27. def _attach(self, container):
  28. params = {
  29. 'stdin': False,
  30. 'stdout': True,
  31. 'stderr': True,
  32. 'logs': False,
  33. 'stream': True,
  34. }
  35. params.update(self.attach_params)
  36. params = dict((name, 1 if value else 0) for (name, value) in list(params.items()))
  37. return container.attach_socket(params=params, ws=True)
  38. def read_websocket(websocket):
  39. while True:
  40. data = websocket.recv()
  41. if data:
  42. yield data
  43. else:
  44. break
  45. def split_buffer(reader, separator):
  46. """
  47. Given a generator which yields strings and a separator string,
  48. joins all input, splits on the separator and yields each chunk.
  49. Requires that each input string is decodable as UTF-8.
  50. """
  51. buffered = ''
  52. for data in reader:
  53. lines = (buffered + data.decode('utf-8')).split(separator)
  54. for line in lines[:-1]:
  55. yield line + separator
  56. if len(lines) > 1:
  57. buffered = lines[-1]
  58. if len(buffered) > 0:
  59. yield buffered