From 7bf254c9afee7ec2433aa29a64e07b74c950201a Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Thu, 4 Feb 2016 23:54:15 -0800 Subject: [PATCH] Implemented log rotator for exec based drivers --- api/tasks.go | 7 ++++++ client/driver/exec.go | 1 + client/driver/executor/executor.go | 27 +++++++++++++-------- client/driver/java.go | 1 + client/driver/{ => logrotator}/logs.go | 2 +- client/driver/{ => logrotator}/logs_test.go | 2 +- client/driver/qemu.go | 1 + client/driver/raw_exec.go | 1 + 8 files changed, 30 insertions(+), 12 deletions(-) rename client/driver/{ => logrotator}/logs.go (99%) rename client/driver/{ => logrotator}/logs_test.go (99%) diff --git a/api/tasks.go b/api/tasks.go index 7fa476b72..04056da21 100644 --- a/api/tasks.go +++ b/api/tasks.go @@ -74,6 +74,12 @@ func (g *TaskGroup) AddTask(t *Task) *TaskGroup { return g } +// LogConfig provides configuration for log rotation +type LogConfig struct { + MaxFiles int `mapstructure:"max_files"` + MaxFileSizeMB int `mapstructure:"max_file_size"` +} + // Task is a single process in a task group. type Task struct { Name string @@ -85,6 +91,7 @@ type Task struct { Resources *Resources Meta map[string]string KillTimeout time.Duration + LogConfig *LogConfig } // NewTask creates and initializes a new Task. diff --git a/client/driver/exec.go b/client/driver/exec.go index 5cfb0fcac..a1ca8ded6 100644 --- a/client/driver/exec.go +++ b/client/driver/exec.go @@ -116,6 +116,7 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, + LogConfig: task.LogConfig, ResourceLimits: true, FSIsolation: true, UnprivilegedUser: true, diff --git a/client/driver/executor/executor.go b/client/driver/executor/executor.go index cdf153cb3..6684ca048 100644 --- a/client/driver/executor/executor.go +++ b/client/driver/executor/executor.go @@ -2,6 +2,7 @@ package executor import ( "fmt" + "io" "log" "os" "os/exec" @@ -15,6 +16,7 @@ import ( "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/driver/env" + "github.com/hashicorp/nomad/client/driver/logrotator" "github.com/hashicorp/nomad/nomad/structs" ) @@ -25,6 +27,7 @@ type ExecutorContext struct { AllocDir *allocdir.AllocDir TaskName string TaskResources *structs.Resources + LogConfig *structs.LogConfig FSIsolation bool ResourceLimits bool UnprivilegedUser bool @@ -94,19 +97,23 @@ func (e *UniversalExecutor) LaunchCmd(command *ExecCommand, ctx *ExecutorContext } } - stdoPath := filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf("%v.stdout", ctx.TaskName)) - stdo, err := os.OpenFile(stdoPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) - if err != nil { - return nil, err - } - e.cmd.Stdout = stdo + logFileSize := int64(ctx.LogConfig.MaxFileSizeMB * 1024 * 1024) - stdePath := filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf("%v.stderr", ctx.TaskName)) - stde, err := os.OpenFile(stdePath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) + stdor, stdow := io.Pipe() + lro, err := logrotator.NewLogRotator(filepath.Join(e.taskDir, allocdir.TaskLocal), fmt.Sprintf("%v.stdout", ctx.TaskName), ctx.LogConfig.MaxFiles, logFileSize, e.logger) if err != nil { - return nil, err + return nil, fmt.Errorf("error creating log rotator for stdout of task %v", err) } - e.cmd.Stderr = stde + e.cmd.Stdout = stdow + go lro.Start(stdor) + + stder, stdew := io.Pipe() + lre, err := logrotator.NewLogRotator(filepath.Join(e.taskDir, allocdir.TaskLocal), fmt.Sprintf("%v.stderr", ctx.TaskName), ctx.LogConfig.MaxFiles, logFileSize, e.logger) + if err != nil { + return nil, fmt.Errorf("error creating log rotator for stderr of task %v", err) + } + e.cmd.Stderr = stdew + go lre.Start(stder) e.cmd.Env = ctx.TaskEnv.EnvList() diff --git a/client/driver/java.go b/client/driver/java.go index 494916324..3b807de0f 100644 --- a/client/driver/java.go +++ b/client/driver/java.go @@ -162,6 +162,7 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, + LogConfig: task.LogConfig, } ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: "java", Args: args}, executorCtx) if err != nil { diff --git a/client/driver/logs.go b/client/driver/logrotator/logs.go similarity index 99% rename from client/driver/logs.go rename to client/driver/logrotator/logs.go index 7297382cd..0442c8519 100644 --- a/client/driver/logs.go +++ b/client/driver/logrotator/logs.go @@ -1,4 +1,4 @@ -package driver +package logrotator import ( "fmt" diff --git a/client/driver/logs_test.go b/client/driver/logrotator/logs_test.go similarity index 99% rename from client/driver/logs_test.go rename to client/driver/logrotator/logs_test.go index d45ae5fdd..12128fb96 100644 --- a/client/driver/logs_test.go +++ b/client/driver/logrotator/logs_test.go @@ -1,4 +1,4 @@ -package driver +package logrotator import ( "io" diff --git a/client/driver/qemu.go b/client/driver/qemu.go index f1bed809a..06709d71a 100644 --- a/client/driver/qemu.go +++ b/client/driver/qemu.go @@ -206,6 +206,7 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, + LogConfig: task.LogConfig, } ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: args[0], Args: args[1:]}, executorCtx) if err != nil { diff --git a/client/driver/raw_exec.go b/client/driver/raw_exec.go index 784e7292e..c67623367 100644 --- a/client/driver/raw_exec.go +++ b/client/driver/raw_exec.go @@ -112,6 +112,7 @@ func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandl AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, + LogConfig: task.LogConfig, } ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: command, Args: driverConfig.Args}, executorCtx) if err != nil {