summaryrefslogtreecommitdiff
path: root/internal/io
diff options
context:
space:
mode:
authorPaul Buetow <35781042+pbuetow@users.noreply.github.com>2020-12-27 19:46:24 +0000
committerGitHub <noreply@github.com>2020-12-27 19:46:24 +0000
commit495e9f38220a6d448b15882a235e7a9c21f21d18 (patch)
tree5b59cade83108c1855d07f1f869a0dcb3b9f0907 /internal/io
parentb4db37d8cbae8f0c3dec289b2e1b0cfe83731415 (diff)
parent2c7bdd09e8b7c58d98d631e32a24e4bd34d5bec9 (diff)
Merge pull request #16 from snonux/develop
Multiple minor enhancements.
Diffstat (limited to 'internal/io')
-rw-r--r--internal/io/fs/permissions/permission_linux.go2
-rw-r--r--internal/io/line/line.go6
-rw-r--r--internal/io/logger/logger.go24
-rw-r--r--internal/io/logger/modes.go1
-rw-r--r--internal/io/prompt/prompt.go6
-rw-r--r--internal/io/run/run.go150
6 files changed, 25 insertions, 164 deletions
diff --git a/internal/io/fs/permissions/permission_linux.go b/internal/io/fs/permissions/permission_linux.go
index feae729..bbc039b 100644
--- a/internal/io/fs/permissions/permission_linux.go
+++ b/internal/io/fs/permissions/permission_linux.go
@@ -11,7 +11,7 @@ import (
"unsafe"
)
-// To check whether user has Linux file system permissions to read a given file.
+// ToRead checks whether user has Linux file system permissions to read a given file.
func ToRead(user, filePath string) (bool, error) {
cUser := C.CString(user)
cFilePath := C.CString(filePath)
diff --git a/internal/io/line/line.go b/internal/io/line/line.go
index 9db93c0..715be34 100644
--- a/internal/io/line/line.go
+++ b/internal/io/line/line.go
@@ -15,7 +15,11 @@ type Line struct {
// lines if that happens but it will signal to the client how
// many log lines in % could be transmitted to the client.
TransmittedPerc int
- SourceID string
+ // Contains the unique identifier of the source log file.
+ // It could be the name of the log or it could be one of the parent
+ // directories in case multiple log files with the same basename are
+ // followed.
+ SourceID string
}
// Return a human readable representation of the followed line.
diff --git a/internal/io/logger/logger.go b/internal/io/logger/logger.go
index b7db0a7..4254eef 100644
--- a/internal/io/logger/logger.go
+++ b/internal/io/logger/logger.go
@@ -72,12 +72,15 @@ type buf struct {
func Start(ctx context.Context, mode Modes) {
Mode = mode
- if Mode.Nothing {
+ switch {
+ case Mode.Nothing:
return
- }
-
- if Mode.Trace {
+ case Mode.Quiet:
+ Mode.Trace = false
+ Mode.Debug = false
+ case Mode.Trace:
Mode.Debug = true
+ default:
}
strategy := logStrategy()
@@ -87,7 +90,7 @@ func Start(ctx context.Context, mode Modes) {
case DailyStrategy:
_, err := os.Stat(config.Common.LogDir)
Mode.logToFile = !os.IsNotExist(err)
- Mode.logToStdout = !Mode.Server || Mode.Debug || Mode.Trace
+ Mode.logToStdout = !Mode.Server || Mode.Debug || Mode.Trace || Mode.Quiet
case StdoutStrategy:
fallthrough
default:
@@ -131,11 +134,14 @@ func Info(args ...interface{}) string {
// Warn message logging.
func Warn(args ...interface{}) string {
- if Mode.Server {
- return log(serverStr, warnStr, args)
+ if !Mode.Quiet {
+ if Mode.Server {
+ return log(serverStr, warnStr, args)
+ }
+ return log(clientStr, warnStr, args)
}
- return log(clientStr, warnStr, args)
+ return ""
}
// Error message logging.
@@ -242,7 +248,7 @@ func log(what string, severity string, args []interface{}) string {
message := strings.Join(messages, "|")
write(what, severity, message)
- return message
+ return fmt.Sprintf("%s|%s", severity, message)
}
// Raw message logging.
diff --git a/internal/io/logger/modes.go b/internal/io/logger/modes.go
index 47dadfe..8864179 100644
--- a/internal/io/logger/modes.go
+++ b/internal/io/logger/modes.go
@@ -6,6 +6,7 @@ type Modes struct {
Trace bool
Debug bool
Nothing bool
+ Quiet bool
logToStdout bool
logToFile bool
}
diff --git a/internal/io/prompt/prompt.go b/internal/io/prompt/prompt.go
index a438d33..36ebdb5 100644
--- a/internal/io/prompt/prompt.go
+++ b/internal/io/prompt/prompt.go
@@ -3,9 +3,10 @@ package prompt
import (
"bufio"
"fmt"
- "github.com/mimecast/dtail/internal/io/logger"
"os"
"strings"
+
+ "github.com/mimecast/dtail/internal/io/logger"
)
// Answer is a user input of a prompt question.
@@ -18,8 +19,7 @@ type Answer struct {
Callback func()
// Runs after Callback and after logging resumes
EndCallback func()
-
- AskAgain bool
+ AskAgain bool
}
// Prompt used for interactive user input.
diff --git a/internal/io/run/run.go b/internal/io/run/run.go
deleted file mode 100644
index 2bb3756..0000000
--- a/internal/io/run/run.go
+++ /dev/null
@@ -1,150 +0,0 @@
-package run
-
-import (
- "bufio"
- "context"
- "io"
- "os/exec"
- "sync"
- "syscall"
- "time"
-
- "github.com/mimecast/dtail/internal/io/line"
- "github.com/mimecast/dtail/internal/io/logger"
-)
-
-// Run is for execute a command.
-type Run struct {
- command string
- args []string
- cmd *exec.Cmd
- pgroupKilled chan struct{}
-}
-
-// New returns a new command runner.
-func New(command string, args []string) Run {
- return Run{
- command: command,
- args: args,
- pgroupKilled: make(chan struct{}),
- }
-}
-
-// StartBackground starts running the command in background.
-func (r Run) StartBackground(ctx context.Context, wg *sync.WaitGroup, ec chan<- int, lines chan<- line.Line) (pid int, err error) {
- pid = -1
-
- if len(r.args) > 0 {
- logger.Debug(r.command, r.args, " ")
- r.cmd = exec.CommandContext(ctx, r.command, r.args...)
- } else {
- logger.Debug(r.command)
- r.cmd = exec.CommandContext(ctx, r.command)
- }
-
- // Create a new process group, so that kill() will only kill this command + pgroup.
- r.cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
-
- stdoutPipe, myErr := r.cmd.StdoutPipe()
- if err != nil {
- wg.Done()
- err = myErr
- return
- }
-
- stderrPipe, myErr := r.cmd.StderrPipe()
- if myErr != nil {
- wg.Done()
- err = myErr
- return
- }
-
- if myErr := r.cmd.Start(); err != nil {
- wg.Done()
- err = myErr
- return
- }
-
- if r.cmd.Process != nil {
- pid = r.cmd.Process.Pid
- }
-
- commandExited := make(chan struct{})
-
- var pipeWg sync.WaitGroup
- pipeWg.Add(2)
-
- go r.killPgroup(ctx, commandExited, pid)
- go r.pipeToLines(commandExited, &pipeWg, pid, stdoutPipe, "STDOUT", lines)
- go r.pipeToLines(commandExited, &pipeWg, pid, stderrPipe, "STDERR", lines)
-
- go func() {
- exitCode := 255
- if waitErr := r.cmd.Wait(); waitErr != nil {
- if exitError, ok := waitErr.(*exec.ExitError); ok {
- exitCode = exitError.ExitCode()
- }
- }
- ec <- exitCode
-
- // Tell pipes we are done
- close(commandExited)
- // Wait for process group to be killed
- <-r.pgroupKilled
- // Wait for the pipes to flush the contents
- pipeWg.Wait()
- // Now the job is truly done
- wg.Done()
- }()
-
- return
-}
-
-func (r Run) pipeToLines(commandExited chan struct{}, wg *sync.WaitGroup, pid int, reader io.Reader, what string, lines chan<- line.Line) {
- defer wg.Done()
- bufReader := bufio.NewReader(reader)
-
- for {
- time.Sleep(time.Millisecond * 10)
- lineStr, err := bufReader.ReadString('\n')
-
- if err != nil {
- select {
- case <-commandExited:
- return
- default:
- }
- continue
- }
-
- newLine := line.Line{
- Content: []byte(lineStr),
- Count: uint64(pid),
- TransmittedPerc: 100,
- SourceID: what,
- }
-
- select {
- case lines <- newLine:
- case <-commandExited:
- return
- }
- }
-}
-
-func (r Run) killPgroup(ctx context.Context, commandExited chan struct{}, pid int) {
- if pid == -1 {
- close(r.pgroupKilled)
- return
- }
-
- if pgid, err := syscall.Getpgid(pid); err == nil {
- // Kill process group when done
- select {
- case <-ctx.Done():
- case <-commandExited:
- }
- syscall.Kill(-pgid, syscall.SIGKILL)
- close(r.pgroupKilled)
- }
-}