func Print(c int, a ...interface{}) (int, error) { if GetOS() == OS_LINUX { defer locker.Unlock() locker.Lock() fc := GetForegroundColor(OS_LINUX, c) return color.New(color.Attribute(fc)).Print(a...) } return fmt.Print(a...) }
// Dump container logs. func (containers Containers) Logs(follow bool, timestamps bool, tail string, colorize bool, since string) { var ( sources = make([]multiplexio.Source, 0, 2*len(containers)) maxPrefixLength = strconv.Itoa(containers.maxNameLength()) ) appendSources := func(reader io.Reader, color *ansi.Color, name string, separator string) { if reader != nil { prefix := fmt.Sprintf("%"+maxPrefixLength+"s "+separator+" ", name) sources = append(sources, multiplexio.Source{ Reader: reader, Write: write(prefix, color, timestamps), }) } } counter := 0 for _, container := range containers { var ( logs = container.Logs(follow, since, tail) stdoutColor *ansi.Color stderrColor *ansi.Color ) for _, log := range logs { if colorize { // red has a negative/error connotation, so skip it ansiAttribute := ansi.Attribute(int(ansi.FgGreen) + counter%int(ansi.FgWhite-ansi.FgGreen)) stdoutColor = ansi.New(ansiAttribute) // To synchronize their output, we need to multiplex stdout & stderr // onto the same stream. Unfortunately, that means that the user won't // be able to pipe them separately, so we use bold as a distinguishing // characteristic. stderrColor = ansi.New(ansiAttribute).Add(ansi.Bold) } appendSources(log.Stdout, stdoutColor, log.Name, "|") appendSources(log.Stderr, stderrColor, log.Name, "*") counter = counter + 1 } } if len(sources) > 0 { aggregatedReader := multiplexio.NewReader(multiplexio.Options{}, sources...) io.Copy(os.Stdout, aggregatedReader) } }
// attr takes a color integer and converts it to color.Attribute func attr(sgr int) color.Attribute { return color.Attribute(sgr) }