@POST
  @Timed
  @ApiOperation(value = "Create a stream rule")
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public Response create(
      @ApiParam(
              title = "streamid",
              description = "The stream id this new rule belongs to.",
              required = true)
          @PathParam("streamid")
          String streamid,
      @ApiParam(title = "JSON body", required = true) String body) {
    CreateRequest cr;
    checkPermission(RestPermissions.STREAMS_EDIT, streamid);

    try {
      cr = objectMapper.readValue(body, CreateRequest.class);
    } catch (IOException e) {
      LOG.error("Error while parsing JSON", e);
      throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
    }

    try {
      streamService.load(streamid);
    } catch (NotFoundException e) {
      throw new WebApplicationException(404);
    }

    Map<String, Object> streamRuleData = Maps.newHashMap();
    streamRuleData.put("type", cr.type);
    streamRuleData.put("value", cr.value);
    streamRuleData.put("field", cr.field);
    streamRuleData.put("inverted", cr.inverted);
    streamRuleData.put("stream_id", new ObjectId(streamid));

    final StreamRule streamRule = new StreamRuleImpl(streamRuleData);

    String id;
    try {
      id = streamService.save(streamRule);
    } catch (ValidationException e) {
      LOG.error("Validation error.", e);
      throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
    }

    Map<String, Object> result = Maps.newHashMap();
    result.put("streamrule_id", id);

    return Response.status(Response.Status.CREATED).entity(json(result)).build();
  }
  @GET
  @Timed
  @ApiOperation(value = "Get a list of all stream rules")
  @Produces(MediaType.APPLICATION_JSON)
  public String get(
      @ApiParam(
              title = "streamid",
              description = "The id of the stream whose stream rules we want.",
              required = true)
          @PathParam("streamid")
          String streamid) {
    List<Map<String, Object>> streamRules = Lists.newArrayList();
    checkPermission(RestPermissions.STREAMS_READ, streamid);

    final Stream stream;
    try {
      stream = streamService.load(streamid);
    } catch (NotFoundException e) {
      throw new WebApplicationException(404);
    }

    try {
      for (StreamRule streamRule : streamRuleService.loadForStream(stream)) {
        streamRules.add(streamRule.asMap());
      }
    } catch (org.graylog2.database.NotFoundException e) {
      throw new WebApplicationException(404);
    }

    Map<String, Object> result = Maps.newHashMap();
    result.put("total", streamRules.size());
    result.put("stream_rules", streamRules);

    return json(result);
  }
  @Override
  public void doRun() {
    if (!indexerSetupService.isRunning()) {
      LOG.error("Indexer is not running, not checking streams for alerts.");
      return;
    }

    LOG.debug("Running alert checks.");
    final List<Stream> alertedStreams = streamService.loadAllWithConfiguredAlertConditions();

    LOG.debug("There are {} streams with configured alert conditions.", alertedStreams.size());

    // Load all streams that have configured alert conditions.
    for (Stream stream : alertedStreams) {
      LOG.debug(
          "Stream [{}] has [{}] configured alert conditions.",
          stream,
          streamService.getAlertConditions(stream).size());

      if (stream.isPaused()) {
        LOG.debug("Stream [{}] has been paused. Skipping alert check.", stream);
        continue;
      }

      // Check if a threshold is reached.
      for (AlertCondition alertCondition : streamService.getAlertConditions(stream)) {
        try {
          final AlertCondition.CheckResult result = alertService.triggered(alertCondition);
          if (result.isTriggered()) {
            // Alert is triggered!
            LOG.debug("Alert condition [{}] is triggered. Sending alerts.", alertCondition);

            // Persist alert.
            final Alert alert = alertService.factory(result);
            alertService.save(alert);

            final List<AlarmCallbackConfiguration> callConfigurations =
                alarmCallbackConfigurationService.getForStream(stream);

            // Checking if alarm callbacks have been defined
            if (callConfigurations.size() > 0)
              for (AlarmCallbackConfiguration configuration : callConfigurations) {
                AlarmCallbackHistory alarmCallbackHistory;
                AlarmCallback alarmCallback = null;
                try {
                  alarmCallback = alarmCallbackFactory.create(configuration);
                  alarmCallback.call(stream, result);
                  alarmCallbackHistory =
                      alarmCallbackHistoryService.success(configuration, alert, alertCondition);
                } catch (Exception e) {
                  if (alarmCallback != null) {
                    LOG.warn(
                        "Alarm callback <" + alarmCallback.getName() + "> failed. Skipping.", e);
                  } else {
                    LOG.warn(
                        "Alarm callback with id " + configuration.getId() + " failed. Skipping.",
                        e);
                  }
                  alarmCallbackHistory =
                      alarmCallbackHistoryService.error(
                          configuration, alert, alertCondition, e.getMessage());
                }

                try {
                  alarmCallbackHistoryService.save(alarmCallbackHistory);
                } catch (Exception e) {
                  LOG.warn("Unable to save history of alarm callback run: ", e);
                }
              }
            else {
              /* Using e-mail alarm callback per default if there are no alarm callbacks configured explicitly.
              This way we are supporting users who have upgraded from an old version where alarm callbacks
              were non-existent. It also helps for users who forgot to set up alarm callbacks for newly
              created alert conditions. */
              emailAlarmCallback.call(stream, result);
            }
          } else {
            // Alert not triggered.
            LOG.debug("Alert condition [{}] is not triggered.", alertCondition);
          }
        } catch (Exception e) {
          LOG.error("Skipping alert check that threw an exception.", e);
        }
      }
    }
  }