Skip to content

Commit

Permalink
Update logging to allow JSON output as well as contextual fields.
Browse files Browse the repository at this point in the history
This change allows Levant to configure in JSON format to allow a
more programatically friendly output. The log library has also
moved to zerolog as a preference over logrus and utilizes a global
context field of job_id once this is discovered.

Closes hashicorp#154
  • Loading branch information
jrasell committed May 1, 2018
1 parent 9263d4d commit e086104
Show file tree
Hide file tree
Showing 14 changed files with 196 additions and 142 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ Levant supports a number of command line arguments which provide control over th

* **-log-level** (string: "INFO") The level at which Levant will log to. Valid values are DEBUG, INFO, WARNING, ERROR and FATAL.

* **-log-format** (string: "HUMAN") Specify the format of Levant's logs. Valid values are HUMAN or JSON

* **-var-file** (string: "") The variables file to render the template with.

The `deploy` command also supports passing variables individually on the command line. Multiple commands can be passed in the format of `-var 'key=value'`. Variables passed via the command line take precedence over the same variable declared within a passed variable file.
Expand All @@ -88,6 +90,8 @@ levant deploy -log-level=debug -address=nomad.devoops -var-file=var.yaml -var 'v

* **-log-level** (string: "INFO") The level at which Levant will log to. Valid values are DEBUG, INFO, WARNING, ERROR and FATAL.

* **-log-format** (string: "HUMAN") Specify the format of Levant's logs. Valid values are HUMAN or JSON

* **-meta** (string: "key=vaule") The metadata key will be merged into the job's metadata. The job may define a default value for the key which is overridden when dispatching. The flag can be provided more than once to inject multiple metadata key/value pairs. Arbitrary keys are not allowed. The parameterized job must allow the key to be merged.

The command also supports the ability to send data payload to the dispatched instance. This can be provided via stdin by using "-" for the input source or by specifying a path to a file.
Expand Down
10 changes: 9 additions & 1 deletion command/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ General Options:
Specify the verbosity level of Levant's logs. Valid values include DEBUG,
INFO, and WARN, in decreasing order of verbosity. The default is INFO.
-log-format=<format>
Specify the format of Levant's logs. Valid values are HUMAN or JSON. The
default is HUMAN.
-var-file=<file>
Used in conjunction with the -job-file will deploy a templated job to your
Nomad cluster. [default: levant.(yaml|yml|tf)]
Expand All @@ -78,6 +82,7 @@ func (c *DeployCommand) Run(args []string) int {
flags.BoolVar(&config.ForceBatch, "force-batch", false, "")
flags.BoolVar(&config.ForceCount, "force-count", false, "")
flags.StringVar(&config.LogLevel, "log-level", "INFO", "")
flags.StringVar(&config.LogFormat, "log-format", "HUMAN", "")
flags.StringVar(&config.VaiableFile, "var-file", "", "")

if err = flags.Parse(args); err != nil {
Expand All @@ -86,7 +91,10 @@ func (c *DeployCommand) Run(args []string) int {

args = flags.Args()

logging.SetLevel(config.LogLevel)
if err = logging.SetupLogger(config.LogLevel, config.LogFormat); err != nil {
c.UI.Error(err.Error())
return 1
}

if len(args) == 1 {
config.TemplateFile = args[0]
Expand Down
12 changes: 10 additions & 2 deletions command/dispatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ General Options:
Specify the verbosity level of Levant's logs. Valid values include DEBUG,
INFO, and WARN, in decreasing order of verbosity. The default is INFO.
-log-format=<format>
Specify the format of Levant's logs. Valid values are HUMAN or JSON. The
default is HUMAN.
Dispatch Options:
-meta <key>=<value>
Expand All @@ -58,13 +62,14 @@ func (c *DispatchCommand) Synopsis() string {
func (c *DispatchCommand) Run(args []string) int {

var meta []string
var addr, logLevel string
var addr, logLevel, logFormat string

flags := c.Meta.FlagSet("dispatch", FlagSetVars)
flags.Usage = func() { c.UI.Output(c.Help()) }
flags.Var((*flaghelper.StringFlag)(&meta), "meta", "")
flags.StringVar(&addr, "address", "", "")
flags.StringVar(&logLevel, "log-level", "INFO", "")
flags.StringVar(&logFormat, "log-format", "human", "")

if err := flags.Parse(args); err != nil {
return 1
Expand All @@ -76,7 +81,10 @@ func (c *DispatchCommand) Run(args []string) int {
return 1
}

logging.SetLevel(logLevel)
err := logging.SetupLogger(logLevel, logFormat)
if err != nil {
c.UI.Error(fmt.Sprintf("Error setting up logging: %v", err))
}

job := args[0]
var payload []byte
Expand Down
12 changes: 6 additions & 6 deletions helper/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"os"
"path/filepath"

"github.com/jrasell/levant/logging"
"github.com/rs/zerolog/log"
)

// GetDefaultTmplFile checks the current working directory for *.nomad files.
Expand All @@ -13,7 +13,7 @@ func GetDefaultTmplFile() (templateFile string) {
if matches, _ := filepath.Glob("*.nomad"); matches != nil {
if len(matches) == 1 {
templateFile = matches[0]
logging.Debug("helper/files: using templatefile `%v`", templateFile)
log.Debug().Msgf("helper/files: using templatefile `%v`", templateFile)
return templateFile
}
}
Expand All @@ -24,17 +24,17 @@ func GetDefaultTmplFile() (templateFile string) {
// The first match is returned.
func GetDefaultVarFile() (varFile string) {
if _, err := os.Stat("levant.yaml"); !os.IsNotExist(err) {
logging.Debug("helper/files: using default var-file `levant.yaml`")
log.Debug().Msg("helper/files: using default var-file `levant.yaml`")
return "levant.yaml"
}
if _, err := os.Stat("levant.yml"); !os.IsNotExist(err) {
logging.Debug("helper/files: using default var-file `levant.yml`")
log.Debug().Msg("helper/files: using default var-file `levant.yml`")
return "levant.yml"
}
if _, err := os.Stat("levant.tf"); !os.IsNotExist(err) {
logging.Debug("helper/files: using default var-file `levant.tf`")
log.Debug().Msg("helper/files: using default var-file `levant.tf`")
return "levant.tf"
}
logging.Debug("helper/files: no default var-file found")
log.Debug().Msg("helper/files: no default var-file found")
return ""
}
10 changes: 6 additions & 4 deletions helper/variable.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package helper

import "github.com/jrasell/levant/logging"
import (
"github.com/rs/zerolog/log"
)

// VariableMerge merges the passed file variables with the flag variabes to
// provide a single set of variables. The flagVars will always prevale over file
Expand All @@ -10,17 +12,17 @@ func VariableMerge(fileVars *map[string]interface{}, flagVars *map[string]string
out := make(map[string]interface{})

for k, v := range *flagVars {
logging.Info("helper/variable: using command line variable with key %s and value %s", k, v)
log.Info().Msgf("helper/variable: using command line variable with key %s and value %s", k, v)
out[k] = v
}

for k, v := range *fileVars {
if _, ok := out[k]; ok {
logging.Debug("helper/variable: variable from file with key %s and value %s overridden by CLI var",
log.Debug().Msgf("helper/variable: variable from file with key %s and value %s overridden by CLI var",
k, v)
continue
}
logging.Info("helper/variable: using variable with key %s and value %v from file", k, v)
log.Info().Msgf("helper/variable: using variable with key %s and value %v from file", k, v)
out[k] = v
}

Expand Down
18 changes: 9 additions & 9 deletions levant/auto_revert.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"time"

nomad "github.com/hashicorp/nomad/api"
"github.com/jrasell/levant/logging"
"github.com/rs/zerolog/log"
)

func (l *levantDeployment) autoRevert(jobID, depID *string) {
Expand All @@ -16,26 +16,26 @@ func (l *levantDeployment) autoRevert(jobID, depID *string) {

dep, _, err := l.nomad.Jobs().LatestDeployment(*jobID, nil)
if err != nil {
logging.Error("levant/auto_revert: unable to query latest deployment of job %s", *jobID)
log.Error().Msgf("levant/auto_revert: unable to query latest deployment of job %s", *jobID)
return
}

// Check whether we have got the original deployment ID as a return from
// Nomad, and if so, continue the loop to try again.
if dep.ID == *depID {
logging.Debug("levant/auto_revert: auto-revert deployment not triggered for job %s, rechecking", *jobID)
log.Debug().Msgf("levant/auto_revert: auto-revert deployment not triggered for job %s, rechecking", *jobID)
time.Sleep(1 * time.Second)
continue
}

logging.Info("levant/auto_revert: beginning deployment watcher for job %s", *jobID)
log.Info().Msgf("levant/auto_revert: beginning deployment watcher for job %s", *jobID)
success := l.deploymentWatcher(dep.ID)

if success {
logging.Info("levant/auto_revert: auto-revert of job %s was successful", *jobID)
log.Info().Msgf("levant/auto_revert: auto-revert of job %s was successful", *jobID)
break
} else {
logging.Error("levant/auto_revert: auto-revert of job %s failed; POTENTIAL OUTAGE SITUATION", *jobID)
log.Error().Msgf("levant/auto_revert: auto-revert of job %s failed; POTENTIAL OUTAGE SITUATION", *jobID)
l.checkFailedDeployment(&dep.ID)
break
}
Expand All @@ -44,7 +44,7 @@ func (l *levantDeployment) autoRevert(jobID, depID *string) {
// At this point we have not been able to get the latest deploymentID that
// is different from the original so we can't perform auto-revert checking.
if i == 5 {
logging.Error("levant/auto_revert: unable to check auto-revert of job %s", *jobID)
log.Error().Msgf("levant/auto_revert: unable to check auto-revert of job %s", *jobID)
}
}

Expand All @@ -64,12 +64,12 @@ func (l *levantDeployment) checkAutoRevert(dep *nomad.Deployment) {
}

if revert {
logging.Info("levant/auto_revert: job %v has entered auto-revert state; launching auto-revert checker",
log.Info().Msgf("levant/auto_revert: job %v has entered auto-revert state; launching auto-revert checker",
dep.JobID)

// Run the levant autoRevert function.
l.autoRevert(&dep.JobID, &dep.ID)
} else {
logging.Info("levant/auto_revert: job %v is not in auto-revert; POTENTIAL OUTAGE SITUATION", dep.JobID)
log.Info().Msgf("levant/auto_revert: job %v is not in auto-revert; POTENTIAL OUTAGE SITUATION", dep.JobID)
}
}
Loading

0 comments on commit e086104

Please sign in to comment.