Skip to content

Commit

Permalink
Merge pull request #4490 from inception-project/feature/4377-configur…
Browse files Browse the repository at this point in the history
…e-patterns-for-logged-events

#4377 - Configure include and exclude patterns for logged events
  • Loading branch information
reckart authored Feb 4, 2024
2 parents c256d22 + 32d3104 commit c889fa1
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
Expand Down Expand Up @@ -55,6 +59,8 @@ public class EventLoggingListener
private final EventLoggingProperties properties;
private final EventLoggingAdapterRegistry adapterRegistry;

private Map<String, Boolean> eventCache = new HashMap<>();

private volatile boolean flushing = false;

@Autowired
Expand All @@ -71,6 +77,32 @@ public EventLoggingListener(EventRepository aRepo, EventLoggingProperties aPrope
scheduler.scheduleAtFixedRate(() -> flush(), 1, 1, TimeUnit.SECONDS);
}

boolean shouldLogEvent(String aEventName)
{
if (eventCache.containsKey(aEventName)) {
return eventCache.get(aEventName);
}

boolean shouldLog;

if (CollectionUtils.isEmpty(properties.getIncludePatterns())) {
shouldLog = true;
}
else {
shouldLog = properties.getIncludePatterns().stream()
.anyMatch(pattern -> Pattern.matches(pattern, aEventName));
}

if (shouldLog && !CollectionUtils.isEmpty(properties.getExcludePatterns())) {
shouldLog = properties.getExcludePatterns().stream()
.noneMatch(pattern -> Pattern.matches(pattern, aEventName));
}

eventCache.put(aEventName, shouldLog);

return shouldLog;
}

@EventListener
public void onApplicationEvent(ApplicationEvent aEvent)
{
Expand All @@ -86,7 +118,7 @@ public void onApplicationEvent(ApplicationEvent aEvent)

var adapter = maybeAdapter.get();

if (properties.getExcludeEvents().contains(adapter.getEvent(aEvent))) {
if (!shouldLogEvent(adapter.getEvent(aEvent))) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,25 @@ public interface EventLoggingProperties

boolean isEnabled();

Set<String> getExcludeEvents();
/**
* @return Set of regex include patterns
*/
Set<String> getIncludePatterns();

/**
* @param includePatterns
* Set of regex include patterns
*/
void setIncludePatterns(Set<String> includePatterns);

/**
* @return Set of regex exclude patterns
*/
Set<String> getExcludePatterns();

/**
* @param aExcludeEvents
* events never to be written to the event log.
* @param excludePatterns
* Set of regex exclude patterns
*/
void setExcludeEvents(Set<String> aExcludeEvents);
void setExcludePatterns(Set<String> excludePatterns);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package de.tudarmstadt.ukp.inception.log.config;

import java.util.Collections;
import java.util.Set;

import org.springframework.boot.availability.AvailabilityChangeEvent;
Expand All @@ -32,8 +33,9 @@ public class EventLoggingPropertiesImpl
{
private boolean enabled;

private Set<String> excludeEvents = Set.of( //
// Do not log this by default - hardly any information value
private Set<String> includePatterns = Collections.emptySet(); // Default include everything

private Set<String> excludePatterns = Set.of( //
AfterCasWrittenEvent.class.getSimpleName(), //
AvailabilityChangeEvent.class.getSimpleName(), //
"RecommenderTaskNotificationEvent", //
Expand All @@ -55,14 +57,26 @@ public void setEnabled(boolean aEnabled)
}

@Override
public Set<String> getExcludeEvents()
public Set<String> getIncludePatterns()
{
return includePatterns;
}

@Override
public void setIncludePatterns(Set<String> aIncludePatterns)
{
this.includePatterns = aIncludePatterns;
}

@Override
public Set<String> getExcludePatterns()
{
return excludeEvents;
return excludePatterns;
}

@Override
public void setExcludeEvents(Set<String> aExcludeEvents)
public void setExcludePatterns(Set<String> aExcludePatterns)
{
excludeEvents = aExcludeEvents;
this.excludePatterns = aExcludePatterns;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Licensed to the Technische Universität Darmstadt under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The Technische Universität Darmstadt
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.tudarmstadt.ukp.inception.log;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Set;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.availability.AvailabilityChangeEvent;

import de.tudarmstadt.ukp.inception.annotation.events.BeforeDocumentOpenedEvent;
import de.tudarmstadt.ukp.inception.annotation.events.PreparingToOpenDocumentEvent;
import de.tudarmstadt.ukp.inception.documents.event.AfterCasWrittenEvent;
import de.tudarmstadt.ukp.inception.log.config.EventLoggingPropertiesImpl;

class EventLoggingListenerTest
{

private EventLoggingListener listener;
private EventLoggingPropertiesImpl properties;

@BeforeEach
void setUp() throws Exception
{
properties = new EventLoggingPropertiesImpl();
listener = new EventLoggingListener(null, properties, null);
}

@Test
public void shouldLogEvent_defaultExcludeInternalList_ReturnsFalse()
{
assertThat(listener.shouldLogEvent(AfterCasWrittenEvent.class.getSimpleName())).isFalse();
assertThat(listener.shouldLogEvent(AvailabilityChangeEvent.class.getSimpleName()))
.isFalse();
assertThat(listener.shouldLogEvent("RecommenderTaskNotificationEvent")).isFalse();
assertThat(listener.shouldLogEvent(BeforeDocumentOpenedEvent.class.getSimpleName()))
.isFalse();
assertThat(listener.shouldLogEvent(PreparingToOpenDocumentEvent.class.getSimpleName()))
.isFalse();
assertThat(listener.shouldLogEvent("BrokerAvailabilityEvent")).isFalse();
assertThat(listener.shouldLogEvent("ShutdownDialogAvailableEvent")).isFalse();
}

@Test
public void shouldLogEvent_EventNotInExcludeLists_ReturnsTrue()
{
var eventAfterDocumentOpened = "AfterDocumentOpenedEvent";

assertThat(listener.shouldLogEvent(eventAfterDocumentOpened)).isTrue();
assertThat(properties.getExcludePatterns()).doesNotContain(eventAfterDocumentOpened);
}

@Test
public void shouldLogEvent_setExcludeWorksAndEventsGetExcludedTrue()
{
var excludedEvent = "ExcludedEvent";

properties.setExcludePatterns(Set.of(excludedEvent));

assertThat(listener.shouldLogEvent(excludedEvent)).isFalse();
}

@Test
public void shouldLogEvent_setIncludeWorksAndOnlyEventsSetIncludedWork()
{
var includedEvent = "IncludedEvent";
var notIncludedEvent = "NotIncludedEvent";

properties.setIncludePatterns(Set.of(includedEvent));

assertThat(listener.shouldLogEvent(includedEvent)).isTrue();
assertThat(listener.shouldLogEvent(notIncludedEvent)).isFalse();
}
}

0 comments on commit c889fa1

Please sign in to comment.