Update webanalytics prometheus metrics (#9939)

* feature: added web analytic events handler

* feature: exclude web analytic events from audit logger

* empty commit to re-run CI
This commit is contained in:
Teddy 2023-01-27 15:51:53 +01:00 committed by GitHub
parent d5c6c0212b
commit 1455d5eb29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 21 deletions

View File

@ -171,9 +171,9 @@ elasticsearch:
batchSize: ${ELASTICSEARCH_BATCH_SIZE:-10}
searchIndexMappingLanguage: ${ELASTICSEARCH_INDEX_MAPPING_LANG:-EN}
# eventMonitoringConfiguration:
# eventMonitor: ${EVENT_MONITOR:-prometheus} # Possible values are "prometheus", "cloudwatch"
# batchSize: ${EVENT_MONITOR_BATCH_SIZE:-10}
eventMonitoringConfiguration:
eventMonitor: ${EVENT_MONITOR:-prometheus} # Possible values are "prometheus", "cloudwatch"
batchSize: ${EVENT_MONITOR_BATCH_SIZE:-10}
# it will use the default auth provider for AWS services if parameters are not set
# parameters:
# region: ${OM_MONITOR_REGION:-""}
@ -184,6 +184,7 @@ eventHandlerConfiguration:
eventHandlerClassNames:
- "org.openmetadata.service.events.AuditEventHandler"
- "org.openmetadata.service.events.ChangeEventHandler"
- "org.openmetadata.service.events.WebAnalyticEventHandler"
airflowConfiguration:
apiEndpoint: ${AIRFLOW_HOST:-http://localhost:8080}

View File

@ -33,6 +33,10 @@ public class AuditEventHandler implements EventHandler {
}
public Void process(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
if (requestContext.getUriInfo().getPath().contains(WebAnalyticEventHandler.WEB_ANALYTIC_ENDPOINT)) {
// we don't want to send web analytic event to the audit log
return null;
}
int responseCode = responseContext.getStatus();
String method = requestContext.getMethod();
if (responseContext.getEntity() != null) {

View File

@ -30,12 +30,6 @@ import org.openmetadata.service.util.ParallelStreamUtil;
@Provider
public class EventFilter implements ContainerResponseFilter {
private static final List<String> AUDITABLE_METHODS = Arrays.asList("POST", "PUT", "PATCH", "DELETE");
private static List<String> EXCLUDED_ENDPOINTS = new ArrayList<>(JwtFilter.EXCLUDED_ENDPOINTS);
static {
EXCLUDED_ENDPOINTS.add("v1/analytics/webAnalyticEvent/collect");
}
private static final int FORK_JOIN_POOL_PARALLELISM = 20;
private final ForkJoinPool forkJoinPool;
private final List<EventHandler> eventHandlers;
@ -75,7 +69,7 @@ public class EventFilter implements ContainerResponseFilter {
.forEach(
(eventHandler) -> {
UriInfo uriInfo = requestContext.getUriInfo();
if (EXCLUDED_ENDPOINTS.stream().noneMatch(endpoint -> uriInfo.getPath().contains(endpoint))) {
if (JwtFilter.EXCLUDED_ENDPOINTS.stream().noneMatch(endpoint -> uriInfo.getPath().contains(endpoint))) {
ParallelStreamUtil.runAsync(() -> eventHandler.process(requestContext, responseContext), forkJoinPool);
}
});

View File

@ -0,0 +1,47 @@
package org.openmetadata.service.events;
import io.micrometer.core.instrument.Counter;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.core.UriInfo;
import lombok.extern.slf4j.Slf4j;
import org.jdbi.v3.core.Jdbi;
import org.openmetadata.service.OpenMetadataApplicationConfig;
import org.openmetadata.service.util.MicrometerBundleSingleton;
@Slf4j
public class WebAnalyticEventHandler implements EventHandler {
private PrometheusMeterRegistry prometheusMeterRegistry;
private String clusterName;
public static final String WEB_ANALYTIC_ENDPOINT = "v1/analytics/webAnalyticEvent/collect";
private static final String COUNTER_NAME = "web.analytics.events";
public void init(OpenMetadataApplicationConfig config, Jdbi jdbi) {
this.prometheusMeterRegistry = MicrometerBundleSingleton.prometheusMeterRegistry;
this.clusterName = config.getClusterName();
}
public Void process(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
UriInfo uriInfo = requestContext.getUriInfo();
if (uriInfo.getPath().contains(WEB_ANALYTIC_ENDPOINT)) {
String username = "anonymous";
if (requestContext.getSecurityContext().getUserPrincipal() != null) {
username = requestContext.getSecurityContext().getUserPrincipal().getName();
}
incrementMetric(username);
}
return null;
}
private void incrementMetric(String username) {
Counter.builder(COUNTER_NAME)
.tags("clusterName", clusterName, "username", username)
.register(prometheusMeterRegistry)
.increment();
}
public void close() {
prometheusMeterRegistry.close();
}
}

View File

@ -52,7 +52,6 @@ import org.openmetadata.service.resources.Collection;
import org.openmetadata.service.resources.EntityResource;
import org.openmetadata.service.security.Authorizer;
import org.openmetadata.service.security.policyevaluator.OperationContext;
import org.openmetadata.service.util.MicrometerBundleSingleton;
import org.openmetadata.service.util.RestUtil;
import org.openmetadata.service.util.ResultList;
@ -427,15 +426,8 @@ public class WebAnalyticEventResource extends EntityResource<WebAnalyticEvent, W
@Context UriInfo uriInfo,
@Context SecurityContext securityContext,
@Valid WebAnalyticEventData webAnalyticEventData)
throws Exception {
return MicrometerBundleSingleton.webAnalyticEvents.recordCallable(
() -> {
try {
return dao.addWebAnalyticEventData(webAnalyticEventData);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
throws IOException {
return dao.addWebAnalyticEventData(webAnalyticEventData);
}
@DELETE

View File

@ -26,7 +26,6 @@ public class MicrometerBundleSingleton {
public static MicrometerBundle getInstance() {
if (INSTANCE == null) {
INSTANCE = new MicrometerBundle();
webAnalyticEvents = MicrometerBundle.prometheusRegistry.timer("web.analytics.events");
// We'll use this registry to add monitoring around Ingestion Pipelines
prometheusMeterRegistry = MicrometerBundle.prometheusRegistry;
}