Java tutorial
/** * This file is part of Graylog. * * Graylog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Graylog is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Graylog. If not, see <http://www.gnu.org/licenses/>. */ package org.graylog2.alerts; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.QueryBuilder; import org.bson.types.ObjectId; import org.graylog2.alerts.types.FieldValueAlertCondition; import org.graylog2.alerts.types.MessageCountAlertCondition; import org.graylog2.database.MongoConnection; import org.graylog2.database.PersistedServiceImpl; import org.graylog2.plugin.Tools; import org.graylog2.plugin.alarms.AlertCondition; import org.graylog2.plugin.streams.Stream; import org.graylog2.rest.resources.streams.alerts.requests.CreateConditionRequest; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Seconds; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.util.List; import java.util.Map; public class AlertServiceImpl extends PersistedServiceImpl implements AlertService { private static final Logger LOG = LoggerFactory.getLogger(AlertServiceImpl.class); private final FieldValueAlertCondition.Factory fieldValueAlertFactory; private final MessageCountAlertCondition.Factory messageCountAlertFactory; @Inject public AlertServiceImpl(MongoConnection mongoConnection, FieldValueAlertCondition.Factory fieldValueAlertFactory, MessageCountAlertCondition.Factory messageCountAlertFactory) { super(mongoConnection); this.fieldValueAlertFactory = fieldValueAlertFactory; this.messageCountAlertFactory = messageCountAlertFactory; } @Override public Alert factory(AlertCondition.CheckResult checkResult) { if (!checkResult.isTriggered()) { throw new RuntimeException("Tried to create alert from not triggered alert condition result."); } Map<String, Object> fields = Maps.newHashMap(); fields.put("triggered_at", checkResult.getTriggeredAt()); fields.put("condition_id", checkResult.getTriggeredCondition().getId()); fields.put("stream_id", checkResult.getTriggeredCondition().getStream().getId()); fields.put("description", checkResult.getResultDescription()); fields.put("condition_parameters", checkResult.getTriggeredCondition().getParameters()); return new AlertImpl(fields); } @Override public List<Alert> loadRecentOfStream(String streamId, DateTime since) { QueryBuilder qb = QueryBuilder.start("stream_id").is(streamId); if (since != null) { qb.and("triggered_at").greaterThanEquals(since.toDate()); } BasicDBObject sort = new BasicDBObject("triggered_at", -1); final List<DBObject> alertObjects = query(AlertImpl.class, qb.get(), sort, AlertImpl.MAX_LIST_COUNT, 0); List<Alert> alerts = Lists.newArrayList(); for (DBObject alertObj : alertObjects) { alerts.add(new AlertImpl(new ObjectId(alertObj.get("_id").toString()), alertObj.toMap())); } return alerts; } @Override public int triggeredSecondsAgo(String streamId, String conditionId) { DBObject query = QueryBuilder.start("stream_id").is(streamId).and("condition_id").is(conditionId).get(); BasicDBObject sort = new BasicDBObject("triggered_at", -1); DBObject alert = findOne(AlertImpl.class, query, sort); if (alert == null) { return -1; } DateTime triggeredAt = new DateTime(alert.get("triggered_at"), DateTimeZone.UTC); return Seconds.secondsBetween(triggeredAt, Tools.iso8601()).getSeconds(); } @Override public long totalCount() { return collection(AlertImpl.class).count(); } @Override public long totalCountForStream(String streamId) { DBObject qry = new BasicDBObject("stream_id", streamId); return collection(AlertImpl.class).count(qry); } @Override public AlertCondition fromPersisted(Map<String, Object> fields, Stream stream) throws AbstractAlertCondition.NoSuchAlertConditionTypeException { AbstractAlertCondition.Type type; try { type = AbstractAlertCondition.Type.valueOf(((String) fields.get("type")).toUpperCase()); } catch (IllegalArgumentException e) { throw new AbstractAlertCondition.NoSuchAlertConditionTypeException( "No such alert condition type: [" + fields.get("type") + "]"); } return createAlertCondition(type, stream, (String) fields.get("id"), DateTime.parse((String) fields.get("created_at")), (String) fields.get("creator_user_id"), (Map<String, Object>) fields.get("parameters")); } private AbstractAlertCondition createAlertCondition(AbstractAlertCondition.Type type, Stream stream, String id, DateTime createdAt, String creatorId, Map<String, Object> parameters) throws AbstractAlertCondition.NoSuchAlertConditionTypeException { switch (type) { case MESSAGE_COUNT: return messageCountAlertFactory.createAlertCondition(stream, id, createdAt, creatorId, parameters); case FIELD_VALUE: return fieldValueAlertFactory.createAlertCondition(stream, id, createdAt, creatorId, parameters); } throw new AbstractAlertCondition.NoSuchAlertConditionTypeException( "Unhandled alert condition type: " + type); } @Override public AbstractAlertCondition fromRequest(CreateConditionRequest ccr, Stream stream, String userId) throws AbstractAlertCondition.NoSuchAlertConditionTypeException { AbstractAlertCondition.Type type; try { type = AbstractAlertCondition.Type.valueOf(ccr.type().toUpperCase()); } catch (IllegalArgumentException e) { throw new AbstractAlertCondition.NoSuchAlertConditionTypeException( "No such alert condition type: [" + ccr.type() + "]"); } Map<String, Object> parameters = ccr.parameters(); return createAlertCondition(type, stream, null, Tools.iso8601(), userId, parameters); } @Override public AbstractAlertCondition updateFromRequest(AlertCondition alertCondition, CreateConditionRequest ccr) throws AbstractAlertCondition.NoSuchAlertConditionTypeException { AbstractAlertCondition.Type type = ((AbstractAlertCondition) alertCondition).getType(); Map<String, Object> parameters = ccr.parameters(); for (Map.Entry<String, Object> stringObjectEntry : alertCondition.getParameters().entrySet()) { if (!parameters.containsKey(stringObjectEntry.getKey())) { parameters.put(stringObjectEntry.getKey(), stringObjectEntry.getValue()); } } return createAlertCondition(type, alertCondition.getStream(), alertCondition.getId(), alertCondition.getCreatedAt(), alertCondition.getCreatorUserId(), parameters); } @Override public boolean inGracePeriod(AlertCondition alertCondition) { int lastAlertSecondsAgo = triggeredSecondsAgo(alertCondition.getStream().getId(), alertCondition.getId()); if (lastAlertSecondsAgo == -1 || alertCondition.getGrace() == 0) { return false; } return lastAlertSecondsAgo < alertCondition.getGrace() * 60; } @Override public AlertCondition.CheckResult triggeredNoGrace(AlertCondition alertCondition) { LOG.debug("Checking alert condition [{}] and not accounting grace time.", this); return ((AbstractAlertCondition) alertCondition).runCheck(); } @Override public AlertCondition.CheckResult triggered(AlertCondition alertCondition) { LOG.debug("Checking alert condition [{}]", this); if (inGracePeriod(alertCondition)) { LOG.debug("Alert condition [{}] is in grace period. Not triggered.", this); return new AbstractAlertCondition.CheckResult(false); } return ((AbstractAlertCondition) alertCondition).runCheck(); } @Override public Map<String, Object> asMap(final AlertCondition alertCondition) { return ImmutableMap.<String, Object>builder().put("id", alertCondition.getId()) .put("type", alertCondition.getTypeString().toLowerCase()) .put("creator_user_id", alertCondition.getCreatorUserId()) .put("created_at", Tools.getISO8601String(alertCondition.getCreatedAt())) .put("parameters", alertCondition.getParameters()).put("in_grace", inGracePeriod(alertCondition)) .build(); } }