Example #1
0
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)
}
Example #2
0
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())
		}
	}
}