mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-07-26 19:00:02 +00:00
Created ActivityFeed Alert (#9339)
This commit is contained in:
parent
fc60098e84
commit
b762593652
@ -1,7 +1,5 @@
|
|||||||
package org.openmetadata.service.alerts;
|
package org.openmetadata.service.alerts;
|
||||||
|
|
||||||
import static org.openmetadata.service.security.policyevaluator.CompiledRule.parseExpression;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -10,7 +8,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.openmetadata.schema.entity.alerts.Alert;
|
import org.openmetadata.schema.entity.alerts.Alert;
|
||||||
import org.openmetadata.schema.entity.alerts.AlertAction;
|
import org.openmetadata.schema.entity.alerts.AlertAction;
|
||||||
import org.openmetadata.schema.entity.alerts.AlertFilterRule;
|
|
||||||
import org.openmetadata.schema.entity.alerts.TriggerConfig;
|
import org.openmetadata.schema.entity.alerts.TriggerConfig;
|
||||||
import org.openmetadata.schema.filter.EventFilter;
|
import org.openmetadata.schema.filter.EventFilter;
|
||||||
import org.openmetadata.schema.filter.Filters;
|
import org.openmetadata.schema.filter.Filters;
|
||||||
@ -21,8 +18,6 @@ import org.openmetadata.service.events.EventPublisher;
|
|||||||
import org.openmetadata.service.events.errors.RetriableException;
|
import org.openmetadata.service.events.errors.RetriableException;
|
||||||
import org.openmetadata.service.resources.events.EventResource.ChangeEventList;
|
import org.openmetadata.service.resources.events.EventResource.ChangeEventList;
|
||||||
import org.openmetadata.service.util.FilterUtil;
|
import org.openmetadata.service.util.FilterUtil;
|
||||||
import org.springframework.expression.Expression;
|
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class AbstractAlertPublisher implements EventPublisher {
|
public abstract class AbstractAlertPublisher implements EventPublisher {
|
||||||
@ -74,7 +69,7 @@ public abstract class AbstractAlertPublisher implements EventPublisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate ChangeEvent Alert Filtering
|
// Evaluate ChangeEvent Alert Filtering
|
||||||
if (!evaluateAlertConditions(changeEvent)) {
|
if (!AlertUtil.evaluateAlertConditions(changeEvent, alert.getFilteringRules())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,20 +115,4 @@ public abstract class AbstractAlertPublisher implements EventPublisher {
|
|||||||
return filter.isEmpty() || FilterUtil.shouldProcessRequest(changeEvent, filter);
|
return filter.isEmpty() || FilterUtil.shouldProcessRequest(changeEvent, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean evaluateAlertConditions(ChangeEvent changeEvent) {
|
|
||||||
boolean result = false;
|
|
||||||
for (AlertFilterRule rule : alert.getFilteringRules()) {
|
|
||||||
AlertsRuleEvaluator ruleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
|
||||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(ruleEvaluator);
|
|
||||||
Expression expression = parseExpression(rule.getCondition());
|
|
||||||
if (rule.getEffect() == AlertFilterRule.Effect.ALLOW) {
|
|
||||||
result = Boolean.TRUE.equals(expression.getValue(evaluationContext, Boolean.class));
|
|
||||||
} else if (rule.getEffect() == AlertFilterRule.Effect.DENY) {
|
|
||||||
result = Boolean.FALSE.equals(expression.getValue(evaluationContext, Boolean.class));
|
|
||||||
}
|
|
||||||
LOG.debug("Alert evaluated as Result : {}", result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package org.openmetadata.service.alerts;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.openmetadata.schema.entity.alerts.Alert;
|
||||||
|
import org.openmetadata.service.exception.EntityNotFoundException;
|
||||||
|
import org.openmetadata.service.jdbi3.AlertRepository;
|
||||||
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class ActivityFeedAlertCache {
|
||||||
|
private static final ActivityFeedAlertCache INSTANCE = new ActivityFeedAlertCache();
|
||||||
|
private static volatile boolean INITIALIZED = false;
|
||||||
|
protected static LoadingCache<String, Alert> ALERTS_CACHE;
|
||||||
|
protected static AlertRepository ALERT_REPOSITORY;
|
||||||
|
private static String activityFeedAlertName;
|
||||||
|
|
||||||
|
public static void initialize(String alertName, CollectionDAO dao) {
|
||||||
|
if (!INITIALIZED) {
|
||||||
|
ALERTS_CACHE =
|
||||||
|
CacheBuilder.newBuilder()
|
||||||
|
.maximumSize(1000)
|
||||||
|
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||||
|
.build(new ActivityFeedAlertCache.ActivityFeedAlertLoader());
|
||||||
|
ALERT_REPOSITORY = new AlertRepository(dao);
|
||||||
|
INITIALIZED = true;
|
||||||
|
activityFeedAlertName = alertName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActivityFeedAlertCache getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Alert getActivityFeedAlert() throws EntityNotFoundException {
|
||||||
|
try {
|
||||||
|
return ALERTS_CACHE.get(activityFeedAlertName);
|
||||||
|
} catch (ExecutionException | UncheckedExecutionException ex) {
|
||||||
|
throw new EntityNotFoundException(ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ActivityFeedAlertLoader extends CacheLoader<String, Alert> {
|
||||||
|
@Override
|
||||||
|
public Alert load(@CheckForNull String alertName) throws IOException {
|
||||||
|
Alert alert = ALERT_REPOSITORY.getByName(null, alertName, ALERT_REPOSITORY.getFields("*"));
|
||||||
|
LOG.debug("Loaded Alert {}", alert);
|
||||||
|
return alert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,9 @@ import java.util.stream.Stream;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.openmetadata.schema.entity.alerts.Alert;
|
import org.openmetadata.schema.entity.alerts.Alert;
|
||||||
import org.openmetadata.schema.entity.alerts.AlertAction;
|
import org.openmetadata.schema.entity.alerts.AlertAction;
|
||||||
|
import org.openmetadata.schema.entity.alerts.AlertFilterRule;
|
||||||
import org.openmetadata.schema.tests.type.TestCaseStatus;
|
import org.openmetadata.schema.tests.type.TestCaseStatus;
|
||||||
|
import org.openmetadata.schema.type.ChangeEvent;
|
||||||
import org.openmetadata.schema.type.EventType;
|
import org.openmetadata.schema.type.EventType;
|
||||||
import org.openmetadata.schema.type.Function;
|
import org.openmetadata.schema.type.Function;
|
||||||
import org.openmetadata.schema.type.ParamAdditionalContext;
|
import org.openmetadata.schema.type.ParamAdditionalContext;
|
||||||
@ -28,6 +30,7 @@ import org.openmetadata.service.exception.CatalogExceptionMessage;
|
|||||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
import org.openmetadata.service.resources.CollectionRegistry;
|
import org.openmetadata.service.resources.CollectionRegistry;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AlertUtil {
|
public class AlertUtil {
|
||||||
@ -48,6 +51,8 @@ public class AlertUtil {
|
|||||||
case EMAIL:
|
case EMAIL:
|
||||||
publisher = new EmailAlertPublisher(alert, alertAction, daoCollection);
|
publisher = new EmailAlertPublisher(alert, alertAction, daoCollection);
|
||||||
break;
|
break;
|
||||||
|
case ACTIVITY_FEED:
|
||||||
|
throw new IllegalArgumentException("Cannot create Activity Feed as Publisher.");
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid Alert Action Specified.");
|
throw new IllegalArgumentException("Invalid Alert Action Specified.");
|
||||||
}
|
}
|
||||||
@ -112,4 +117,20 @@ public class AlertUtil {
|
|||||||
}
|
}
|
||||||
return indexesToSearch;
|
return indexesToSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean evaluateAlertConditions(ChangeEvent changeEvent, List<AlertFilterRule> alertFilterRules) {
|
||||||
|
boolean result = false;
|
||||||
|
for (AlertFilterRule rule : alertFilterRules) {
|
||||||
|
AlertsRuleEvaluator ruleEvaluator = new AlertsRuleEvaluator(changeEvent);
|
||||||
|
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(ruleEvaluator);
|
||||||
|
Expression expression = parseExpression(rule.getCondition());
|
||||||
|
if (rule.getEffect() == AlertFilterRule.Effect.ALLOW) {
|
||||||
|
result = Boolean.TRUE.equals(expression.getValue(evaluationContext, Boolean.class));
|
||||||
|
} else if (rule.getEffect() == AlertFilterRule.Effect.DENY) {
|
||||||
|
result = Boolean.FALSE.equals(expression.getValue(evaluationContext, Boolean.class));
|
||||||
|
}
|
||||||
|
LOG.debug("Alert evaluated as Result : {}", result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ import org.openmetadata.schema.type.EntityReference;
|
|||||||
import org.openmetadata.schema.type.EventType;
|
import org.openmetadata.schema.type.EventType;
|
||||||
import org.openmetadata.service.Entity;
|
import org.openmetadata.service.Entity;
|
||||||
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
||||||
import org.openmetadata.service.filter.FilterRegistry;
|
|
||||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
import org.openmetadata.service.jdbi3.FeedRepository;
|
import org.openmetadata.service.jdbi3.FeedRepository;
|
||||||
import org.openmetadata.service.resources.feeds.MessageParser.EntityLink;
|
import org.openmetadata.service.resources.feeds.MessageParser.EntityLink;
|
||||||
@ -69,7 +68,7 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
String loggedInUserName = securityContext.getUserPrincipal().getName();
|
String loggedInUserName = securityContext.getUserPrincipal().getName();
|
||||||
try {
|
try {
|
||||||
notificationHandler.processNotifications(responseContext);
|
notificationHandler.processNotifications(responseContext);
|
||||||
ChangeEvent changeEvent = getChangeEvent(method, responseContext);
|
ChangeEvent changeEvent = getChangeEvent(loggedInUserName, method, responseContext);
|
||||||
if (changeEvent == null) {
|
if (changeEvent == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -92,7 +91,7 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
if (Entity.shouldDisplayEntityChangeOnFeed(changeEvent.getEntityType())) {
|
if (Entity.shouldDisplayEntityChangeOnFeed(changeEvent.getEntityType())) {
|
||||||
// ignore usageSummary updates in the feed
|
// ignore usageSummary updates in the feed
|
||||||
boolean filterEnabled;
|
boolean filterEnabled;
|
||||||
filterEnabled = FilterUtil.shouldProcessRequest(changeEvent, FilterRegistry.getAllFilters());
|
filterEnabled = FilterUtil.shouldProcessRequest(changeEvent);
|
||||||
if (filterEnabled) {
|
if (filterEnabled) {
|
||||||
for (Thread thread : listOrEmpty(getThreads(responseContext, loggedInUserName))) {
|
for (Thread thread : listOrEmpty(getThreads(responseContext, loggedInUserName))) {
|
||||||
// Don't create a thread if there is no message
|
// Don't create a thread if there is no message
|
||||||
@ -126,7 +125,7 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangeEvent getChangeEvent(String method, ContainerResponseContext responseContext) {
|
public ChangeEvent getChangeEvent(String updateBy, String method, ContainerResponseContext responseContext) {
|
||||||
// GET operations don't produce change events
|
// GET operations don't produce change events
|
||||||
if (method.equals("GET")) {
|
if (method.equals("GET")) {
|
||||||
return null;
|
return null;
|
||||||
@ -147,7 +146,7 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
EntityReference entityReference = entityInterface.getEntityReference();
|
EntityReference entityReference = entityInterface.getEntityReference();
|
||||||
String entityType = entityReference.getType();
|
String entityType = entityReference.getType();
|
||||||
String entityFQN = entityReference.getFullyQualifiedName();
|
String entityFQN = entityReference.getFullyQualifiedName();
|
||||||
return getChangeEvent(EventType.ENTITY_CREATED, entityType, entityInterface)
|
return getChangeEvent(updateBy, EventType.ENTITY_CREATED, entityType, entityInterface)
|
||||||
.withEntity(entityInterface)
|
.withEntity(entityInterface)
|
||||||
.withEntityFullyQualifiedName(entityFQN);
|
.withEntityFullyQualifiedName(entityFQN);
|
||||||
}
|
}
|
||||||
@ -171,7 +170,7 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
eventType = ENTITY_SOFT_DELETED;
|
eventType = ENTITY_SOFT_DELETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getChangeEvent(eventType, entityType, entityInterface)
|
return getChangeEvent(updateBy, eventType, entityType, entityInterface)
|
||||||
.withPreviousVersion(entityInterface.getChangeDescription().getPreviousVersion())
|
.withPreviousVersion(entityInterface.getChangeDescription().getPreviousVersion())
|
||||||
.withEntity(entityInterface)
|
.withEntity(entityInterface)
|
||||||
.withEntityFullyQualifiedName(entityFQN);
|
.withEntityFullyQualifiedName(entityFQN);
|
||||||
@ -188,7 +187,7 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
EntityReference entityReference = entityInterface.getEntityReference();
|
EntityReference entityReference = entityInterface.getEntityReference();
|
||||||
String entityType = entityReference.getType();
|
String entityType = entityReference.getType();
|
||||||
String entityFQN = entityReference.getFullyQualifiedName();
|
String entityFQN = entityReference.getFullyQualifiedName();
|
||||||
return getChangeEvent(ENTITY_DELETED, entityType, entityInterface)
|
return getChangeEvent(updateBy, ENTITY_DELETED, entityType, entityInterface)
|
||||||
.withPreviousVersion(entityInterface.getVersion())
|
.withPreviousVersion(entityInterface.getVersion())
|
||||||
.withEntity(entityInterface)
|
.withEntity(entityInterface)
|
||||||
.withEntityFullyQualifiedName(entityFQN);
|
.withEntityFullyQualifiedName(entityFQN);
|
||||||
@ -196,12 +195,13 @@ public class ChangeEventHandler implements EventHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ChangeEvent getChangeEvent(EventType eventType, String entityType, EntityInterface entityInterface) {
|
private static ChangeEvent getChangeEvent(
|
||||||
|
String updateBy, EventType eventType, String entityType, EntityInterface entityInterface) {
|
||||||
return new ChangeEvent()
|
return new ChangeEvent()
|
||||||
.withEventType(eventType)
|
.withEventType(eventType)
|
||||||
.withEntityId(entityInterface.getId())
|
.withEntityId(entityInterface.getId())
|
||||||
.withEntityType(entityType)
|
.withEntityType(entityType)
|
||||||
.withUserName(entityInterface.getUpdatedBy())
|
.withUserName(updateBy)
|
||||||
.withTimestamp(entityInterface.getUpdatedAt())
|
.withTimestamp(entityInterface.getUpdatedAt())
|
||||||
.withChangeDescription(entityInterface.getChangeDescription())
|
.withChangeDescription(entityInterface.getChangeDescription())
|
||||||
.withCurrentVersion(entityInterface.getVersion());
|
.withCurrentVersion(entityInterface.getVersion());
|
||||||
|
@ -18,16 +18,19 @@ import java.util.concurrent.ForkJoinPool;
|
|||||||
import javax.ws.rs.container.ContainerRequestContext;
|
import javax.ws.rs.container.ContainerRequestContext;
|
||||||
import javax.ws.rs.container.ContainerResponseContext;
|
import javax.ws.rs.container.ContainerResponseContext;
|
||||||
import javax.ws.rs.container.ContainerResponseFilter;
|
import javax.ws.rs.container.ContainerResponseFilter;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
import javax.ws.rs.ext.Provider;
|
import javax.ws.rs.ext.Provider;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jdbi.v3.core.Jdbi;
|
import org.jdbi.v3.core.Jdbi;
|
||||||
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
||||||
|
import org.openmetadata.service.security.JwtFilter;
|
||||||
import org.openmetadata.service.util.ParallelStreamUtil;
|
import org.openmetadata.service.util.ParallelStreamUtil;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Provider
|
@Provider
|
||||||
public class EventFilter implements ContainerResponseFilter {
|
public class EventFilter implements ContainerResponseFilter {
|
||||||
private static final List<String> AUDITABLE_METHODS = Arrays.asList("POST", "PUT", "PATCH", "DELETE");
|
private static final List<String> AUDITABLE_METHODS = Arrays.asList("POST", "PUT", "PATCH", "DELETE");
|
||||||
|
|
||||||
private static final int FORK_JOIN_POOL_PARALLELISM = 20;
|
private static final int FORK_JOIN_POOL_PARALLELISM = 20;
|
||||||
private final ForkJoinPool forkJoinPool;
|
private final ForkJoinPool forkJoinPool;
|
||||||
private final List<EventHandler> eventHandlers;
|
private final List<EventHandler> eventHandlers;
|
||||||
@ -65,7 +68,11 @@ public class EventFilter implements ContainerResponseFilter {
|
|||||||
eventHandlers
|
eventHandlers
|
||||||
.parallelStream()
|
.parallelStream()
|
||||||
.forEach(
|
.forEach(
|
||||||
eventHandler ->
|
(eventHandler) -> {
|
||||||
ParallelStreamUtil.runAsync(() -> eventHandler.process(requestContext, responseContext), forkJoinPool));
|
UriInfo uriInfo = requestContext.getUriInfo();
|
||||||
|
if (JwtFilter.EXCLUDED_ENDPOINTS.stream().noneMatch(endpoint -> uriInfo.getPath().contains(endpoint))) {
|
||||||
|
ParallelStreamUtil.runAsync(() -> eventHandler.process(requestContext, responseContext), forkJoinPool);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,18 +13,15 @@
|
|||||||
|
|
||||||
package org.openmetadata.service.filter;
|
package org.openmetadata.service.filter;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import org.openmetadata.schema.entity.alerts.Alert;
|
||||||
import org.openmetadata.schema.filter.EventFilter;
|
import org.openmetadata.schema.filter.EventFilter;
|
||||||
import org.openmetadata.schema.filter.Filters;
|
import org.openmetadata.schema.filter.Filters;
|
||||||
import org.openmetadata.schema.settings.Settings;
|
|
||||||
import org.openmetadata.schema.type.EventType;
|
import org.openmetadata.schema.type.EventType;
|
||||||
import org.openmetadata.service.resources.settings.SettingsCache;
|
import org.openmetadata.service.alerts.ActivityFeedAlertCache;
|
||||||
import org.openmetadata.service.util.FilterUtil;
|
|
||||||
|
|
||||||
public class FilterRegistry {
|
public class FilterRegistry {
|
||||||
private static final ConcurrentHashMap<String, Map<EventType, Filters>> FILTERS_MAP = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<String, Map<EventType, Filters>> FILTERS_MAP = new ConcurrentHashMap<>();
|
||||||
@ -47,23 +44,9 @@ public class FilterRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Map<EventType, Filters>> listAllFilters() {
|
public static Map<String, Map<EventType, Filters>> getAllFilters() {
|
||||||
List<Map<EventType, Filters>> filterList = new ArrayList<>();
|
Alert alert = ActivityFeedAlertCache.getInstance().getActivityFeedAlert();
|
||||||
FILTERS_MAP.forEach((key, value) -> filterList.add(value));
|
add(alert.getTriggerConfig().getEventFilters());
|
||||||
return filterList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> listAllEntitiesHavingFilter() {
|
|
||||||
return List.copyOf(FILTERS_MAP.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<EventType, Filters> getFilterForEntity(String key) {
|
|
||||||
return FILTERS_MAP.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<String, Map<EventType, Filters>> getAllFilters() throws IOException {
|
|
||||||
Settings settings = SettingsCache.getInstance().getEventFilters();
|
|
||||||
add(FilterUtil.getEventFilterFromSettings(settings));
|
|
||||||
return FILTERS_MAP;
|
return FILTERS_MAP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.json.JsonPatch;
|
import javax.json.JsonPatch;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@ -45,16 +46,21 @@ import javax.ws.rs.core.Response;
|
|||||||
import javax.ws.rs.core.SecurityContext;
|
import javax.ws.rs.core.SecurityContext;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.openmetadata.common.utils.CommonUtil;
|
||||||
import org.openmetadata.schema.api.events.CreateAlertAction;
|
import org.openmetadata.schema.api.events.CreateAlertAction;
|
||||||
import org.openmetadata.schema.entity.alerts.AlertAction;
|
import org.openmetadata.schema.entity.alerts.AlertAction;
|
||||||
import org.openmetadata.schema.type.EntityHistory;
|
import org.openmetadata.schema.type.EntityHistory;
|
||||||
import org.openmetadata.schema.type.Include;
|
import org.openmetadata.schema.type.Include;
|
||||||
|
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
||||||
import org.openmetadata.service.jdbi3.AlertActionRepository;
|
import org.openmetadata.service.jdbi3.AlertActionRepository;
|
||||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
import org.openmetadata.service.jdbi3.ListFilter;
|
import org.openmetadata.service.jdbi3.ListFilter;
|
||||||
import org.openmetadata.service.resources.Collection;
|
import org.openmetadata.service.resources.Collection;
|
||||||
import org.openmetadata.service.resources.EntityResource;
|
import org.openmetadata.service.resources.EntityResource;
|
||||||
|
import org.openmetadata.service.resources.policies.PolicyResource;
|
||||||
import org.openmetadata.service.security.Authorizer;
|
import org.openmetadata.service.security.Authorizer;
|
||||||
|
import org.openmetadata.service.util.EntityUtil;
|
||||||
|
import org.openmetadata.service.util.JsonUtils;
|
||||||
import org.openmetadata.service.util.ResultList;
|
import org.openmetadata.service.util.ResultList;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -62,7 +68,7 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Api(value = "Alerts collection", tags = "Alerts collection")
|
@Api(value = "Alerts collection", tags = "Alerts collection")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Collection(name = "alertAction", order = 7) // init befoe Alert Resource Init
|
@Collection(name = "alertAction", order = 7) // init before Alert Resource Init
|
||||||
public class AlertActionResource extends EntityResource<AlertAction, AlertActionRepository> {
|
public class AlertActionResource extends EntityResource<AlertAction, AlertActionRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/alertAction/";
|
public static final String COLLECTION_PATH = "v1/alertAction/";
|
||||||
|
|
||||||
@ -81,6 +87,28 @@ public class AlertActionResource extends EntityResource<AlertAction, AlertAction
|
|||||||
public AlertActionList() {}
|
public AlertActionList() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(OpenMetadataApplicationConfig config) throws IOException {
|
||||||
|
initDefaultAlertActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDefaultAlertActions() throws IOException {
|
||||||
|
List<String> jsonDataFiles = EntityUtil.getJsonDataResources(".*json/data/alerts/alertsActionData.json$");
|
||||||
|
if (jsonDataFiles.size() != 1) {
|
||||||
|
LOG.warn("Invalid number of jsonDataFiles {}. Only one expected.", jsonDataFiles.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String jsonDataFile = jsonDataFiles.get(0);
|
||||||
|
try {
|
||||||
|
String json = CommonUtil.getResourceAsStream(PolicyResource.class.getClassLoader(), jsonDataFile);
|
||||||
|
// Assumes to have 1 entry currently
|
||||||
|
AlertAction alertActions = JsonUtils.readObjects(json, AlertAction.class).get(0);
|
||||||
|
dao.initializeEntity(alertActions);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Failed to initialize the resource descriptors from file {}", jsonDataFile, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Operation(
|
@Operation(
|
||||||
operationId = "listAlertActions",
|
operationId = "listAlertActions",
|
||||||
|
@ -52,19 +52,24 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.openmetadata.common.utils.CommonUtil;
|
import org.openmetadata.common.utils.CommonUtil;
|
||||||
import org.openmetadata.schema.api.events.CreateAlert;
|
import org.openmetadata.schema.api.events.CreateAlert;
|
||||||
import org.openmetadata.schema.entity.alerts.Alert;
|
import org.openmetadata.schema.entity.alerts.Alert;
|
||||||
|
import org.openmetadata.schema.entity.alerts.AlertAction;
|
||||||
import org.openmetadata.schema.entity.alerts.AlertActionStatus;
|
import org.openmetadata.schema.entity.alerts.AlertActionStatus;
|
||||||
import org.openmetadata.schema.entity.alerts.EntitySpelFilters;
|
import org.openmetadata.schema.entity.alerts.EntitySpelFilters;
|
||||||
import org.openmetadata.schema.entity.alerts.TriggerConfig;
|
import org.openmetadata.schema.entity.alerts.TriggerConfig;
|
||||||
import org.openmetadata.schema.type.EntityHistory;
|
import org.openmetadata.schema.type.EntityHistory;
|
||||||
import org.openmetadata.schema.type.Function;
|
import org.openmetadata.schema.type.Function;
|
||||||
import org.openmetadata.schema.type.Include;
|
import org.openmetadata.schema.type.Include;
|
||||||
|
import org.openmetadata.service.Entity;
|
||||||
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
import org.openmetadata.service.OpenMetadataApplicationConfig;
|
||||||
|
import org.openmetadata.service.alerts.ActivityFeedAlertCache;
|
||||||
import org.openmetadata.service.alerts.AlertUtil;
|
import org.openmetadata.service.alerts.AlertUtil;
|
||||||
import org.openmetadata.service.jdbi3.AlertRepository;
|
import org.openmetadata.service.jdbi3.AlertRepository;
|
||||||
import org.openmetadata.service.jdbi3.CollectionDAO;
|
import org.openmetadata.service.jdbi3.CollectionDAO;
|
||||||
|
import org.openmetadata.service.jdbi3.EntityRepository;
|
||||||
import org.openmetadata.service.jdbi3.ListFilter;
|
import org.openmetadata.service.jdbi3.ListFilter;
|
||||||
import org.openmetadata.service.resources.Collection;
|
import org.openmetadata.service.resources.Collection;
|
||||||
import org.openmetadata.service.resources.EntityResource;
|
import org.openmetadata.service.resources.EntityResource;
|
||||||
|
import org.openmetadata.service.resources.policies.PolicyResource;
|
||||||
import org.openmetadata.service.resources.settings.SettingsResource;
|
import org.openmetadata.service.resources.settings.SettingsResource;
|
||||||
import org.openmetadata.service.security.Authorizer;
|
import org.openmetadata.service.security.Authorizer;
|
||||||
import org.openmetadata.service.util.EntityUtil;
|
import org.openmetadata.service.util.EntityUtil;
|
||||||
@ -79,12 +84,12 @@ import org.openmetadata.service.util.ResultList;
|
|||||||
@Collection(name = "alerts", order = 8) // init after alertAction Resource
|
@Collection(name = "alerts", order = 8) // init after alertAction Resource
|
||||||
public class AlertResource extends EntityResource<Alert, AlertRepository> {
|
public class AlertResource extends EntityResource<Alert, AlertRepository> {
|
||||||
public static final String COLLECTION_PATH = "v1/alerts/";
|
public static final String COLLECTION_PATH = "v1/alerts/";
|
||||||
private final CollectionDAO.AlertDAO alertDAO;
|
private final CollectionDAO daoCollection;
|
||||||
private List<TriggerConfig> bootStrappedFilters = new ArrayList<>();
|
private List<TriggerConfig> bootStrappedFilters = new ArrayList<>();
|
||||||
private Map<String, EntitySpelFilters> entitySpelFiltersList = new HashMap<>();
|
private final Map<String, EntitySpelFilters> entitySpelFiltersList = new HashMap<>();
|
||||||
static final String FIELDS = "triggerConfig,filteringRules,alertActions";
|
static final String FIELDS = "triggerConfig,filteringRules,alertActions";
|
||||||
|
|
||||||
private void initDefaultTriggersSettings() throws IOException {
|
private void initAlerts() throws IOException {
|
||||||
// Load Trigger File
|
// Load Trigger File
|
||||||
List<String> triggerDataFiles = EntityUtil.getJsonDataResources(".*json/data/alerts/triggerData.json$");
|
List<String> triggerDataFiles = EntityUtil.getJsonDataResources(".*json/data/alerts/triggerData.json$");
|
||||||
if (triggerDataFiles.size() != 1) {
|
if (triggerDataFiles.size() != 1) {
|
||||||
@ -109,13 +114,44 @@ public class AlertResource extends EntityResource<Alert, AlertRepository> {
|
|||||||
try {
|
try {
|
||||||
String json = CommonUtil.getResourceAsStream(getClass().getClassLoader(), filterDataFile);
|
String json = CommonUtil.getResourceAsStream(getClass().getClassLoader(), filterDataFile);
|
||||||
List<EntitySpelFilters> filters = JsonUtils.readObjects(json, EntitySpelFilters.class);
|
List<EntitySpelFilters> filters = JsonUtils.readObjects(json, EntitySpelFilters.class);
|
||||||
filters.forEach(
|
filters.forEach((spelFilter) -> entitySpelFiltersList.put(spelFilter.getEntityType(), spelFilter));
|
||||||
(spelFilter) -> {
|
|
||||||
entitySpelFiltersList.put(spelFilter.getEntityType(), spelFilter);
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Failed to initialize the {} from file {}", "filters", filterDataFile, e);
|
LOG.warn("Failed to initialize the {} from file {}", "filters", filterDataFile, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize Alert For ActivityFeed, this does not have any publisher since it is for internal system filtering
|
||||||
|
List<String> alertFile = EntityUtil.getJsonDataResources(".*json/data/alerts/alertsData.json$");
|
||||||
|
List<String> alertActionFile = EntityUtil.getJsonDataResources(".*json/data/alerts/alertsActionData.json$");
|
||||||
|
String alertDataFile = alertFile.get(0);
|
||||||
|
String alertActionDataFile = alertActionFile.get(0);
|
||||||
|
Alert activityFeedAlert = null;
|
||||||
|
try {
|
||||||
|
String actionJson = CommonUtil.getResourceAsStream(PolicyResource.class.getClassLoader(), alertActionDataFile);
|
||||||
|
// Assumes to have 1 entry currently
|
||||||
|
AlertAction alertActions = JsonUtils.readObjects(actionJson, AlertAction.class).get(0);
|
||||||
|
|
||||||
|
String alertJson = CommonUtil.getResourceAsStream(getClass().getClassLoader(), alertDataFile);
|
||||||
|
activityFeedAlert = JsonUtils.readObjects(alertJson, Alert.class).get(0);
|
||||||
|
// populate alert actions
|
||||||
|
EntityRepository<AlertAction> actionEntityRepository = Entity.getEntityRepository(Entity.ALERT_ACTION);
|
||||||
|
AlertAction action =
|
||||||
|
actionEntityRepository.getByName(null, alertActions.getName(), actionEntityRepository.getFields("id"));
|
||||||
|
activityFeedAlert.setAlertActions(List.of(action.getEntityReference()));
|
||||||
|
dao.initializeEntity(activityFeedAlert);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Failed to initialize the {} from file {}", "filters", alertDataFile, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init Publishers
|
||||||
|
ActivityFeedAlertCache.initialize(activityFeedAlert.getName(), daoCollection);
|
||||||
|
// Create Publishers
|
||||||
|
List<String> listAllAlerts = daoCollection.alertDAO().listAllAlerts(daoCollection.alertDAO().getTableName());
|
||||||
|
List<Alert> alertList = JsonUtils.readObjects(listAllAlerts, Alert.class);
|
||||||
|
for (Alert alert : alertList) {
|
||||||
|
if (alert.getName().equals(activityFeedAlert.getName())) {
|
||||||
|
dao.addAlertActionPublishers(alert);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -125,7 +161,7 @@ public class AlertResource extends EntityResource<Alert, AlertRepository> {
|
|||||||
|
|
||||||
public AlertResource(CollectionDAO dao, Authorizer authorizer) {
|
public AlertResource(CollectionDAO dao, Authorizer authorizer) {
|
||||||
super(Alert.class, new AlertRepository(dao), authorizer);
|
super(Alert.class, new AlertRepository(dao), authorizer);
|
||||||
alertDAO = dao.alertDAO();
|
daoCollection = dao;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AlertList extends ResultList<Alert> {
|
public static class AlertList extends ResultList<Alert> {
|
||||||
@ -137,12 +173,7 @@ public class AlertResource extends EntityResource<Alert, AlertRepository> {
|
|||||||
@Override
|
@Override
|
||||||
public void initialize(OpenMetadataApplicationConfig config) {
|
public void initialize(OpenMetadataApplicationConfig config) {
|
||||||
try {
|
try {
|
||||||
List<String> listAllAlerts = alertDAO.listAllAlerts(alertDAO.getTableName());
|
initAlerts();
|
||||||
List<Alert> alertList = JsonUtils.readObjects(listAllAlerts, Alert.class);
|
|
||||||
for (Alert alert : alertList) {
|
|
||||||
dao.addAlertActionPublishers(alert);
|
|
||||||
}
|
|
||||||
initDefaultTriggersSettings();
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// Starting application should not fail
|
// Starting application should not fail
|
||||||
LOG.warn("Exception during initialization", ex);
|
LOG.warn("Exception during initialization", ex);
|
||||||
|
@ -32,6 +32,9 @@ import org.openmetadata.schema.type.ChangeEvent;
|
|||||||
import org.openmetadata.schema.type.EventType;
|
import org.openmetadata.schema.type.EventType;
|
||||||
import org.openmetadata.schema.type.FieldChange;
|
import org.openmetadata.schema.type.FieldChange;
|
||||||
import org.openmetadata.service.Entity;
|
import org.openmetadata.service.Entity;
|
||||||
|
import org.openmetadata.service.alerts.ActivityFeedAlertCache;
|
||||||
|
import org.openmetadata.service.alerts.AlertUtil;
|
||||||
|
import org.openmetadata.service.filter.FilterRegistry;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FilterUtil {
|
public class FilterUtil {
|
||||||
@ -65,6 +68,19 @@ public class FilterUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean shouldProcessRequest(ChangeEvent event) {
|
||||||
|
// Check Trigger Conditions
|
||||||
|
if (!shouldProcessRequest(event, FilterRegistry.getAllFilters())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check Spel Conditions
|
||||||
|
if (!AlertUtil.evaluateAlertConditions(
|
||||||
|
event, ActivityFeedAlertCache.getInstance().getActivityFeedAlert().getFilteringRules())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean handleTestCaseFilter(ChangeEvent changeEvent, Filters sf) {
|
private static boolean handleTestCaseFilter(ChangeEvent changeEvent, Filters sf) {
|
||||||
List<FieldChange> fieldChanges = getAllFieldChange(changeEvent);
|
List<FieldChange> fieldChanges = getAllFieldChange(changeEvent);
|
||||||
for (FieldChange fieldChange : fieldChanges) {
|
for (FieldChange fieldChange : fieldChanges) {
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "ActivityFeedAlertAction",
|
||||||
|
"enabled": "true",
|
||||||
|
"alertActionType": "ActivityFeed",
|
||||||
|
"alertActionConfig": {
|
||||||
|
"name": "ActivityFeedAlertAction",
|
||||||
|
"description": "Controls the Activity Displayed on the Feeds Page"
|
||||||
|
},
|
||||||
|
"provider" : "system"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,232 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "ActivityFeedAlert",
|
||||||
|
"triggerConfig": {
|
||||||
|
"type": "EntitySpecific",
|
||||||
|
"eventFilters": [
|
||||||
|
{
|
||||||
|
"entityType": "all",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"eventType": "entityCreated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityUpdated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": ["usageSummary"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entitySoftDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entityType": "table",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"eventType": "entityCreated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityUpdated",
|
||||||
|
"include": [
|
||||||
|
"description",
|
||||||
|
"owner",
|
||||||
|
"tags",
|
||||||
|
"followers",
|
||||||
|
"tableConstraints",
|
||||||
|
"constraint"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entitySoftDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entityType": "dashboard",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"eventType": "entityCreated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityUpdated",
|
||||||
|
"include": [
|
||||||
|
"description",
|
||||||
|
"owner",
|
||||||
|
"tags",
|
||||||
|
"followers"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entitySoftDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entityType": "pipeline",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"eventType": "entityCreated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityUpdated",
|
||||||
|
"include": [
|
||||||
|
"description",
|
||||||
|
"owner",
|
||||||
|
"tags",
|
||||||
|
"followers"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entitySoftDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entityType": "mlmodel",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"eventType": "entityCreated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityUpdated",
|
||||||
|
"include": [
|
||||||
|
"description",
|
||||||
|
"owner",
|
||||||
|
"tags",
|
||||||
|
"followers"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entitySoftDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entityType": "testCase",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"eventType": "entityCreated",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityUpdated",
|
||||||
|
"include": [
|
||||||
|
"testCaseResultSuccess",
|
||||||
|
"testCaseResultFailed",
|
||||||
|
"testCaseResultAborted"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entityDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventType": "entitySoftDeleted",
|
||||||
|
"include": [
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filteringRules": [
|
||||||
|
{
|
||||||
|
"name": "DisableIngestionActivityFeedData",
|
||||||
|
"effect": "allow",
|
||||||
|
"condition": "!matchUpdatedBy('ingestion-bot')"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"provider" : "system"
|
||||||
|
}
|
||||||
|
]
|
@ -14,7 +14,8 @@
|
|||||||
"GenericWebhook",
|
"GenericWebhook",
|
||||||
"SlackWebhook",
|
"SlackWebhook",
|
||||||
"MsTeamsWebhook",
|
"MsTeamsWebhook",
|
||||||
"Email"
|
"Email",
|
||||||
|
"ActivityFeed"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
@ -56,6 +57,21 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
|
"activityFeedAlertActionConfig": {
|
||||||
|
"description": "Activity Feed Alert Action Config",
|
||||||
|
"type": "object",
|
||||||
|
"javaType": "org.openmetadata.schema.entity.alerts.ActivityFeedAlertActionConfig",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "Name",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"description": "Description",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"alertActionStatus": {
|
"alertActionStatus": {
|
||||||
"description": "Alert Action Current Status",
|
"description": "Alert Action Current Status",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -152,6 +168,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "./emailAlertConfig.json"
|
"$ref": "./emailAlertConfig.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/activityFeedAlertActionConfig"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -163,5 +182,7 @@
|
|||||||
"provider" : {
|
"provider" : {
|
||||||
"$ref": "../type/basic.json#/definitions/providerType"
|
"$ref": "../type/basic.json#/definitions/providerType"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"required": ["name", "alertActionType", "alertActionConfig"],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,12 @@
|
|||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"$ref": "../../entity/events/webhook.json"
|
"$ref": "../../entity/events/webhook.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "../emailAlertConfig.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "../alertAction.json#/definitions/activityFeedAlertActionConfig"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user