Merge pull request #1301 from docker/color_fix

fix color assignment on status messages
This commit is contained in:
Nicolas De loof 2021-02-16 10:43:16 +01:00 committed by GitHub
commit 8029db807c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 34 deletions

View File

@ -194,9 +194,9 @@ type Stack struct {
// LogConsumer is a callback to process log messages from services // LogConsumer is a callback to process log messages from services
type LogConsumer interface { type LogConsumer interface {
Log(service, container, message string) Log(name, container, message string)
Status(service, container, msg string) Status(name, container, msg string)
Register(service string, source string) Register(name string, source string)
} }
// ContainerEventListener is a callback to process ContainerEvent from services // ContainerEventListener is a callback to process ContainerEvent from services
@ -207,6 +207,7 @@ type ContainerEvent struct {
Type int Type int
Source string Source string
Service string Service string
Name string
Line string Line string
ExitCode int ExitCode int
} }

View File

@ -320,11 +320,11 @@ func (p printer) run(ctx context.Context, cascadeStop bool, exitCodeFrom string,
event := <-p.queue event := <-p.queue
switch event.Type { switch event.Type {
case compose.ContainerEventAttach: case compose.ContainerEventAttach:
consumer.Register(event.Service, event.Source) consumer.Register(event.Name, event.Source)
count++ count++
case compose.ContainerEventExit: case compose.ContainerEventExit:
if !aborting { if !aborting {
consumer.Status(event.Service, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode)) consumer.Status(event.Name, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode))
} }
if cascadeStop { if cascadeStop {
if !aborting { if !aborting {
@ -347,7 +347,7 @@ func (p printer) run(ctx context.Context, cascadeStop bool, exitCodeFrom string,
} }
case compose.ContainerEventLog: case compose.ContainerEventLog:
if !aborting { if !aborting {
consumer.Log(event.Service, event.Source, event.Line) consumer.Log(event.Name, event.Source, event.Line)
} }
} }
} }

View File

