作者:mathp
项目:bosu
// AddMeta adds a metadata entry to memory, which is queued for later sending.
func AddMeta(metric string, tags opentsdb.TagSet, name string, value interface{}, setHost bool) {
if tags == nil {
tags = make(opentsdb.TagSet)
}
if _, present := tags["host"]; setHost && !present {
tags["host"] = util.Hostname
}
if err := tags.Clean(); err != nil {
slog.Error(err)
return
}
ts := tags.Tags()
metalock.Lock()
defer metalock.Unlock()
prev, present := metadata[Metakey{metric, ts, name}]
if present && !reflect.DeepEqual(prev, value) {
slog.Infof("metadata changed for %s/%s/%s: %v to %v", metric, ts, name, prev, value)
go sendMetadata([]Metasend{{
Metric: metric,
Tags: tags,
Name: name,
Value: value,
}})
} else if metadebug {
slog.Infof("AddMeta for %s/%s/%s: %v", metric, ts, name, value)
}
metadata[Metakey{metric, ts, name}] = value
}
作者:mhenderson-s
项目:bosu
// MakeSaveCommandHook takes a fuction based on the command name and will run it on save passing files, user,
// message, args... as arguments to the command. For the SaveHook function that is returned, If the command fails
// to execute or returns a non normal output then an error is returned.
func MakeSaveCommandHook(cmdName string) (f SaveHook, err error) {
_, err = exec.LookPath(cmdName)
if err != nil {
return f, fmt.Errorf("command %v not found, failed to create save hook: %v", cmdName, err)
}
f = func(files, user, message string, args ...string) error {
cArgs := []string{files, user, message}
cArgs = append(cArgs, args...)
slog.Infof("executing save hook %v\n", cmdName)
c := exec.Command(cmdName, cArgs...)
var cOut bytes.Buffer
var cErr bytes.Buffer
c.Stdout = &cOut
c.Stderr = &cErr
err := c.Start()
if err != nil {
return err
}
err = c.Wait()
if err != nil {
slog.Warning(cErr.String())
return err
}
slog.Infof("save hook ouput: %v\n", cOut.String())
return nil
}
return
}
作者:Skyscanne
项目:bosu
func (s *Schedule) CheckAlert(T miniprofiler.Timer, r *RunHistory, a *conf.Alert) {
slog.Infof("check alert %v start", a.Name)
start := utcNow()
for _, ak := range s.findUnknownAlerts(r.Start, a.Name) {
r.Events[ak] = &models.Event{Status: models.StUnknown}
}
var warns, crits models.AlertKeys
d, err := s.executeExpr(T, r, a, a.Depends)
var deps expr.ResultSlice
if err == nil {
deps = filterDependencyResults(d)
crits, err = s.CheckExpr(T, r, a, a.Crit, models.StCritical, nil)
if err == nil {
warns, err = s.CheckExpr(T, r, a, a.Warn, models.StWarning, crits)
}
}
unevalCount, unknownCount := markDependenciesUnevaluated(r.Events, deps, a.Name)
if err != nil {
slog.Errorf("Error checking alert %s: %s", a.Name, err.Error())
removeUnknownEvents(r.Events, a.Name)
s.markAlertError(a.Name, err)
} else {
s.markAlertSuccessful(a.Name)
}
collect.Put("check.duration", opentsdb.TagSet{"name": a.Name}, time.Since(start).Seconds())
slog.Infof("check alert %v done (%s): %v crits, %v warns, %v unevaluated, %v unknown", a.Name, time.Since(start), len(crits), len(warns), unevalCount, unknownCount)
}
作者:eswd
项目:bosu
func runService(name string, isDebug bool) {
errFix := fixEventMessageFile(name) //Temp fix. Remove after a few weeks.
if errFix != nil {
slog.Errorf("%s fixEventMessageFile failed: %v", name, errFix)
return
}
if isDebug {
slog.SetEventLog(debug.New(name), 1)
} else {
elog, err := eventlog.Open(name)
if err != nil {
return
}
slog.SetEventLog(elog, 1)
defer elog.Close()
}
slog.Infof("starting %s service version %v (%v)", name, version.Version, version.VersionSHA)
run := svc.Run
if isDebug {
run = debug.Run
}
err := run(name, &s{})
if err != nil {
slog.Errorf("%s service failed: %v", name, err)
return
}
slog.Infof("%s service stopped", name)
os.Exit(0)
}
作者:Skyscanne
项目:bosu
func LogComputations(r *Results) {
slice := r.Results
for _, result := range slice {
slog.Infof("Group tags %v\n", result.Group)
for _, z := range result.Computations {
slog.Infof("%v = %v \n", z.Text, z.Value)
}
}
}
作者:snowsnai
项目:bosu
func (s *Schedule) executeTemplates(state *State, event *Event, a *conf.Alert, r *RunHistory) {
state.Subject = ""
state.Body = ""
state.EmailBody = nil
state.EmailSubject = nil
state.Attachments = nil
if event.Status != StUnknown {
metric := "template.render"
//Render subject
endTiming := collect.StartTimer(metric, opentsdb.TagSet{"alert": a.Name, "type": "subject"})
subject, serr := s.ExecuteSubject(r, a, state, false)
if serr != nil {
slog.Infof("%s: %v", state.AlertKey(), serr)
}
endTiming()
//Render body
endTiming = collect.StartTimer(metric, opentsdb.TagSet{"alert": a.Name, "type": "body"})
body, _, berr := s.ExecuteBody(r, a, state, false)
if berr != nil {
slog.Infof("%s: %v", state.AlertKey(), berr)
}
endTiming()
//Render email body
endTiming = collect.StartTimer(metric, opentsdb.TagSet{"alert": a.Name, "type": "emailbody"})
emailbody, attachments, merr := s.ExecuteBody(r, a, state, true)
if merr != nil {
slog.Infof("%s: %v", state.AlertKey(), merr)
}
endTiming()
//Render email subject
endTiming = collect.StartTimer(metric, opentsdb.TagSet{"alert": a.Name, "type": "emailsubject"})
emailsubject, eserr := s.ExecuteSubject(r, a, state, true)
endTiming()
if serr != nil || berr != nil || merr != nil || eserr != nil {
var err error
endTiming = collect.StartTimer(metric, opentsdb.TagSet{"alert": a.Name, "type": "bad"})
subject, body, err = s.ExecuteBadTemplate(serr, berr, r, a, state)
endTiming()
if err != nil {
subject = []byte(fmt.Sprintf("unable to create template error notification: %v", err))
}
emailbody = body
attachments = nil
}
state.Subject = string(subject)
state.Body = string(body)
state.EmailBody = emailbody
state.EmailSubject = emailsubject
state.Attachments = attachments
}
}
作者:nicolle
项目:bosu
func (s *Schedule) CheckAlert(T miniprofiler.Timer, r *RunHistory, a *conf.Alert) (cancelled bool) {
slog.Infof("check alert %v start", a.Name)
start := utcNow()
for _, ak := range s.findUnknownAlerts(r.Start, a.Name) {
r.Events[ak] = &models.Event{Status: models.StUnknown}
}
var warns, crits models.AlertKeys
type res struct {
results *expr.Results
error error
}
// buffered channel so go func that runs executeExpr won't leak if the Check is cancelled
// by the closing of the schedule
rc := make(chan res, 1)
var d *expr.Results
var err error
go func() {
d, err := s.executeExpr(T, r, a, a.Depends)
rc <- res{d, err} // this will hang forever if the channel isn't buffered since nothing will ever receieve from rc
}()
select {
case res := <-rc:
d = res.results
err = res.error
// If the schedule closes before the expression has finised executing, we abandon the
// execution of the expression
case <-s.runnerContext.Done():
return true
}
var deps expr.ResultSlice
if err == nil {
deps = filterDependencyResults(d)
crits, err, cancelled = s.CheckExpr(T, r, a, a.Crit, models.StCritical, nil)
if err == nil && !cancelled {
warns, err, cancelled = s.CheckExpr(T, r, a, a.Warn, models.StWarning, crits)
}
}
if cancelled {
return true
}
unevalCount, unknownCount := markDependenciesUnevaluated(r.Events, deps, a.Name)
if err != nil {
slog.Errorf("Error checking alert %s: %s", a.Name, err.Error())
removeUnknownEvents(r.Events, a.Name)
s.markAlertError(a.Name, err)
} else {
s.markAlertSuccessful(a.Name)
}
collect.Put("check.duration", opentsdb.TagSet{"name": a.Name}, time.Since(start).Seconds())
slog.Infof("check alert %v done (%s): %v crits, %v warns, %v unevaluated, %v unknown", a.Name, time.Since(start), len(crits), len(warns), unevalCount, unknownCount)
return false
}
作者:nicolle
项目:bosu
// errRecover is the handler that turns panics into returns from the top
// level of Parse.
func errRecover(errp *error) {
e := recover()
if e != nil {
switch err := e.(type) {
case runtime.Error:
slog.Infof("%s: %s", e, debug.Stack())
panic(e)
case error:
*errp = err
default:
slog.Infof("%s: %s", e, debug.Stack())
panic(e)
}
}
}
作者:nicolle
项目:bosu
func init() {
err := slog.SetSyslog("scollector")
if err != nil {
slog.Error(err)
}
slog.Infof("starting %s", version.GetVersionInfo("scollector"))
}
作者:youngl9
项目:bosu
func (s *Schedule) save() {
if s.db == nil {
return
}
s.Lock("Save")
store := map[string]interface{}{
dbMetric: s.Search.Read.Metric,
dbTagk: s.Search.Read.Tagk,
dbTagv: s.Search.Read.Tagv,
dbMetricTags: s.Search.Read.MetricTags,
dbNotifications: s.Notifications,
dbSilence: s.Silence,
dbStatus: s.status,
dbMetadata: s.Metadata,
dbIncidents: s.Incidents,
}
tostore := make(map[string][]byte)
for name, data := range store {
f := new(bytes.Buffer)
gz := gzip.NewWriter(f)
cw := &counterWriter{w: gz}
enc := gob.NewEncoder(cw)
if err := enc.Encode(data); err != nil {
slog.Errorf("error saving %s: %v", name, err)
s.Unlock()
return
}
if err := gz.Flush(); err != nil {
slog.Errorf("gzip flush error saving %s: %v", name, err)
}
if err := gz.Close(); err != nil {
slog.Errorf("gzip close error saving %s: %v", name, err)
}
tostore[name] = f.Bytes()
slog.Infof("wrote %s: %v", name, conf.ByteSize(cw.written))
collect.Put("statefile.size", opentsdb.TagSet{"object": name}, cw.written)
}
s.Unlock()
err := s.db.Update(func(tx *bolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte(dbBucket))
if err != nil {
return err
}
for name, data := range tostore {
if err := b.Put([]byte(name), data); err != nil {
return err
}
}
return nil
})
if err != nil {
slog.Errorf("save db update error: %v", err)
return
}
fi, err := os.Stat(s.Conf.StateFile)
if err == nil {
collect.Put("statefile.size", opentsdb.TagSet{"object": "total"}, fi.Size())
}
slog.Infoln("save to db complete")
}
作者:mathp
项目:bosu
// Command executes the named program with the given arguments. If it does not
// exit within timeout, it is sent SIGINT (if supported by Go). After
// another timeout, it is killed.
func Command(timeout time.Duration, stdin io.Reader, name string, arg ...string) (io.Reader, error) {
if _, err := exec.LookPath(name); err != nil {
return nil, ErrPath
}
if Debug {
slog.Infof("executing command: %v %v", name, arg)
}
c := exec.Command(name, arg...)
var b bytes.Buffer
c.Stdout = &b
c.Stdin = stdin
done := make(chan error, 1)
go func() {
done <- c.Run()
}()
interrupt := time.After(timeout)
kill := time.After(timeout * 2)
for {
select {
case err := <-done:
return &b, err
case <-interrupt:
c.Process.Signal(os.Interrupt)
case <-kill:
// todo: figure out if this can leave the done chan hanging open
c.Process.Kill()
return nil, ErrTimeout
}
}
}
作者:nicolle
项目:bosu
// Command executes the named program with the given arguments. If it does not
// exit within timeout, it is sent SIGINT (if supported by Go). After
// another timeout, it is killed.
func Command(timeout time.Duration, stdin io.Reader, name string, arg ...string) (io.Reader, error) {
if _, err := exec.LookPath(name); err != nil {
return nil, ErrPath
}
if Debug {
slog.Infof("executing command: %v %v", name, arg)
}
c := exec.Command(name, arg...)
b := &bytes.Buffer{}
c.Stdout = b
c.Stdin = stdin
if err := c.Start(); err != nil {
return nil, err
}
timedOut := false
intTimer := time.AfterFunc(timeout, func() {
slog.Errorf("Process taking too long. Interrupting: %s %s", name, strings.Join(arg, " "))
c.Process.Signal(os.Interrupt)
timedOut = true
})
killTimer := time.AfterFunc(timeout*2, func() {
slog.Errorf("Process taking too long. Killing: %s %s", name, strings.Join(arg, " "))
c.Process.Signal(os.Kill)
timedOut = true
})
err := c.Wait()
intTimer.Stop()
killTimer.Stop()
if timedOut {
return nil, ErrTimeout
}
return b, err
}
作者:noblehn
项目:bosu
func (s *Schedule) checkAlert(a *conf.Alert) {
checkTime := s.ctx.runTime
checkCache := s.ctx.checkCache
rh := s.NewRunHistory(checkTime, checkCache)
s.CheckAlert(nil, rh, a)
start := utcNow()
s.RunHistory(rh)
slog.Infof("runHistory on %s took %v\n", a.Name, time.Since(start))
}
作者:mathp
项目:bosu
func sendBatch(batch []*opentsdb.DataPoint) {
if Print {
for _, d := range batch {
j, err := d.MarshalJSON()
if err != nil {
slog.Error(err)
}
slog.Info(string(j))
}
recordSent(len(batch))
return
}
now := time.Now()
resp, err := SendDataPoints(batch, tsdbURLs[currentTsdbURL])
if err == nil {
defer resp.Body.Close()
}
d := time.Since(now).Nanoseconds() / 1e6
Sample("collect.post.duration", Tags, float64(d))
Add("collect.post.total_duration", Tags, d)
Add("collect.post.count", Tags, 1)
// Some problem with connecting to the server; retry later.
if err != nil || (resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK) {
if err != nil {
Add("collect.post.error", Tags, 1)
slog.Error(err)
// Switch endpoint if possible
currentTsdbURL = (currentTsdbURL + 1) % len(tsdbURLs)
} else if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK {
Add("collect.post.bad_status", Tags, 1)
slog.Errorln(resp.Status)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
slog.Error(err)
}
if len(body) > 0 {
slog.Error(string(body))
}
// Switch endpoint if possible
currentTsdbURL = (currentTsdbURL + 1) % len(tsdbURLs)
}
restored := 0
for _, msg := range batch {
restored++
tchan <- msg
}
d := time.Second * 5
Add("collect.post.restore", Tags, int64(restored))
slog.Infof("restored %d, sleeping %s", restored, d)
time.Sleep(d)
return
}
recordSent(len(batch))
}
作者:noblehn
项目:bosu
func (n *Notification) DoGet(ak string) {
resp, err := http.Get(n.Get.String())
if err != nil {
slog.Error(err)
return
}
if resp.StatusCode >= 300 {
slog.Error("bad response on notification get:", resp.Status)
} else {
slog.Infof("get notification successful for alert %s. Response code %d.", ak, resp.StatusCode)
}
}
作者:nicolle
项目:bosu
func (s *Schedule) checkAlert(a *conf.Alert) {
checkTime := s.ctx.runTime
checkCache := s.ctx.checkCache
rh := s.NewRunHistory(checkTime, checkCache)
// s.CheckAlert will return early if the schedule has been closed
cancelled := s.CheckAlert(nil, rh, a)
if cancelled {
// Don't runHistory for the alert if expression evaluation has been cancelled
return
}
start := utcNow()
s.RunHistory(rh)
slog.Infof("runHistory on %s took %v\n", a.Name, time.Since(start))
}
作者:nicolle
项目:bosu
func runService(name string, isDebug bool) {
if isDebug {
slog.SetEventLog(debug.New(name), 1)
} else {
elog, err := eventlog.Open(name)
if err != nil {
return
}
slog.SetEventLog(elog, 1)
defer elog.Close()
}
slog.Infof("starting service %s%s", name, version.GetVersionInfo(""))
run := svc.Run
if isDebug {
run = debug.Run
}
err := run(name, &s{})
if err != nil {
slog.Errorf("%s service failed: %v", name, err)
return
}
slog.Infof("%s service stopped", name)
os.Exit(0)
}
作者:nicolle
项目:bosu
// ReadCommandTimeout is the same as ReadCommand with a specifiable timeout.
// It can also take a []byte as input (useful for chaining commands).
func ReadCommandTimeout(timeout time.Duration, line func(string) error, stdin io.Reader, name string, arg ...string) error {
b, err := Command(timeout, stdin, name, arg...)
if err != nil {
return err
}
scanner := bufio.NewScanner(b)
for scanner.Scan() {
if err := line(scanner.Text()); err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
slog.Infof("%v: %v\n", name, err)
}
return nil
}
作者:rajde
项目:bosu
// Locks the queue and sends all datapoints. Intended to be used as scollector exits.
func Flush() {
qlock.Lock()
for len(queue) > 0 {
i := len(queue)
if i > BatchSize {
i = BatchSize
}
sending := queue[:i]
queue = queue[i:]
if Debug {
slog.Infof("sending: %d, remaining: %d", i, len(queue))
}
sendBatch(sending)
}
qlock.Unlock()
}
作者:Yahpa
项目:Yahpay-bosu
func send() {
for {
qlock.Lock()
if i := len(queue); i > 0 {
if i > BatchSize {
i = BatchSize
}
sending := queue[:i]
queue = queue[i:]
if Debug {
slog.Infof("sending: %d, remaining: %d", i, len(queue))
}
qlock.Unlock()
sendBatch(sending)
} else {
qlock.Unlock()
time.Sleep(time.Second)
}
}
}