allow for viewing logs in both status and containers panel

This commit is contained in:
Jesse Duffield 2019-06-09 12:24:22 +10:00
parent da645cf173
commit d81c407dd2
8 changed files with 98 additions and 30 deletions

View file

@ -389,3 +389,14 @@ func (c *Container) EraseOldHistory() {
}
}
}
// ViewLogs attaches to a subprocess viewing the container's logs
func (c *Container) ViewLogs() (*exec.Cmd, error) {
templateString := c.OSCommand.Config.UserConfig.CommandTemplates.ViewContainerLogs
command := utils.ApplyTemplate(templateString, c)
cmd := c.OSCommand.ExecutableFromString(command)
c.OSCommand.PrepareForChildren(cmd)
return cmd, nil
}

View file

@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"os/exec"
"sort"
"strings"
"sync"
@ -392,3 +393,11 @@ func (c *DockerCommand) PruneContainers() error {
_, err := c.Client.ContainersPrune(context.Background(), filters.Args{})
return err
}
// ViewAllLogs attaches to a subprocess viewing all the logs from docker-compose
func (c *DockerCommand) ViewAllLogs() (*exec.Cmd, error) {
cmd := c.OSCommand.ExecutableFromString(c.OSCommand.Config.UserConfig.CommandTemplates.ViewAllLogs)
c.OSCommand.PrepareForChildren(cmd)
return cmd, nil
}

View file

@ -377,3 +377,10 @@ func (c *OSCommand) Kill(cmd *exec.Cmd) error {
return cmd.Process.Kill()
}
// PrepareForChildren sets Setpgid to true on the cmd, so that when we run it as a sideproject, we can kill its group rather than the process itself. This is because some commands, like `docker-compose logs` spawn multiple children processes, and killing the parent process isn't sufficient for killing those child processes. We set the group id here, and then in subprocess.go we check if the group id is set and if so, we kill the whole group rather than just the one process.
func (c *OSCommand) PrepareForChildren(cmd *exec.Cmd) {
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
}

View file