@ -38,21 +38,20 @@ func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) c
} }
} }
func (l *logConsumer) Register(service string, source string) { func (l *logConsumer) Register(name string, id string) {
l.register(service, source) l.register(name, id)
} }
func (l *logConsumer) register(service string, source string) *presenter { func (l *logConsumer) register(name string, id string) *presenter {
cf := monochrome cf := monochrome
if l.color { if l.color {
cf = <-loop cf = <-loop
} }
p := &presenter{ p := &presenter{
colors: cf, colors: cf,
service: service, name: name,
container: source,
} }
l.presenters[source] = p l.presenters[id] = p
if l.prefix { if l.prefix {
l.computeWidth() l.computeWidth()
for _, p := range l.presenters { for _, p := range l.presenters {
@ -62,34 +61,34 @@ func (l *logConsumer) register(service string, source string) *presenter {
return p return p
} }
// Log formats a log message as received from service/container // Log formats a log message as received from name/container
func (l *logConsumer) Log(service, container, message string) { func (l *logConsumer) Log(name, id, message string) {
if l.ctx.Err() != nil { if l.ctx.Err() != nil {
return return
} }
p, ok := l.presenters[container] p, ok := l.presenters[id]
if !ok { // should have been registered, but ¯\_(ツ)_/¯ if !ok { // should have been registered, but ¯\_(ツ)_/¯
p = l.register(service, container) p = l.register(name, id)
} }
for _, line := range strings.Split(message, "\n") { for _, line := range strings.Split(message, "\n") {
fmt.Fprintf(l.writer, "%s %s\n", p.prefix, line) // nolint:errcheck fmt.Fprintf(l.writer, "%s %s\n", p.prefix, line) // nolint:errcheck
} }
} }
func (l *logConsumer) Status(service, container, msg string) { func (l *logConsumer) Status(name, id, msg string) {
p, ok := l.presenters[container] p, ok := l.presenters[id]
if !ok { if !ok {
p = l.register(service, container) p = l.register(name, id)
} }
s := p.colors(fmt.Sprintf("%s %s\n", container, msg)) s := p.colors(fmt.Sprintf("%s %s\n", name, msg))
l.writer.Write([]byte(s)) // nolint:errcheck l.writer.Write([]byte(s)) // nolint:errcheck
} }
func (l *logConsumer) computeWidth() { func (l *logConsumer) computeWidth() {
width := 0 width := 0
for n := range l.presenters { for _, p := range l.presenters {
if len(n) > width { if len(p.name) > width {
width = len(n) width = len(p.name)
} }
} }
l.width = width + 1 l.width = width + 1
@ -106,12 +105,11 @@ type logConsumer struct {
} }
type presenter struct { type presenter struct {
colors colorFunc colors colorFunc
service string name string
container string prefix string
prefix string
} }
func (p *presenter) setPrefix(width int) { func (p *presenter) setPrefix(width int) {
p.prefix = p.colors(fmt.Sprintf("%-"+strconv.Itoa(width)+"s |", p.container)) p.prefix = p.colors(fmt.Sprintf("%-"+strconv.Itoa(width)+"s |", p.name))
} }

View File

@ -48,7 +48,8 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, con
for _, container := range containers { for _, container := range containers {
consumer(compose.ContainerEvent{ consumer(compose.ContainerEvent{
Type: compose.ContainerEventAttach, Type: compose.ContainerEventAttach,
Source: getContainerNameWithoutProject(container), Source: container.ID,
Name: getContainerNameWithoutProject(container),
Service: container.Labels[serviceLabel], Service: container.Labels[serviceLabel],
}) })
err := s.attachContainer(ctx, container, consumer, project) err := s.attachContainer(ctx, container, consumer, project)
@ -61,7 +62,7 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, con
func (s *composeService) attachContainer(ctx context.Context, container moby.Container, consumer compose.ContainerEventListener, project *types.Project) error { func (s *composeService) attachContainer(ctx context.Context, container moby.Container, consumer compose.ContainerEventListener, project *types.Project) error {
serviceName := container.Labels[serviceLabel] serviceName := container.Labels[serviceLabel]
w := getWriter(serviceName, getContainerNameWithoutProject(container), consumer) w := getWriter(getContainerNameWithoutProject(container), serviceName, container.ID, consumer)
service, err := project.GetService(serviceName) service, err := project.GetService(serviceName)
if err != nil { if err != nil {

View File

@ -88,14 +88,16 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer
} }
type splitBuffer struct { type splitBuffer struct {
service string name string
container string container string
consumer compose.ContainerEventListener consumer compose.ContainerEventListener
service string
} }
// getWriter creates a io.Writer that will actually split by line and format by LogConsumer // getWriter creates a io.Writer that will actually split by line and format by LogConsumer
func getWriter(service, container string, events compose.ContainerEventListener) io.Writer { func getWriter(name, service, container string, events compose.ContainerEventListener) io.Writer {
return splitBuffer{ return splitBuffer{
name: name,
service: service, service: service,
container: container, container: container,
consumer: events, consumer: events,
@ -108,6 +110,7 @@ func (s splitBuffer) Write(b []byte) (n int, err error) {
if len(line) != 0 { if len(line) != 0 {
s.consumer(compose.ContainerEvent{ s.consumer(compose.ContainerEvent{
Type: compose.ContainerEventLog, Type: compose.ContainerEventLog,
Name: s.name,
Service: s.service, Service: s.service,
Source: s.container, Source: s.container,
Line: string(line), Line: string(line),

View File

@ -55,7 +55,8 @@ func (s *composeService) Start(ctx context.Context, project *types.Project, opti
case status := <-statusC: case status := <-statusC:
options.Attach(compose.ContainerEvent{ options.Attach(compose.ContainerEvent{
Type: compose.ContainerEventExit, Type: compose.ContainerEventExit,
Source: getCanonicalContainerName(c), Source: c.ID,
Name: getCanonicalContainerName(c),
Service: c.Labels[serviceLabel], Service: c.Labels[serviceLabel],
ExitCode: int(status.StatusCode), ExitCode: int(status.StatusCode),
}) })