func measurementObjectiveEvaluate(context *ctp.ApiContext, item *Measurement) *ctp.HttpError { item.Objective.Status = ctp.Terror ctp.Log(context, ctp.DEBUG, "Evaluating objective: %s\n", item.Objective.Condition) machine, err := jsmm.Compile(item.Objective.Condition) if err != nil { return ctp.NewBadRequestErrorf("Error in objective compilation - %s", err.Error()) } if item.Result == nil { item.Objective.Status = ctp.Ttrue return nil } if context.DebugVM { machine.DebugMode(true) } if err := importMeasurementResultInJSMM(machine, item.Result); err != nil { return ctp.NewBadRequestErrorf("Error in objective evaluation while importing result - %s", err.Error) } v, exception := machine.Execute() if exception != nil { return ctp.NewBadRequestErrorf("Error in objective evaluation - %s", exception.Error()) } if v != nil { item.Objective.Status = ctp.ToBoolErr(v.ToBoolean()) } return nil }
func measurementCheckResult(context *ctp.ApiContext, item *Measurement) *ctp.HttpError { var metric Metric if item.Metric == "" { return ctp.NewBadRequestError("Missing metric attribute in measurement.") } if item.Result == nil { return ctp.NewBadRequestError("Missing result attribute in measurement.") } metricParams, ok := ctp.ParseLink(context.CtpBase, "@/metrics/$", item.Metric) if !ok { return ctp.NewBadRequestError("Metric URL is incorrect in measurement") } if !ctp.LoadResource(context, "metrics", ctp.Base64Id(metricParams[0]), &metric) { return ctp.NewBadRequestErrorf("Metric %s does not exist", ctp.ExpandLink(context.CtpBase, item.Metric)) } for _, row := range item.Result.Value { if len(row) != len(metric.ResultFormat) { return ctp.NewBadRequestErrorf("Metric expects %d columns, but result value provides %d", len(metric.ResultFormat), len(row)) } for name, cell := range row { metricDetailFound := false for _, metricDetail := range metric.ResultFormat { if metricDetail.Name == name { metricDetailFound = true kind := reflect.ValueOf(cell).Kind() switch metricDetail.Type { case "number": if kind != reflect.Float64 { return ctp.NewBadRequestError("Metric expects a number, but result is of different type") } case "boolean": if kind != reflect.Bool { return ctp.NewBadRequestError("Metric expects a boolean, but result is of different type") } case "string": if kind != reflect.String { return ctp.NewBadRequestError("Metric expects a string, but result is of different type") } default: return ctp.NewBadRequestError("Metric type information is incorrect") } break // from for } } if !metricDetailFound { return ctp.NewBadRequestErrorf("Metric does not describe '%s', which appears in result", name) } } } return nil }
func measurementCheckMetric(context *ctp.ApiContext, item *Measurement) *ctp.HttpError { var metric Metric if item.Metric == "" { return ctp.NewBadRequestError("Missing metric attribute in measurement.") } metricParams, ok := ctp.ParseLink(context.CtpBase, "@/metrics/$", item.Metric) if !ok { return ctp.NewBadRequestError("Metric URL is incorrect in measurement") } if !ctp.LoadResource(context, "metrics", ctp.Base64Id(metricParams[0]), &metric) { return ctp.NewBadRequestErrorf("Metric %s does not exist", ctp.ExpandLink(context.CtpBase, item.Metric)) } return nil }
func triggerCheckCondition(context *ctp.ApiContext, trigger *Trigger, measurement *Measurement) (bool, error) { if measurement == nil { measurementParams, ok := ctp.ParseLink(context.CtpBase, "@/measurements/$", trigger.Measurement) if !ok { return false, fmt.Errorf("Measurement URL is incorrect") } measurement = new(Measurement) if !ctp.LoadResource(context, "measurements", ctp.Base64Id(measurementParams[0]), measurement) { return false, fmt.Errorf("Measurement %s does not exist", ctp.ExpandLink(context.CtpBase, trigger.Measurement)) } } machine, err := jsmm.Compile(trigger.Condition) if err != nil { return false, ctp.NewBadRequestErrorf("Error in condition specification - %s", err.Error()) } if context.DebugVM { machine.DebugMode(true) } if measurement.State != "activated" { return false, nil } if measurement.Result == nil { ctp.Log(context, ctp.ERROR, "In /measurements/%s, the state is activated but the value is null.", measurement.Id) return false, nil } if err := importMeasurementResultInJSMM(machine, measurement.Result); err != nil { return false, err } v, exception := machine.Execute() if exception != nil { return false, fmt.Errorf("Failed to evaluate condition: %s", exception.Error()) } return v.ToBoolean(), nil }
func (trigger *Trigger) Create(context *ctp.ApiContext) *ctp.HttpError { trigger.BuildLinks(context) trigger.Measurement = ctp.ShortenLink(context.CtpBase, trigger.Measurement) if !ctp.IsShortLink(trigger.Measurement) { return ctp.NewBadRequestError("Invalid measurement URL") } ok, err := triggerCheckCondition(context, trigger, nil) if err != nil { return ctp.NewBadRequestErrorf("%s", err.Error()) } if ok { triggerLogAndNotify(context, trigger, nil) } if !ctp.CreateResource(context, "triggers", trigger) { return ctp.NewHttpError(http.StatusInternalServerError, "Could not save object") } return nil }