@ -2,7 +2,6 @@ package commands
import (
"os/exec"
"syscall"
"github.com/docker/docker/api/types"
"github.com/fatih/color"
@ -65,10 +64,7 @@ func (s *Service) ViewLogs() (*exec.Cmd, error) {
command := utils.ApplyTemplate(templateString, s)
cmd := s.OSCommand.ExecutableFromString(command)
// so long as this is commented in, the child process does not receive the interrupt
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
s.OSCommand.PrepareForChildren(cmd)
return cmd, nil
}

View file

@ -102,15 +102,19 @@ type GuiConfig struct {
}
type CommandTemplatesConfig struct {
RestartService string `yaml:"restartService,omitempty"`
DockerCompose string `yaml:"dockerCompose,omitempty"`
StopService string `yaml:"stopService,omitempty"`
ServiceLogs string `yaml:"serviceLogs,omitempty"`
ViewServiceLogs string `yaml:"viewServiceLogs,omitempty"`
RebuildService string `yaml:"rebuildService,omitempty"`
ContainerLogs string `yaml:"containerLogs,omitempty"`
ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"`
AllLogs string `yaml:"allLogs,omitempty"`
RestartService string `yaml:"restartService,omitempty"`
DockerCompose string `yaml:"dockerCompose,omitempty"`
StopService string `yaml:"stopService,omitempty"`
ServiceLogs string `yaml:"serviceLogs,omitempty"`
ViewServiceLogs string `yaml:"viewServiceLogs,omitempty"`
RebuildService string `yaml:"rebuildService,omitempty"`
// ViewContainerLogs is for viewing the container logs in a subprocess. We have this as a separate command in case you want to show all the logs rather than just tail them for the sake of reducing CPU load when in the lazydocker GUI
ViewContainerLogs string `yaml:"viewContainerLogs,omitempty"`
ContainerLogs string `yaml:"containerLogs,omitempty"`
ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"`
AllLogs string `yaml:"allLogs,omitempty"`
ViewAllLogs string `yaml:"viewAlLogs,omitempty"`
}
type OSConfig struct {
@ -158,14 +162,16 @@ func GetDefaultConfig() UserConfig {
Reporting: "undetermined",
ConfirmOnQuit: false,
CommandTemplates: CommandTemplatesConfig{
RestartService: "docker-compose restart {{ .Name }}",
RebuildService: "docker-compose up -d --build {{ .Name }}",
DockerCompose: "apdev compose",
StopService: "apdev stop {{ .Name }}",
ServiceLogs: "apdev logs {{ .Name }}",
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}",
AllLogs: "apdev logs --tail=100",
RestartService: "docker-compose restart {{ .Name }}",
RebuildService: "docker-compose up -d --build {{ .Name }}",
DockerCompose: "apdev compose",
StopService: "apdev stop {{ .Name }}",
ServiceLogs: "apdev logs {{ .Name }}",
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}",
AllLogs: "apdev logs --tail=100",
ViewAllLogs: "apdev logs",
},
OS: GetPlatformDefaultConfig(),
Update: UpdateConfig{

View file

@ -26,7 +26,7 @@ func (gui *Gui) getContainerContextTitles() []string {
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ConfigTitle}
}
func (gui *Gui) getSelectedContainer(g *gocui.Gui) (*commands.Container, error) {
func (gui *Gui) getSelectedContainer() (*commands.Container, error) {
selectedLine := gui.State.Panels.Containers.SelectedLine
if selectedLine == -1 {
return &commands.Container{}, gui.Errors.ErrNoContainers
@ -64,7 +64,7 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
return err
}
container, err := gui.getSelectedContainer(g)
container, err := gui.getSelectedContainer()
if err != nil {
if err != gui.Errors.ErrNoContainers {
return err
@ -379,7 +379,7 @@ func (r *removeContainerOption) GetDisplayStrings(isFocused bool) []string {
}
func (gui *Gui) handleContainersRemoveMenu(g *gocui.Gui, v *gocui.View) error {
container, err := gui.getSelectedContainer(g)
container, err := gui.getSelectedContainer()
if err != nil {
return nil
}
@ -430,7 +430,7 @@ func (gui *Gui) handleContainersRemoveMenu(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleContainerStop(g *gocui.Gui, v *gocui.View) error {
container, err := gui.getSelectedContainer(g)
container, err := gui.getSelectedContainer()
if err != nil {
return nil
}
@ -448,7 +448,7 @@ func (gui *Gui) handleContainerStop(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleContainerRestart(g *gocui.Gui, v *gocui.View) error {
container, err := gui.getSelectedContainer(g)
container, err := gui.getSelectedContainer()
if err != nil {
return nil
}
@ -463,7 +463,7 @@ func (gui *Gui) handleContainerRestart(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleContainerAttach(g *gocui.Gui, v *gocui.View) error {
container, err := gui.getSelectedContainer(g)
container, err := gui.getSelectedContainer()
if err != nil {
return nil
}
@ -488,3 +488,18 @@ func (gui *Gui) handlePruneContainers(g *gocui.Gui, v *gocui.View) error {
})
}, nil)
}
func (gui *Gui) handleContainerViewLogs(g *gocui.Gui, v *gocui.View) error {
container, err := gui.getSelectedContainer()
if err != nil {
return nil
}
c, err := container.ViewLogs()
if err != nil {
return gui.createErrorPanel(gui.g, err.Error())
}
gui.SubProcess = c
return gui.Errors.ErrSubProcess
}

View file

@ -147,6 +147,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleStatusNextContext,
Description: gui.Tr.NextContext,
},
{
ViewName: "status",
Key: 'm',
Modifier: gocui.ModNone,
Handler: gui.handleViewAllLogs,
Description: gui.Tr.ViewLogs,
},
{
ViewName: "menu",
Key: gocui.KeyEsc,
@ -214,6 +221,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handlePruneContainers,
Description: gui.Tr.PruneContainers,
},
{
ViewName: "containers",
Key: 'm',
Modifier: gocui.ModNone,
Handler: gui.handleContainerViewLogs,
Description: gui.Tr.ViewLogs,
},
{
ViewName: "services",
Key: 'd',

View file

@ -3,7 +3,6 @@ package gui
import (
"fmt"
"strings"
"syscall"
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui"
@ -101,7 +100,7 @@ func (gui *Gui) renderAllLogs() error {
cmd.Stdout = mainView
cmd.Stderr = mainView
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
gui.OSCommand.PrepareForChildren(cmd)
cmd.Start()
go func() {
@ -163,3 +162,14 @@ func (gui *Gui) handleStatusPrevContext(g *gocui.Gui, v *gocui.View) error {
return nil
}
// handleViewAllLogs switches to a subprocess viewing all the logs from docker-compose
func (gui *Gui) handleViewAllLogs(g *gocui.Gui, v *gocui.View) error {
c, err := gui.DockerCommand.ViewAllLogs()
if err != nil {
return gui.createErrorPanel(gui.g, err.Error())
}
gui.SubProcess = c
return gui.Errors.ErrSubProcess
}