-
Notifications
You must be signed in to change notification settings - Fork 495
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/scollector: add windows support to puppet collector (#2227)
- Loading branch information
1 parent
6c5bf65
commit 8a14759
Showing
3 changed files
with
168 additions
and
157 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
// +build windows linux | ||
|
||
package collectors | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"strconv" | ||
"time" | ||
|
||
"bosun.org/metadata" | ||
"bosun.org/opentsdb" | ||
"gopkg.in/yaml.v1" | ||
) | ||
|
||
func init() { | ||
collectors = append(collectors, &IntervalCollector{F: puppet, Enable: puppetEnable}) | ||
} | ||
|
||
func puppetEnable() bool { | ||
_, err := os.Stat(puppetPath) | ||
return err == nil | ||
} | ||
|
||
type PRSummary struct { | ||
Changes struct { | ||
Total float64 `yaml:"total"` | ||
} `yaml:"changes"` | ||
Events struct { | ||
Failure float64 `yaml:"failure"` | ||
Success float64 `yaml:"success"` | ||
Total float64 `yaml:"total"` | ||
} `yaml:"events"` | ||
Resources struct { | ||
Changed float64 `yaml:"changed"` | ||
Failed float64 `yaml:"failed"` | ||
FailedToRestart float64 `yaml:"failed_to_restart"` | ||
OutOfSync float64 `yaml:"out_of_sync"` | ||
Restarted float64 `yaml:"restarted"` | ||
Scheduled float64 `yaml:"scheduled"` | ||
Skipped float64 `yaml:"skipped"` | ||
Total float64 `yaml:"total"` | ||
} `yaml:"resources"` | ||
Time map[string]string `yaml:"time"` | ||
Version struct { | ||
Config string `yaml:"config"` | ||
Puppet string `yaml:"puppet"` | ||
} `yaml:"version"` | ||
} | ||
|
||
type PRReport struct { | ||
Status string `yaml:"status"` | ||
Time string `yaml:"time"` // 2006-01-02 15:04:05.999999 -07:00 | ||
} | ||
|
||
func puppet() (opentsdb.MultiDataPoint, error) { | ||
var md opentsdb.MultiDataPoint | ||
// See if puppet has been disabled (i.e. `puppet agent --disable 'Reason'`) | ||
var disabled, noReason int | ||
if v, err := ioutil.ReadFile(puppetDisabled); err == nil { | ||
disabled = 1 | ||
d := struct { | ||
Disabled string `json:"disabled_message"` | ||
}{} | ||
if err := json.Unmarshal(v, &d); err == nil && d.Disabled != "" { | ||
if d.Disabled == "reason not specified" { | ||
noReason = 1 | ||
} | ||
metadata.AddMeta("", nil, "puppet.disabled_reason", d.Disabled, true) | ||
} | ||
} | ||
Add(&md, "puppet.disabled", disabled, nil, metadata.Gauge, metadata.Count, "") | ||
Add(&md, "puppet.disabled_no_reason", noReason, nil, metadata.Gauge, metadata.Count, "") | ||
// Gather stats from the run summary | ||
s, err := ioutil.ReadFile(puppetRunSummary) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var m PRSummary | ||
if err = yaml.Unmarshal(s, &m); err != nil { | ||
return nil, err | ||
} | ||
last_run, err := strconv.ParseInt(m.Time["last_run"], 10, 64) | ||
seconds_since_run := time.Now().Unix() - last_run | ||
//m.Version.Config appears to be the unix timestamp | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Changed, opentsdb.TagSet{"resource": "changed"}, metadata.Gauge, metadata.Count, descPuppetChanged) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Failed, opentsdb.TagSet{"resource": "failed"}, metadata.Gauge, metadata.Count, descPuppetFailed) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.FailedToRestart, opentsdb.TagSet{"resource": "failed_to_restart"}, metadata.Gauge, metadata.Count, descPuppetFailedToRestart) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.OutOfSync, opentsdb.TagSet{"resource": "out_of_sync"}, metadata.Gauge, metadata.Count, descPuppetOutOfSync) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Restarted, opentsdb.TagSet{"resource": "restarted"}, metadata.Gauge, metadata.Count, descPuppetRestarted) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Scheduled, opentsdb.TagSet{"resource": "scheduled"}, metadata.Gauge, metadata.Count, descPuppetScheduled) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Skipped, opentsdb.TagSet{"resource": "skipped"}, metadata.Gauge, metadata.Count, descPuppetSkipped) | ||
AddTS(&md, "puppet.run.resources_total", last_run, m.Resources.Total, nil, metadata.Gauge, metadata.Count, descPuppetTotalResources) | ||
AddTS(&md, "puppet.run.changes", last_run, m.Changes.Total, nil, metadata.Gauge, metadata.Count, descPuppetTotalChanges) | ||
Add(&md, "puppet.last_run", seconds_since_run, nil, metadata.Gauge, metadata.Second, descPuppetLastRun) | ||
for k, v := range m.Time { | ||
metric, err := strconv.ParseFloat(v, 64) | ||
if err != nil { | ||
return md, fmt.Errorf("Error parsing time: %s", err) | ||
} | ||
if k == "total" { | ||
AddTS(&md, "puppet.run_duration_total", last_run, metric, nil, metadata.Gauge, metadata.Second, descPuppetTotalTime) | ||
} else if k != "last_run" { | ||
AddTS(&md, "puppet.run_duration", last_run, metric, opentsdb.TagSet{"time": k}, metadata.Gauge, metadata.Second, descPuppetModuleTime) | ||
} | ||
} | ||
|
||
// Not all hosts will use puppet run reports | ||
if _, err := os.Stat(puppetRunReport); err == nil { | ||
f, err := ioutil.ReadFile(puppetRunReport) | ||
if err != nil { | ||
return md, err | ||
} | ||
|
||
var report PRReport | ||
if err = yaml.Unmarshal(f, &report); err != nil { | ||
return md, err | ||
} | ||
|
||
t, err := time.Parse("2006-01-02 15:04:05.999999 -07:00", report.Time) | ||
if err != nil { | ||
// Puppet 5 changed the time format | ||
t, err = time.Parse("2006-01-02T15:04:05.999999-07:00", report.Time) | ||
} | ||
if err != nil { | ||
return md, fmt.Errorf("Error parsing report time: %s", err) | ||
} | ||
// As listed at https://docs.puppetlabs.com/puppet/latest/reference/format_report.html | ||
var statusCode = map[string]int{ | ||
"changed": 0, | ||
"unchanged": 1, | ||
"failed": 2, | ||
} | ||
if status, ok := statusCode[report.Status]; ok { | ||
AddTS(&md, "puppet.run.status", t.Unix(), status, nil, metadata.Gauge, metadata.StatusCode, descPuppetRunStatus) | ||
} else { | ||
return md, fmt.Errorf("Unknown status in %s: %s", puppetRunReport, report.Status) | ||
} | ||
} | ||
return md, nil | ||
} | ||
|
||
const ( | ||
descPuppetChanged = "Number of resources for which changes were applied." | ||
descPuppetFailed = "Number of resources which caused an error during evaluation." | ||
descPuppetFailedToRestart = "Number of service resources which failed to restart." | ||
descPuppetOutOfSync = "Number of resources which should have been changed if catalog was applied." | ||
descPuppetRestarted = "Number of service resources which were restarted." | ||
descPuppetScheduled = "Number of service resources which were scheduled for restart." | ||
descPuppetSkipped = "Number of resources which puppet opted to not apply changes to." | ||
descPuppetTotalResources = "Total number of resources." | ||
descPuppetTotalChanges = "Total number of changes." | ||
descPuppetTotalTime = "Total time which puppet took to run." | ||
descPuppetModuleTime = "Time which this tagged module took to run." | ||
descPuppetLastRun = "Number of seconds since puppet run last ran." | ||
descPuppetRunStatus = "0: changed, 1: unchanged, 2: failed" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,164 +1,8 @@ | ||
package collectors | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"strconv" | ||
"time" | ||
|
||
"bosun.org/metadata" | ||
"bosun.org/opentsdb" | ||
"gopkg.in/yaml.v1" | ||
) | ||
|
||
func init() { | ||
collectors = append(collectors, &IntervalCollector{F: puppet_linux, Enable: puppetEnable}) | ||
} | ||
|
||
const ( | ||
puppetPath = "/var/lib/puppet/" | ||
puppetRunSummary = "/var/lib/puppet/state/last_run_summary.yaml" | ||
puppetRunReport = "/var/lib/puppet/state/last_run_report.yaml" | ||
puppetDisabled = "/var/lib/puppet/state/agent_disabled.lock" | ||
) | ||
|
||
func puppetEnable() bool { | ||
_, err := os.Stat(puppetPath) | ||
return err == nil | ||
} | ||
|
||
type PRSummary struct { | ||
Changes struct { | ||
Total float64 `yaml:"total"` | ||
} `yaml:"changes"` | ||
Events struct { | ||
Failure float64 `yaml:"failure"` | ||
Success float64 `yaml:"success"` | ||
Total float64 `yaml:"total"` | ||
} `yaml:"events"` | ||
Resources struct { | ||
Changed float64 `yaml:"changed"` | ||
Failed float64 `yaml:"failed"` | ||
FailedToRestart float64 `yaml:"failed_to_restart"` | ||
OutOfSync float64 `yaml:"out_of_sync"` | ||
Restarted float64 `yaml:"restarted"` | ||
Scheduled float64 `yaml:"scheduled"` | ||
Skipped float64 `yaml:"skipped"` | ||
Total float64 `yaml:"total"` | ||
} `yaml:"resources"` | ||
Time map[string]string `yaml:"time"` | ||
Version struct { | ||
Config string `yaml:"config"` | ||
Puppet string `yaml:"puppet"` | ||
} `yaml:"version"` | ||
} | ||
|
||
type PRReport struct { | ||
Status string `yaml:"status"` | ||
Time string `yaml:"time"` // 2006-01-02 15:04:05.999999 -07:00 | ||
} | ||
|
||
func puppet_linux() (opentsdb.MultiDataPoint, error) { | ||
var md opentsdb.MultiDataPoint | ||
// See if puppet has been disabled (i.e. `puppet agent --disable 'Reason'`) | ||
var disabled, noReason int | ||
if v, err := ioutil.ReadFile(puppetDisabled); err == nil { | ||
disabled = 1 | ||
d := struct { | ||
Disabled string `json:"disabled_message"` | ||
}{} | ||
if err := json.Unmarshal(v, &d); err == nil && d.Disabled != "" { | ||
if d.Disabled == "reason not specified" { | ||
noReason = 1 | ||
} | ||
metadata.AddMeta("", nil, "puppet.disabled_reason", d.Disabled, true) | ||
} | ||
} | ||
Add(&md, "puppet.disabled", disabled, nil, metadata.Gauge, metadata.Count, "") | ||
Add(&md, "puppet.disabled_no_reason", noReason, nil, metadata.Gauge, metadata.Count, "") | ||
// Gather stats from the run summary | ||
s, err := ioutil.ReadFile(puppetRunSummary) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var m PRSummary | ||
if err = yaml.Unmarshal(s, &m); err != nil { | ||
return nil, err | ||
} | ||
last_run, err := strconv.ParseInt(m.Time["last_run"], 10, 64) | ||
seconds_since_run := time.Now().Unix() - last_run | ||
//m.Version.Config appears to be the unix timestamp | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Changed, opentsdb.TagSet{"resource": "changed"}, metadata.Gauge, metadata.Count, descPuppetChanged) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Failed, opentsdb.TagSet{"resource": "failed"}, metadata.Gauge, metadata.Count, descPuppetFailed) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.FailedToRestart, opentsdb.TagSet{"resource": "failed_to_restart"}, metadata.Gauge, metadata.Count, descPuppetFailedToRestart) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.OutOfSync, opentsdb.TagSet{"resource": "out_of_sync"}, metadata.Gauge, metadata.Count, descPuppetOutOfSync) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Restarted, opentsdb.TagSet{"resource": "restarted"}, metadata.Gauge, metadata.Count, descPuppetRestarted) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Scheduled, opentsdb.TagSet{"resource": "scheduled"}, metadata.Gauge, metadata.Count, descPuppetScheduled) | ||
AddTS(&md, "puppet.run.resources", last_run, m.Resources.Skipped, opentsdb.TagSet{"resource": "skipped"}, metadata.Gauge, metadata.Count, descPuppetSkipped) | ||
AddTS(&md, "puppet.run.resources_total", last_run, m.Resources.Total, nil, metadata.Gauge, metadata.Count, descPuppetTotalResources) | ||
AddTS(&md, "puppet.run.changes", last_run, m.Changes.Total, nil, metadata.Gauge, metadata.Count, descPuppetTotalChanges) | ||
Add(&md, "puppet.last_run", seconds_since_run, nil, metadata.Gauge, metadata.Second, descPuppetLastRun) | ||
for k, v := range m.Time { | ||
metric, err := strconv.ParseFloat(v, 64) | ||
if err != nil { | ||
return md, fmt.Errorf("Error parsing time: %s", err) | ||
} | ||
if k == "total" { | ||
AddTS(&md, "puppet.run_duration_total", last_run, metric, nil, metadata.Gauge, metadata.Second, descPuppetTotalTime) | ||
} else if k != "last_run" { | ||
AddTS(&md, "puppet.run_duration", last_run, metric, opentsdb.TagSet{"time": k}, metadata.Gauge, metadata.Second, descPuppetModuleTime) | ||
} | ||
} | ||
|
||
// Not all hosts will use puppet run reports | ||
if _, err := os.Stat(puppetRunReport); err == nil { | ||
f, err := ioutil.ReadFile(puppetRunReport) | ||
if err != nil { | ||
return md, err | ||
} | ||
|
||
var report PRReport | ||
if err = yaml.Unmarshal(f, &report); err != nil { | ||
return md, err | ||
} | ||
|
||
t, err := time.Parse("2006-01-02 15:04:05.999999 -07:00", report.Time) | ||
if err != nil { | ||
// Puppet 5 changed the time format | ||
t, err = time.Parse("2006-01-02T15:04:05.999999-07:00", report.Time) | ||
} | ||
if err != nil { | ||
return md, fmt.Errorf("Error parsing report time: %s", err) | ||
} | ||
// As listed at https://docs.puppetlabs.com/puppet/latest/reference/format_report.html | ||
var statusCode = map[string]int{ | ||
"changed": 0, | ||
"unchanged": 1, | ||
"failed": 2, | ||
} | ||
if status, ok := statusCode[report.Status]; ok { | ||
AddTS(&md, "puppet.run.status", t.Unix(), status, nil, metadata.Gauge, metadata.StatusCode, descPuppetRunStatus) | ||
} else { | ||
return md, fmt.Errorf("Unknown status in %s: %s", puppetRunReport, report.Status) | ||
} | ||
} | ||
return md, nil | ||
} | ||
|
||
const ( | ||
descPuppetChanged = "Number of resources for which changes were applied." | ||
descPuppetFailed = "Number of resources which caused an error during evaluation." | ||
descPuppetFailedToRestart = "Number of service resources which failed to restart." | ||
descPuppetOutOfSync = "Number of resources which should have been changed if catalog was applied." | ||
descPuppetRestarted = "Number of service resources which were restarted." | ||
descPuppetScheduled = "Number of service resources which were scheduled for restart." | ||
descPuppetSkipped = "Number of resources which puppet opted to not apply changes to." | ||
descPuppetTotalResources = "Total number of resources." | ||
descPuppetTotalChanges = "Total number of changes." | ||
descPuppetTotalTime = "Total time which puppet took to run." | ||
descPuppetModuleTime = "Time which this tagged module took to run." | ||
descPuppetLastRun = "Number of seconds since puppet run last ran." | ||
descPuppetRunStatus = "0: changed, 1: unchanged, 2: failed" | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package collectors | ||
|
||
const ( | ||
puppetPath = `C:\ProgramData\PuppetLabs` | ||
puppetRunSummary = `C:\ProgramData\PuppetLabs\puppet\cache\state\last_run_summary.yaml` | ||
puppetRunReport = `C:\ProgramData\PuppetLabs\puppet\cache\state\last_run_report.yaml` | ||
puppetDisabled = `C:\ProgramData\PuppetLabs\puppet\cache\state\agent_disabled.lock` | ||
) |