Skip to content

Commit 75da750

Browse files
committed
add timestamp function for stdout logging
1 parent 61096a6 commit 75da750

File tree

5 files changed

+68
-2
lines changed

5 files changed

+68
-2
lines changed

examples/bootjob.d/job.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
sleep 10
4+
exit 0

examples/bootjob.d/job2.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
3+
sleep 5
4+
exit 0

examples/bootjob.d/one_shot.hcl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
boot "oneshotzero" {
2+
command = "/bin/bash"
3+
args = [
4+
"examples/bootjob.d/job2.sh"
5+
]
6+
}
7+
8+
boot "oneshot" {
9+
command = "/bin/bash"
10+
args = [
11+
"examples/bootjob.d/job.sh"
12+
]
13+
}
14+
15+
job "memes" {
16+
command = "/bin/bash"
17+
args = [
18+
"-c",
19+
"while true ; do echo 'memes'; sleep 10; done"
20+
]
21+
22+
stdout = "memes.log"
23+
stdout = "memes_error.log"
24+
enableTimestamps = true
25+
}

internal/config/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ type BaseJobConfig struct {
9696
WorkingDirectory string `hcl:"workingDirectory" json:"workingDirectory,omitempty"`
9797
Stdout string `hcl:"stdout" json:"stdout,omitempty"`
9898
Stderr string `hcl:"stderr" json:"stderr,omitempty"`
99+
EnableTimestamps bool `hcl:"enableTimestamps" json:"enableTimestamps"`
99100
}
100101

101102
type Laziness struct {

pkg/proc/basejob.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,26 @@ func (job *baseJob) startOnce(ctx context.Context, process chan<- *os.Process) e
114114
cmd := exec.Command(job.Config.Command, job.Config.Args...)
115115
cmd.Env = os.Environ()
116116
cmd.Dir = job.Config.WorkingDirectory
117-
cmd.Stdout = job.stdout
118-
cmd.Stderr = job.stderr
117+
118+
// pipe stdout and stderr through timestamp function if they are enabled
119+
if job.Config.EnableTimestamps {
120+
stdoutPipe, err := cmd.StdoutPipe()
121+
if err != nil {
122+
return fmt.Errorf("failed to create stdout pipe for process: %s", err.Error())
123+
}
124+
125+
stderrPipe, _ := cmd.StderrPipe()
126+
if err != nil {
127+
return fmt.Errorf("failed to create stderr pipe for process: %s", err.Error())
128+
}
129+
130+
go job.logWithTimestamp(stdoutPipe, job.stdout)
131+
go job.logWithTimestamp(stderrPipe, job.stderr)
132+
} else {
133+
cmd.Stdout = job.stdout
134+
cmd.Stderr = job.stderr
135+
}
136+
119137
cmd.SysProcAttr = &syscall.SysProcAttr{
120138
Setpgid: true,
121139
}
@@ -201,6 +219,20 @@ func (job *baseJob) closeStdFiles() {
201219
}
202220
}
203221

222+
func (job *baseJob) logWithTimestamp(r io.Reader, w io.Writer) {
223+
l := log.WithField("job.name", job.Config.Name)
224+
225+
scanner := bufio.NewScanner(r)
226+
for scanner.Scan() {
227+
timestamp := time.Now().Format(time.RFC3339)
228+
line := fmt.Sprintf("[%s] %s\n", timestamp, scanner.Text())
229+
w.Write([]byte(line))
230+
}
231+
if err := scanner.Err(); err != nil {
232+
l.Info(os.Stderr, "error reading from process: %v\n", err)
233+
}
234+
}
235+
204236
func (job *baseJob) readStdFile(ctx context.Context, wg *sync.WaitGroup, filePath string, outChan chan []byte, errChan chan error, follow bool, tailLen int) {
205237
stdFile, err := os.OpenFile(filePath, os.O_RDONLY, 0o666)
206238
if err != nil {

0 commit comments

Comments
 (0)