Skip to content
Snippets Groups Projects
Commit 0aeb2355 authored by gmantele's avatar gmantele
Browse files

[TAP] Add log management in the TAP configuration file. 2 additional...

[TAP] Add log management in the TAP configuration file. 2 additional properties have been added: min_log_level and log_rotation.
parent 6fc94d89
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@ import static tap.config.TAPConfiguration.KEY_FILE_MANAGER;
import static tap.config.TAPConfiguration.KEY_FILE_ROOT_PATH;
import static tap.config.TAPConfiguration.KEY_GEOMETRIES;
import static tap.config.TAPConfiguration.KEY_GROUP_USER_DIRECTORIES;
import static tap.config.TAPConfiguration.KEY_LOG_ROTATION;
import static tap.config.TAPConfiguration.KEY_MAX_ASYNC_JOBS;
import static tap.config.TAPConfiguration.KEY_MAX_EXECUTION_DURATION;
import static tap.config.TAPConfiguration.KEY_MAX_OUTPUT_LIMIT;
......@@ -22,6 +23,7 @@ import static tap.config.TAPConfiguration.KEY_MAX_RETENTION_PERIOD;
import static tap.config.TAPConfiguration.KEY_MAX_UPLOAD_LIMIT;
import static tap.config.TAPConfiguration.KEY_METADATA;
import static tap.config.TAPConfiguration.KEY_METADATA_FILE;
import static tap.config.TAPConfiguration.KEY_MIN_LOG_LEVEL;
import static tap.config.TAPConfiguration.KEY_OUTPUT_FORMATS;
import static tap.config.TAPConfiguration.KEY_PROVIDER_NAME;
import static tap.config.TAPConfiguration.KEY_SERVICE_DESCRIPTION;
......@@ -77,6 +79,7 @@ import uws.UWSException;
import uws.service.UserIdentifier;
import uws.service.file.LocalUWSFileManager;
import uws.service.file.UWSFileManager;
import uws.service.log.UWSLog.LogLevel;
import adql.db.FunctionDef;
import adql.parser.ParseException;
import adql.query.operand.function.UserDefinedFunction;
......@@ -124,7 +127,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
initFileManager(tapConfig);
// 2. CREATE THE LOGGER:
logger = new DefaultTAPLog(fileManager);
initLogger(tapConfig);
// 3. BUILD THE TAP FACTORY:
tapFactory = new ConfigurableTAPFactory(this, tapConfig);
......@@ -211,6 +214,34 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
}
}
private void initLogger(final Properties tapConfig){
// Create the logger:
logger = new DefaultTAPLog(fileManager);
StringBuffer buf = new StringBuffer("Logger initialized");
// Set the minimum log level:
String propValue = getProperty(tapConfig, KEY_MIN_LOG_LEVEL);
if (propValue != null){
try{
((DefaultTAPLog)logger).setMinLogLevel(LogLevel.valueOf(propValue.toUpperCase()));
}catch(IllegalArgumentException iae){}
}
buf.append(" (minimum log level: ").append(((DefaultTAPLog)logger).getMinLogLevel());
// Set the log rotation period, if any:
if (fileManager instanceof LocalUWSFileManager){
propValue = getProperty(tapConfig, KEY_LOG_ROTATION);
if (propValue != null)
((LocalUWSFileManager)fileManager).setLogRotationFreq(propValue);
buf.append(", log rotation: ").append(((LocalUWSFileManager)fileManager).getLogRotationFreq());
}
// Log the successful initialization with set parameters:
buf.append(").");
logger.info(buf.toString());
}
private TAPMetadata initMetadata(final Properties tapConfig) throws TAPException{
// Get the fetching method to use:
String metaFetchType = getProperty(tapConfig, KEY_METADATA);
......
......@@ -28,6 +28,10 @@ public final class TAPConfiguration {
public final static String KEY_MAX_RETENTION_PERIOD = "max_retention_period";
public final static int DEFAULT_RETENTION_PERIOD = 0;
/* LOG KEYS */
public final static String KEY_MIN_LOG_LEVEL = "min_log_level";
public final static String KEY_LOG_ROTATION = "log_rotation";
/* UWS BACKUP */
public final static String KEY_BACKUP_FREQUENCY = "backup_frequency";
public final static String VALUE_USER_ACTION = "user_action";
......
......@@ -327,6 +327,51 @@
<td>604800 <em>(1 week)</em></td>
</tr>
<tr><td colspan="5">Log files</td></tr>
<tr class="optional">
<td class="done">min_log_level</td>
<td></td>
<td>text</td>
<td>
<p>Minimum level that a message must have in order to be logged.</p>
<p>5 possible values:</p>p>
<ul>
<li><b>DEBUG</b>: every messages are logged.</li>
<li><b>INFO</b>: every messages EXCEPT DEBUG are logged.</li>
<li><b>WARNING</b>: every messages EXCEPT DEBUG and INFO are logged.</li>
<li><b>ERROR</b>: only ERROR and FATAL messages are logged.</li>
<li><b>FATAL</b>: only FATAL messages are logged.</li>
</ul>
<p><em>Default: <code>DEBUG</code> (every messages are logged)</em></p>
</td>
<td><ul><li>DEBUG</li><li>INFO</li><li>WANRING</li><li>ERROR</li><li>FATAL</li></ul></td>
</tr>
<tr class="optional">
<td class="done">log_rotation</td>
<td></td>
<td>text</td>
<td>
<p>Frequency of the log file rotation. That's to say, logs will be written in a new file after this period. This avoid having too big log files.
Old log files are renamed so that highlighting its logging period.</p>
<p>The frequency string must respect the following syntax:</p>
<ul>
<li><b>'D' hh mm</b>: daily schedule at hh:mm</li>
<li><b>'W' dd hh mm</b>: weekly schedule at the given day of the week (1:sunday, 2:monday, ..., 7:saturday) at hh:mm</li>
<li><b>'M' dd hh mm</b>: monthly schedule at the given day of the month at hh:mm</li>
<li><b>'h' mm</b>: hourly schedule at the given minute</li>
<li><b>'m'</b>: scheduled every minute (for completness :-))</li>
</ul>
<p><em>Where: hh = integer between 0 and 23, mm = integer between 0 and 59, dd (for 'W') = integer between 1 and 7 (1:sunday, 2:monday, ..., 7:saturday),
dd (for 'M') = integer between 1 and 31.</em></p>
<p><em><b>Warning:</b>
The frequency type is case sensitive! Then you should particularly pay attention at the case
when using the frequency types 'M' (monthly) and 'm' (every minute).
</em></p>
<p><em>Default: <code>D 0 0</code> (daily at midnight)</em></p>
</td>
<td><ul><li>D 6 30</li><li>W 2 6 30</li><li>M 2 6 30</li><li>H 10</li><li>m</li></ul></td>
</tr>
<tr><td colspan="5">UWS Backup</td></tr>
<tr class="optional">
<td class="done">backup_frequency</td>
......
......@@ -2,7 +2,7 @@
# FULL TAP CONFIGURATION FILE #
# #
# TAP Version: 2.0 #
# Date: 17 Feb. 2015 #
# Date: 18 Feb. 2015 #
# Author: Gregory Mantelet (ARI) #
# #
##########################################################
......@@ -191,6 +191,42 @@ default_retention_period = 0
# Default: 0 (results kept forever).
max_retention_period = 0
#############
# LOG FILES #
#############
# [OPTIONAL]
# Minimum level that a message must have in order to be logged.
#
# 5 possible values:
# * DEBUG: every messages are logged.
# * INFO: every messages EXCEPT DEBUG are logged.
# * WARNING: every messages EXCEPT DEBUG and INFO are logged.
# * ERROR: only ERROR and FATAL messages are logged.
# * FATAL: only FATAL messages are logged.
#
# Default: DEBUG (every messages are logged)
min_log_level =
# [OPTIONAL]
# Frequency of the log file rotation. That's to say, logs will be written in a new file after this period. This avoid having too big log files.
# Old log files are renamed so that highlighting its logging period.
#
# The frequency string must respect the following syntax:
# 'D' hh mm: daily schedule at hh:mm
# 'W' dd hh mm: weekly schedule at the given day of the week (1:sunday, 2:monday, ..., 7:saturday) at hh:mm
# 'M' dd hh mm: monthly schedule at the given day of the month at hh:mm
# 'h' mm: hourly schedule at the given minute
# 'm': scheduled every minute (for completness :-))
# Where: hh = integer between 0 and 23, mm = integer between 0 and 59, dd (for 'W') = integer between 1 and 7 (1:sunday, 2:monday, ..., 7:saturday), dd (for 'M') = integer between 1 and 31.
#
# Warning: The frequency type is case sensitive! Then you should particularly pay attention at the case when using the frequency types 'M' (monthly) and 'm' (every minute).
#
# Note: this property is ignored if the file manager is not any more an extension of uws.service.file.LocalUWSFileManager.
#
# Default: D 0 0 (daily at midnight)
log_rotation =
##############
# UWS_BACKUP #
##############
......
......@@ -16,7 +16,7 @@ package tap.log;
* You should have received a copy of the GNU Lesser General Public License
* along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
......@@ -37,7 +37,7 @@ import uws.service.log.DefaultUWSLog;
* Default implementation of the {@link TAPLog} interface which lets logging any message about a TAP service.
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.0 (12/2014)
* @version 2.0 (02/2015)
*
* @see DefaultUWSLog
*/
......@@ -117,7 +117,15 @@ public class DefaultTAPLog extends DefaultUWSLog implements TAPLog {
}
@Override
public void logDB(final LogLevel level, final DBConnection connection, final String event, final String message, final Throwable error){
public void logDB(LogLevel level, final DBConnection connection, final String event, final String message, final Throwable error){
// If the type is missing:
if (level == null)
level = (error != null) ? LogLevel.ERROR : LogLevel.INFO;
// Log or not?
if (!canLog(level))
return;
// log the main given error:
log(level, "DB", event, (connection != null ? connection.getID() : null), message, error);
......@@ -133,7 +141,15 @@ public class DefaultTAPLog extends DefaultUWSLog implements TAPLog {
}
@Override
public void logTAP(final LogLevel level, final Object obj, final String event, final String message, final Throwable error){
public void logTAP(LogLevel level, final Object obj, final String event, final String message, final Throwable error){
// If the type is missing:
if (level == null)
level = (error != null) ? LogLevel.ERROR : LogLevel.INFO;
// Log or not?
if (!canLog(level))
return;
// Get more information (when known event and available object):
String jobId = null, msgAppend = null;
try{
......
......@@ -10,10 +10,12 @@ import static tap.config.TAPConfiguration.DEFAULT_MAX_ASYNC_JOBS;
import static tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT;
import static tap.config.TAPConfiguration.KEY_FILE_MANAGER;
import static tap.config.TAPConfiguration.KEY_GEOMETRIES;
import static tap.config.TAPConfiguration.KEY_LOG_ROTATION;
import static tap.config.TAPConfiguration.KEY_MAX_ASYNC_JOBS;
import static tap.config.TAPConfiguration.KEY_MAX_OUTPUT_LIMIT;
import static tap.config.TAPConfiguration.KEY_METADATA;
import static tap.config.TAPConfiguration.KEY_METADATA_FILE;
import static tap.config.TAPConfiguration.KEY_MIN_LOG_LEVEL;
import static tap.config.TAPConfiguration.KEY_OUTPUT_FORMATS;
import static tap.config.TAPConfiguration.KEY_UDFS;
import static tap.config.TAPConfiguration.KEY_USER_IDENTIFIER;
......@@ -55,6 +57,8 @@ import uws.job.user.JobOwner;
import uws.service.UWSUrl;
import uws.service.UserIdentifier;
import uws.service.file.LocalUWSFileManager;
import uws.service.log.DefaultUWSLog;
import uws.service.log.UWSLog.LogLevel;
import adql.db.FunctionDef;
import adql.db.TestDBChecker.UDFToto;
......@@ -63,21 +67,22 @@ public class TestConfigurableServiceConnection {
private final static String XML_FILE = "test/tap/config/tables.xml";
private static Properties validProp, noFmProp, fmClassPathProp,
incorrectFmProp, xmlMetaProp, missingMetaProp, missingMetaFileProp,
wrongMetaProp, wrongMetaFileProp, validFormatsProp,
validVOTableFormatsProp, badSVFormat1Prop, badSVFormat2Prop,
badVotFormat1Prop, badVotFormat2Prop, badVotFormat3Prop,
badVotFormat4Prop, badVotFormat5Prop, badVotFormat6Prop,
unknownFormatProp, maxAsyncProp, negativeMaxAsyncProp,
notIntMaxAsyncProp, defaultOutputLimitProp, maxOutputLimitProp,
bothOutputLimitGoodProp, bothOutputLimitBadProp, userIdentProp,
notClassPathUserIdentProp, geometriesProp, noneGeomProp,
anyGeomProp, noneInsideGeomProp, unknownGeomProp, anyUdfsProp,
noneUdfsProp, udfsProp, udfsWithClassPathProp,
udfsListWithNONEorANYProp, udfsWithWrongParamLengthProp,
udfsWithMissingBracketsProp, udfsWithMissingDefProp1,
udfsWithMissingDefProp2, emptyUdfItemProp1, emptyUdfItemProp2,
udfWithMissingEndBracketProp;
incorrectFmProp, correctLogProp, incorrectLogLevelProp,
incorrectLogRotationProp, xmlMetaProp, missingMetaProp,
missingMetaFileProp, wrongMetaProp, wrongMetaFileProp,
validFormatsProp, validVOTableFormatsProp, badSVFormat1Prop,
badSVFormat2Prop, badVotFormat1Prop, badVotFormat2Prop,
badVotFormat3Prop, badVotFormat4Prop, badVotFormat5Prop,
badVotFormat6Prop, unknownFormatProp, maxAsyncProp,
negativeMaxAsyncProp, notIntMaxAsyncProp, defaultOutputLimitProp,
maxOutputLimitProp, bothOutputLimitGoodProp,
bothOutputLimitBadProp, userIdentProp, notClassPathUserIdentProp,
geometriesProp, noneGeomProp, anyGeomProp, noneInsideGeomProp,
unknownGeomProp, anyUdfsProp, noneUdfsProp, udfsProp,
udfsWithClassPathProp, udfsListWithNONEorANYProp,
udfsWithWrongParamLengthProp, udfsWithMissingBracketsProp,
udfsWithMissingDefProp1, udfsWithMissingDefProp2,
emptyUdfItemProp1, emptyUdfItemProp2, udfWithMissingEndBracketProp;
@BeforeClass
public static void setUp() throws Exception{
......@@ -93,6 +98,16 @@ public class TestConfigurableServiceConnection {
incorrectFmProp = (Properties)validProp.clone();
incorrectFmProp.setProperty(KEY_FILE_MANAGER, "foo");
correctLogProp = (Properties)validProp.clone();
correctLogProp.setProperty(KEY_LOG_ROTATION, " M 5 6 03 ");
correctLogProp.setProperty(KEY_MIN_LOG_LEVEL, " WARNing ");
incorrectLogLevelProp = (Properties)validProp.clone();
incorrectLogLevelProp.setProperty(KEY_MIN_LOG_LEVEL, "foo");
incorrectLogRotationProp = (Properties)validProp.clone();
incorrectLogRotationProp.setProperty(KEY_LOG_ROTATION, "foo");
xmlMetaProp = (Properties)validProp.clone();
xmlMetaProp.setProperty(KEY_METADATA, VALUE_XML);
xmlMetaProp.setProperty(KEY_METADATA_FILE, XML_FILE);
......@@ -254,7 +269,9 @@ public class TestConfigurableServiceConnection {
// tests:
assertNotNull(connection.getLogger());
assertEquals(LogLevel.DEBUG, ((DefaultUWSLog)connection.getLogger()).getMinLogLevel());
assertNotNull(connection.getFileManager());
assertEquals("daily at 00:00", ((LocalUWSFileManager)connection.getFileManager()).getLogRotationFreq());
assertNotNull(connection.getFactory());
assertNotNull(connection.getTAPMetadata());
assertTrue(connection.getTAPMetadata().getNbSchemas() >= 1);
......@@ -284,7 +301,9 @@ public class TestConfigurableServiceConnection {
try{
ServiceConnection connection = new ConfigurableServiceConnection(xmlMetaProp);
assertNotNull(connection.getLogger());
assertEquals(LogLevel.DEBUG, ((DefaultUWSLog)connection.getLogger()).getMinLogLevel());
assertNotNull(connection.getFileManager());
assertEquals("daily at 00:00", ((LocalUWSFileManager)connection.getFileManager()).getLogRotationFreq());
assertNotNull(connection.getFactory());
assertNotNull(connection.getTAPMetadata());
assertEquals(nbSchemas, connection.getTAPMetadata().getNbSchemas());
......@@ -349,7 +368,9 @@ public class TestConfigurableServiceConnection {
try{
ServiceConnection connection = new ConfigurableServiceConnection(fmClassPathProp);
assertNotNull(connection.getLogger());
assertEquals(LogLevel.DEBUG, ((DefaultUWSLog)connection.getLogger()).getMinLogLevel());
assertNotNull(connection.getFileManager());
assertEquals("daily at 00:00", ((LocalUWSFileManager)connection.getFileManager()).getLogRotationFreq());
assertNotNull(connection.getFactory());
assertNotNull(connection.getTAPMetadata());
assertFalse(connection.isAvailable());
......@@ -374,6 +395,35 @@ public class TestConfigurableServiceConnection {
assertEquals("Unknown value for the property \"" + KEY_FILE_MANAGER + "\": \"foo\". Only two possible values: " + VALUE_LOCAL + " or a class path between {...}.", e.getMessage());
}
// Custom log level and log rotation:
try{
ServiceConnection connection = new ConfigurableServiceConnection(correctLogProp);
assertNotNull(connection.getLogger());
assertEquals(LogLevel.WARNING, ((DefaultUWSLog)connection.getLogger()).getMinLogLevel());
assertNotNull(connection.getFileManager());
assertEquals("monthly on the 5th at 06:03", ((LocalUWSFileManager)connection.getFileManager()).getLogRotationFreq());
}catch(Exception e){
fail("This MUST have succeeded because the provided log level and log rotation are valid! \nCaught exception: " + getPertinentMessage(e));
}
// Incorrect log level:
try{
ServiceConnection connection = new ConfigurableServiceConnection(incorrectLogLevelProp);
assertNotNull(connection.getLogger());
assertEquals(LogLevel.DEBUG, ((DefaultUWSLog)connection.getLogger()).getMinLogLevel());
}catch(Exception e){
fail("This MUST have succeeded because even if the provided log level is incorrect the default behavior is to not throw exception and set the default value! \nCaught exception: " + getPertinentMessage(e));
}
// Incorrect log rotation:
try{
ServiceConnection connection = new ConfigurableServiceConnection(incorrectLogRotationProp);
assertNotNull(connection.getFileManager());
assertEquals("daily at 00:00", ((LocalUWSFileManager)connection.getFileManager()).getLogRotationFreq());
}catch(Exception e){
fail("This MUST have succeeded because even if the provided log rotation is incorrect the default behavior is to not throw exception and set the default value! \nCaught exception: " + getPertinentMessage(e));
}
// Valid output formats list:
try{
ServiceConnection connection = new ConfigurableServiceConnection(validFormatsProp);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment