Skip to content
This repository has been archived by the owner on Feb 5, 2018. It is now read-only.

Commit

Permalink
Merge pull request #52 from alexef/flags
Browse files Browse the repository at this point in the history
Add -g flag for grouping metrics together
  • Loading branch information
ranjib authored Jan 13, 2017
2 parents 1573936 + edcca49 commit 60ee6e7
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
11 changes: 6 additions & 5 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ type binArgs struct {
Cmd string // this is not a command line flag, but rather parsed results
CmdArgs []string // this is not a command line flag, also parsed results
LockDir string `short:"d" long:"lock-dir" default:"/var/lock" description:"the directory where lock files will be placed"`
AllEvents bool `short:"e" long:"event" default:"false" description:"emit a start and end datadog event"`
FailEvent bool `short:"E" long:"event-fail" default:"false" description:"only emit an event on failure"`
LogFail bool `short:"F" long:"log-fail" default:"false" description:"when a command fails, log its full output (stdout/stderr) to the log directory using the UUID as the filename"`
AllEvents bool `short:"e" long:"event" description:"emit a start and end datadog event"`
FailEvent bool `short:"E" long:"event-fail" description:"only emit an event on failure"`
LogFail bool `short:"F" long:"log-fail" description:"when a command fails, log its full output (stdout/stderr) to the log directory using the UUID as the filename"`
EventGroup string `short:"G" long:"event-group" value-name:"<group>" description:"emit a cronner_group:<group> tag with Datadog events, does not get sent with statsd metrics"`
Lock bool `short:"k" long:"lock" default:"false" description:"lock based on label so that multiple commands with the same label can not run concurrently"`
Group string `short:"g" long:"group" value-name:"<group>" description:"emit a cronner_group:<group> tag with statsd metrics"`
Lock bool `short:"k" long:"lock" description:"lock based on label so that multiple commands with the same label can not run concurrently"`
Label string `short:"l" long:"label" description:"name for cron job to be used in statsd emissions and DogStatsd events. alphanumeric only; cronner will lowercase it"`
LogPath string `long:"log-path" default:"/var/log/cronner" description:"where to place the log files for command output (path for -F/--log-fail output)"`
LogLevel string `short:"L" long:"log-level" default:"error" description:"set the level at which to log at [none|error|info|debug]"`
Namespace string `short:"N" long:"namespace" default:"cronner" description:"namespace for statsd emissions, value is prepended to metric name by statsd client"`
Sensitive bool `short:"s" long:"sensitive" default:"false" description:"specify whether command output may contain sensitive details, this only avoids it being printed to stderr"`
Sensitive bool `short:"s" long:"sensitive" description:"specify whether command output may contain sensitive details, this only avoids it being printed to stderr"`
Version bool `short:"V" long:"version" description:"print the version string and exit"`
WarnAfter uint64 `short:"w" long:"warn-after" default:"0" value-name:"N" description:"emit a warning event every N seconds if the job hasn't finished, set to 0 to disable"`
WaitSeconds uint64 `short:"W" long:"wait-secs" default:"0" description:"how long to wait for the file lock for"`
Expand Down
7 changes: 7 additions & 0 deletions args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
c.Check(args.FailEvent, Equals, false)
c.Check(args.LogFail, Equals, false)
c.Check(args.EventGroup, Equals, "")
c.Check(args.Group, Equals, "")
c.Check(args.Lock, Equals, false)
c.Check(args.LogPath, Equals, "/var/log/cronner")
c.Check(args.LogLevel, Equals, "error")
Expand All @@ -120,6 +121,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
"-E",
"-F",
"-G", "test_group",
"-g", "metric_group",
"-k",
"-l", "test",
"-L", "info",
Expand All @@ -143,6 +145,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
c.Check(args.FailEvent, Equals, true)
c.Check(args.LogFail, Equals, true)
c.Check(args.EventGroup, Equals, "test_group")
c.Check(args.Group, Equals, "metric_group")
c.Check(args.Lock, Equals, true)
c.Check(args.Label, Equals, "test")
c.Check(args.LogLevel, Equals, "info")
Expand All @@ -165,6 +168,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
"--event-fail",
"--log-fail",
"--event-group", "test_group",
"--group", "metric_group",
"--lock",
"--label", "test",
"--log-path", "/var/log/testcronner",
Expand All @@ -186,6 +190,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
c.Check(args.FailEvent, Equals, true)
c.Check(args.LogFail, Equals, true)
c.Check(args.EventGroup, Equals, "test_group")
c.Check(args.Group, Equals, "metric_group")
c.Check(args.Lock, Equals, true)
c.Check(args.Label, Equals, "test")
c.Check(args.LogPath, Equals, "/var/log/testcronner")
Expand All @@ -206,6 +211,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
Arg0,
"--lock-dir=/var/testlock",
"--event-group=test_group",
"--group=metric_group",
"--label=test",
"--log-path=/var/log/testcronner",
"--log-level=info",
Expand All @@ -222,6 +228,7 @@ func (t *TestSuite) Test_binArgs_parse(c *C) {
c.Check(len(output), Equals, 0)
c.Check(args.LockDir, Equals, "/var/testlock")
c.Check(args.EventGroup, Equals, "test_group")
c.Check(args.Group, Equals, "metric_group")
c.Check(args.Label, Equals, "test")
c.Check(args.LogPath, Equals, "/var/log/testcronner")
c.Check(args.LogLevel, Equals, "info")
Expand Down
12 changes: 9 additions & 3 deletions runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,14 @@ func handleCommand(hndlr *cmdHandler) (int, []byte, float64, error) {
}

// emit the metric for how long it took us and return code
hndlr.gs.Timing(fmt.Sprintf("%v.time", hndlr.opts.Label), wallRtMs, nil)
hndlr.gs.Gauge(fmt.Sprintf("%v.exit_code", hndlr.opts.Label), float64(ret), nil)
tags := []string{}

if len(hndlr.opts.Group) > 0 {
tags = append(tags, fmt.Sprintf("cronner_group:%s", hndlr.opts.Group))
}

hndlr.gs.Timing(fmt.Sprintf("%v.time", hndlr.opts.Label), wallRtMs, tags)
hndlr.gs.Gauge(fmt.Sprintf("%v.exit_code", hndlr.opts.Label), float64(ret), tags)

out := b.Bytes()

Expand Down Expand Up @@ -278,7 +284,7 @@ func emitEvent(title, body, label, alertType string, hndlr *cmdHandler) {
tags := []string{"source_type:cronner", fmt.Sprintf("cronner_label_name:%v", label)}

if len(hndlr.opts.EventGroup) > 0 {
tags = append(tags, fmt.Sprintf("cronner_group:%v", hndlr.opts.EventGroup))
tags = append(tags, fmt.Sprintf("cronner_group:%s", hndlr.opts.EventGroup))
}

hndlr.gs.Event(title, body, fields, tags)
Expand Down
47 changes: 47 additions & 0 deletions runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,52 @@ func (t *TestSuite) Test_handleCommand(c *C) {
fmt.Sprintf(`_e{55,77}:Cron testCmd succeeded in %.5f seconds on brainbox01|UUID: %v\nexit code: 0\noutput: somevalue\n|k:%v|s:cronner|t:success|#source_type:cronner,cronner_label_name:testCmd,cronner_group:testgroup`, runTime/1000, t.h.uuid, t.h.uuid),
)

//
// Test that DD metrics contain the cronner_group tag
//

// Reset variables used
r = nil
err = nil
runTime = 0
match = nil

t.h.cmd = exec.Command("/bin/echo", "somevalue")
t.h.opts.Group = "metricgroup"
t.h.opts.EventGroup = ""

_, r, runTime, err = handleCommand(t.h)
c.Assert(err, IsNil)

stat, ok = <-t.out
c.Assert(ok, Equals, true)
c.Check(
string(stat),
Equals,
fmt.Sprintf(`_e{35,44}:Cron testCmd starting on brainbox01|UUID: %v\n|k:%v|s:cronner|t:info|#source_type:cronner,cronner_label_name:testCmd`, t.h.uuid, t.h.uuid),
)

stat, ok = <-t.out
c.Assert(ok, Equals, true)
timeStatTagRegex := regexp.MustCompile("^cronner.testCmd.time:([0-9\\.]+)\\|ms\\|#cronner_group:([a-z]+)$")
match = timeStatTagRegex.FindAllStringSubmatch(string(stat), -1)
c.Assert(len(match), Equals, 1)
c.Assert(len(match[0]), Equals, 3)
c.Check(strconv.FormatFloat(runTime, 'f', -1, 64), Equals, match[0][1])
c.Check("metricgroup", Equals, match[0][2])

stat, ok = <-t.out
c.Assert(ok, Equals, true)
c.Check(string(stat), Equals, "cronner.testCmd.exit_code:0|g|#cronner_group:metricgroup")

stat, ok = <-t.out
c.Assert(ok, Equals, true)
c.Check(
string(stat),
Equals,
fmt.Sprintf(`_e{55,77}:Cron testCmd succeeded in %.5f seconds on brainbox01|UUID: %v\nexit code: 0\noutput: somevalue\n|k:%v|s:cronner|t:success|#source_type:cronner,cronner_label_name:testCmd`, runTime/1000, t.h.uuid, t.h.uuid),
)

//
// Test that no output is given
//
Expand All @@ -257,6 +303,7 @@ func (t *TestSuite) Test_handleCommand(c *C) {

t.h.cmd = exec.Command("/bin/echo", "something")
t.h.opts.EventGroup = ""
t.h.opts.Group = ""

t.h.opts.LogFail = false
t.h.opts.Lock = true
Expand Down

0 comments on commit 60ee6e7

Please sign in to comment.