func CreateErrorLogEntry(context *ctp.ApiContext, trigger *Trigger, errmsg string) *ctp.HttpError { var log = new(LogEntry) log.Id = ctp.NewBase64Id() log.Parent = trigger.Parent log.AccessTags = trigger.AccessTags log.CreationTime = ctp.Now() log.Trigger = trigger.Self log.Error = &errmsg log.Tags = []string{"error"} return log.Create(context) }
func CreateNormalLogEntry(context *ctp.ApiContext, trigger *Trigger, result *Result, tags []string) *ctp.HttpError { var log = new(LogEntry) log.Id = ctp.NewBase64Id() log.Parent = trigger.Parent log.AccessTags = trigger.AccessTags log.CreationTime = ctp.Now() log.Trigger = trigger.Self log.Result = result log.Tags = tags return log.Create(context) }
func (measurement *Measurement) Update(context *ctp.ApiContext, update ctp.ResourceUpdater) *ctp.HttpError { measurement.BuildLinks(context) up, ok := update.(*Measurement) if !ok { return ctp.NewInternalServerError("Updated object is not a measurement") // should never happen } switch context.QueryParam { case "userActivated": switch up.State { case "activated": if measurement.State == "deactivated" { measurement.State = "pending" // FIXME: add backoffice logic for notification of state change? } case "deactivated": measurement.State = "deactivated" measurement.Result = nil default: return ctp.NewBadRequestError("state can only be 'activated' or 'deactivated'") } case "objective": measurement.Objective = up.Objective if err := measurementObjectiveEvaluate(context, measurement); err != nil { return err } case "result": if measurement.State == "deactivated" { return ctp.NewHttpError(http.StatusConflict, "Measurement is not in activated state.") } if measurement.State == "pending" { measurement.State = "activated" } if up.Result == nil { return ctp.NewBadRequestError("No result provided in request") } measurement.Result = up.Result if measurement.Result.UpdateTime.IsZero() { measurement.Result.UpdateTime = ctp.Now() } if err := measurementCheckMetric(context, measurement); err != nil { return err } if measurement.Objective != nil { if err := measurementObjectiveEvaluate(context, measurement); err != nil { return err } } measurementTriggersEvaluate(context, measurement) default: return ctp.NewBadRequestError("invalid query string") // should never happen, because already filtered in serve.go } if !ctp.UpdateResource(context, "measurements", measurement.Id, measurement) { return ctp.NewInternalServerError("Could not update measurement object") } return nil }
func measurementTriggersEvaluate(context *ctp.ApiContext, measurement *Measurement) { var trigger Trigger now := ctp.Now() mlink := ctp.ShortenLink(context.CtpBase, measurement.Self) query := context.Session.DB("ctp").C("triggers").Find(bson.M{"measurement": mlink}) n, err := query.Count() if err == nil { ctp.Log(context, ctp.DEBUG, "Evaluating %d triggers related to measurement %s", n, measurement.Id) } else { ctp.Log(context, ctp.ERROR, "Failed to evaludate triggers related to measurement %s, %s", measurement.Id, err.Error()) return } iter := query.Iter() for iter.Next(&trigger) { var err error var err_upd error var ok bool trigger.BuildLinks(context) ctp.Log(context, ctp.DEBUG, "Evaludating trigger %s, currently with status '%s'", trigger.Id, trigger.Status.String()) switch trigger.Status { case ctp.Tfalse: ok, err = triggerCheckCondition(context, &trigger, measurement) case ctp.Ttrue: if uint(ctp.SecondsSince(trigger.StatusUpdateTime)) <= trigger.GuardTime { continue } ok, err = triggerCheckCondition(context, &trigger, measurement) case ctp.Terror: continue } switch { case err != nil: ctp.Log(context, ctp.ERROR, "Error in trigger %s for measurement %s", trigger.Id, measurement.Id) err_log := CreateErrorLogEntry(context, &trigger, err.Error()) if err_log != nil { ctp.Log(context, ctp.ERROR, "Failed to create error log: %s", err_log.Error()) } err_upd = context.Session.DB("ctp").C("triggers").Update(bson.M{"_id": trigger.Id}, bson.M{"$set": bson.M{"status": ctp.Terror, "statusUpdateTime": now.String()}}) case ok: ctp.Log(context, ctp.DEBUG, "trigger %s is TRUE", trigger.Id) err_log := CreateNormalLogEntry(context, &trigger, measurement.Result, trigger.Tags) if err_log != nil { ctp.Log(context, ctp.ERROR, "Failed to create normal log: %s", err_log.Error()) } err_upd = context.Session.DB("ctp").C("triggers").Update(bson.M{"_id": trigger.Id}, bson.M{"$set": bson.M{"status": ctp.Ttrue, "statusUpdateTime": now.String()}}) default: ctp.Log(context, ctp.DEBUG, "Trigger %s is FALSE", trigger.Id) err_upd = context.Session.DB("ctp").C("triggers").Update(bson.M{"_id": trigger.Id}, bson.M{"$set": bson.M{"status": ctp.Tfalse, "statusUpdateTime": now.String()}}) } if err_upd != nil { ctp.Log(context, ctp.ERROR, "Failed to update trigger 'status' and 'statusDateTime': %s", err_upd.Error()) } } }