Skip to content
Snippets Groups Projects
Commit d2df1f30 authored by ribeaudc's avatar ribeaudc
Browse files

[DMV-15] - Add 'ConditionalNotificationLogger' and its test.

- Notify the administrator when the script for data completed is not found after DataMover has been started.

SVN: 6327
parent 56e2908d
No related branches found
No related tags found
No related merge requests found
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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 ch.systemsx.cisd.common.logging;
import org.apache.log4j.Logger;
/**
* An <code>ISimpleLogger</code> implementation which sends an email (via logger) when the number
* of log errors reaches a given number.
* <p>
* Note that this class sends one and only one notification email. To reset the state of this class,
* use {@link #reset(String)}.
* </p>
*
* @author Christian Ribeaud
*/
public final class ConditionalNotificationLogger implements ISimpleLogger
{
private final Logger notificationLog;
private final Logger operationLog;
private final int ignoredErrorCountBeforeNotification;
private int errorCount;
private boolean notified;
/**
* @param ignoredErrorCountBeforeNotification the number of errors that are ignored before
* sending a notification email.
*/
public ConditionalNotificationLogger(final Class<?> clazz,
final int ignoredErrorCountBeforeNotification)
{
assert clazz != null : "Unspecified class";
assert ignoredErrorCountBeforeNotification > -1 : "Negative ignored error "
+ "count before notification";
this.ignoredErrorCountBeforeNotification = ignoredErrorCountBeforeNotification;
operationLog = LogFactory.getLogger(LogCategory.OPERATION, clazz);
notificationLog = LogFactory.getLogger(LogCategory.NOTIFY, clazz);
}
/**
* Resets counting of errors and <code>notified</code> flag.
* <p>
* As side effect, it sends a notification log to inform that we are "green" again (if and only
* if an email has already been sent to inform the "bad" state and if log info is enabled).
* </p>
*
* @param message the info log message.
*/
public final void reset(final String message)
{
if (notified && notificationLog.isInfoEnabled())
{
notificationLog.info(message);
}
errorCount = 0;
notified = false;
}
//
// ISimpleLogger
//
public final void log(final LogLevel level, final String message)
{
if (LogLevel.ERROR.equals(level))
{
if (errorCount < ignoredErrorCountBeforeNotification)
{
operationLog.warn(message);
} else if (notified == false)
{
notificationLog.error(message);
notified = true;
}
errorCount++;
}
}
}
\ No newline at end of file
...@@ -22,10 +22,10 @@ import java.util.TimerTask; ...@@ -22,10 +22,10 @@ import java.util.TimerTask;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.logging.ConditionalNotificationLogger;
import ch.systemsx.cisd.common.logging.ISimpleLogger; import ch.systemsx.cisd.common.logging.ISimpleLogger;
import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.common.logging.LogLevel;
/** /**
* A {@link TimerTask} that scans a source directory for entries that are accepted by some * A {@link TimerTask} that scans a source directory for entries that are accepted by some
...@@ -58,8 +58,6 @@ public final class DirectoryScanningTimerTask extends TimerTask ...@@ -58,8 +58,6 @@ public final class DirectoryScanningTimerTask extends TimerTask
*/ */
private final int ignoredErrorCount; private final int ignoredErrorCount;
private int errorCountReadingDirectory;
private final IDirectoryScanningHandler directoryScanningHandler; private final IDirectoryScanningHandler directoryScanningHandler;
/** /**
...@@ -214,54 +212,18 @@ public final class DirectoryScanningTimerTask extends TimerTask ...@@ -214,54 +212,18 @@ public final class DirectoryScanningTimerTask extends TimerTask
private final StoreItem[] listStoreItems() private final StoreItem[] listStoreItems()
{ {
// Avoid mailbox flooding. final ConditionalNotificationLogger notificationLogger =
final boolean logNotifyError = (errorCountReadingDirectory == ignoredErrorCount); new ConditionalNotificationLogger(getClass(), ignoredErrorCount);
final boolean logOperationError = (errorCountReadingDirectory < ignoredErrorCount); final StoreItem[] storeItems =
final ISimpleLogger errorLogger = sourceDirectory.tryListSortedReadyToProcess(notificationLogger);
logNotifyError ? createSimpleErrorLogger(LogCategory.NOTIFY) if (storeItems != null)
: (logOperationError ? createSimpleErrorLogger(LogCategory.OPERATION)
: null);
final StoreItem[] storeItems = sourceDirectory.tryListSortedReadyToProcess(errorLogger);
if (errorCountReadingDirectory > ignoredErrorCount && storeItems != null)
{ {
if (notificationLog.isInfoEnabled()) notificationLogger.reset(String.format("Directory '%s' is available again.",
{ sourceDirectory));
notificationLog.info(String.format("Directory '%s' is available again.",
sourceDirectory));
}
}
if (storeItems == null)
{
++errorCountReadingDirectory;
} else
{
errorCountReadingDirectory = 0;
} }
return (storeItems == null) ? StoreItem.EMPTY_ARRAY : storeItems; return (storeItems == null) ? StoreItem.EMPTY_ARRAY : storeItems;
} }
private final ISimpleLogger createSimpleErrorLogger(final LogCategory category)
{
return new ISimpleLogger()
{
//
// ISimpleLogger
//
public final void log(final LogLevel dummyLevel, final String message)
{
if (category == LogCategory.NOTIFY)
{
notificationLog.log(org.apache.log4j.Level.ERROR, message);
} else
{
operationLog.log(org.apache.log4j.Level.WARN, message);
}
}
};
}
// //
// Helper classes // Helper classes
// //
......
/*
* Copyright 2008 ETH Zuerich, CISD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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 ch.systemsx.cisd.common.logging;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Level;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* Test cases for corresponding {@link ConditionalNotificationLogger} class.
*
* @author Christian Ribeaud
*/
public final class ConditionalNotificationLoggerTest
{
private final ConditionalNotificationLogger createConditionalNotificationLogger(
final int ignoredErrorCountBeforeNotification)
{
final ConditionalNotificationLogger logger =
new ConditionalNotificationLogger(getClass(), ignoredErrorCountBeforeNotification);
return logger;
}
private BufferedAppender operationLogRecorder;
private BufferedAppender notificationLogRecorder;
@BeforeMethod
public final void setUp()
{
operationLogRecorder = new BufferedAppender("%m", Level.WARN);
notificationLogRecorder = new BufferedAppender("%m", Level.ERROR);
}
@Test
public final void testConstructor()
{
boolean fail = true;
try
{
new ConditionalNotificationLogger(null, -1);
} catch (final AssertionError e)
{
fail = false;
}
try
{
new ConditionalNotificationLogger(getClass(), -1);
} catch (final AssertionError e)
{
fail = false;
}
assertFalse(fail);
}
@DataProvider(name = "ignoredErrorCount")
public final Object[][] getIgnoredErrorCount()
{
return new Object[][]
{
{ 0 },
{ 1 },
{ 2 }, };
}
@Test(dataProvider = "ignoredErrorCount")
public final void testLogWithErrorLevel(final int ignoredErrorCountBeforeNotification)
{
final ConditionalNotificationLogger logger =
createConditionalNotificationLogger(ignoredErrorCountBeforeNotification);
final String logMessage = "Some message";
for (int i = 0; i <= ignoredErrorCountBeforeNotification; i++)
{
logger.log(LogLevel.ERROR, logMessage);
assertEquals(StringUtils.repeat(logMessage, i + 1), operationLogRecorder
.getLogContent());
if (i >= ignoredErrorCountBeforeNotification)
{
assertEquals(logMessage, notificationLogRecorder.getLogContent());
}
}
logger.log(null, logMessage);
assertEquals(logMessage, notificationLogRecorder.getLogContent());
}
@Test
public final void testLogWithNullLevel()
{
final ConditionalNotificationLogger logger = createConditionalNotificationLogger(0);
final String logMessage = "Some message";
logger.log(null, logMessage);
assertEquals("", operationLogRecorder.getLogContent());
assertEquals("", notificationLogRecorder.getLogContent());
}
@Test
public final void testReset()
{
final ConditionalNotificationLogger logger = createConditionalNotificationLogger(2);
final String logMessage = "Some message";
logger.log(LogLevel.ERROR, logMessage);
logger.log(LogLevel.ERROR, logMessage);
logger.log(LogLevel.ERROR, logMessage);
assertEquals(logMessage, notificationLogRecorder.getLogContent());
logger.log(LogLevel.ERROR, logMessage);
assertEquals(logMessage, notificationLogRecorder.getLogContent());
logger.reset("Green again");
notificationLogRecorder.resetLogContent();
logger.log(LogLevel.ERROR, logMessage);
assertEquals("", notificationLogRecorder.getLogContent());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment