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
}
Beispiel #3
0
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
}