diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/logging')
29 files changed, 994 insertions, 89 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java b/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java index b4e6cc09..36ed3d64 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java +++ b/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java b/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java index 560e1b0f..53540ec2 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java +++ b/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java b/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java index 827108aa..b4530c25 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java +++ b/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/Logging.java b/src/de/lmu/ifi/dbs/elki/logging/Logging.java index 807d4b6e..b9cbc16d 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/Logging.java +++ b/src/de/lmu/ifi/dbs/elki/logging/Logging.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,28 +24,35 @@ package de.lmu.ifi.dbs.elki.logging; */ import java.util.HashMap; -import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import de.lmu.ifi.dbs.elki.logging.progress.Progress; import de.lmu.ifi.dbs.elki.logging.progress.ProgressLogRecord; +import de.lmu.ifi.dbs.elki.logging.statistics.Counter; +import de.lmu.ifi.dbs.elki.logging.statistics.Duration; +import de.lmu.ifi.dbs.elki.logging.statistics.MillisTimeDuration; +import de.lmu.ifi.dbs.elki.logging.statistics.Statistic; +import de.lmu.ifi.dbs.elki.logging.statistics.UnsynchronizedLongCounter; /** * This class is a wrapper around {@link java.util.logging.Logger} and - * {@link java.util.logging.LogManager} offering additional convenience functions. + * {@link java.util.logging.LogManager} offering additional convenience + * functions. * - * If a class keeps a static reference to the appropriate {@link Logging} object, - * performance penalty compared to standard logging should be minimal. + * If a class keeps a static reference to the appropriate {@link Logging} + * object, performance penalty compared to standard logging should be minimal. * - * However when using {@link java.util.logging.LogRecord} directly instead of - * {@link ELKILogRecord}, the use of the {@link #log(LogRecord)} method will result in - * incorrectly logged cause location. Therefore, use {@link ELKILogRecord}! + * However when using {@link java.util.logging.LogRecord} directly instead of + * {@link ELKILogRecord}, the use of the {@link #log(LogRecord)} method will + * result in incorrectly logged cause location. Therefore, use + * {@link ELKILogRecord}! * * @author Erich Schubert - * + * * @apiviz.uses LoggingConfiguration * @apiviz.uses ELKILogRecord oneway - - «create» + * @apiviz.uses Level */ public class Logging { /** @@ -58,7 +65,7 @@ public class Logging { /** * HashMap to keep track of loggers. */ - private static HashMap<String, Logging> loggers = new HashMap<String, Logging>(); + private static HashMap<String, Logging> loggers = new HashMap<>(); /** * Wrapped logger of this instance - not static! @@ -66,6 +73,47 @@ public class Logging { private final Logger logger; /** + * Logging Level class. + * + * @author Erich Schubert + */ + public static class Level extends java.util.logging.Level { + /** + * Additional level for logging: statistics and timing information. + * + * Inbetween of "verbose" and "warning". + */ + public static final Level STATISTICS = new Level("STATISTICS", (INFO.intValue() + WARNING.intValue()) >> 1); + + /** + * Alias for the "INFO" logging level: "verbose". + */ + public static final java.util.logging.Level VERBOSE = INFO; + + /** + * Additional level for logging: additional verbose messages. + * + * Inbetween of "verbose" and "config", usually 750. + */ + public static final Level VERYVERBOSE = new Level("VERYVERBOSE", (INFO.intValue() + CONFIG.intValue()) >> 1); + + /** + * Serial version. + */ + private static final long serialVersionUID = 1L; + + /** + * Constructor. + * + * @param name Name + * @param value Value + */ + public Level(String name, int value) { + super(name, value); + } + } + + /** * Constructor, wrapping a logger. * * @param logger Logger to wrap. @@ -87,12 +135,12 @@ public class Logging { /** * Retrieve logging utility for a particular class. * - * @param name Class name + * @param name Class name * @return Logger */ public synchronized static Logging getLogger(final String name) { Logging logger = loggers.get(name); - if(logger == null) { + if (logger == null) { logger = new Logging(Logger.getLogger(name)); loggers.put(name, logger); } @@ -110,12 +158,21 @@ public class Logging { } /** + * Test whether to log 'statistics'. + * + * @return true if logging statistics + */ + public boolean isStatistics() { + return logger.isLoggable(Level.STATISTICS); + } + + /** * Test whether to log 'verbose' aka 'info'. * * @return true if verbose */ public boolean isVerbose() { - return logger.isLoggable(Level.INFO); + return logger.isLoggable(Level.VERBOSE); } /** @@ -128,6 +185,15 @@ public class Logging { } /** + * Test whether to log 'veryverbose'. + * + * @return true if extra verbose + */ + public boolean isVeryVerbose() { + return logger.isLoggable(Level.VERYVERBOSE); + } + + /** * Test whether to log 'debug' at 'FINE' level. * * This is the same as {@link #isDebuggingFine} @@ -142,7 +208,7 @@ public class Logging { * Test whether to log 'debug' at 'FINE' level * * This is the same as {@link #isDebugging} - * + * * @return true if debug logging enabled */ public boolean isDebuggingFine() { @@ -173,7 +239,7 @@ public class Logging { * @param level Level to log at. * @param message Message to log. */ - public void log(Level level, CharSequence message) { + public void log(java.util.logging.Level level, CharSequence message) { LogRecord rec = new ELKILogRecord(level, message); logger.log(rec); } @@ -185,7 +251,7 @@ public class Logging { * @param message Message to log. * @param e Exception */ - public void log(Level level, CharSequence message, Throwable e) { + public void log(java.util.logging.Level level, CharSequence message, Throwable e) { LogRecord rec = new ELKILogRecord(level, message); rec.setThrown(e); logger.log(rec); @@ -239,6 +305,29 @@ public class Logging { } /** + * Log a message at the 'STATISTICS' level. + * + * You should check isTime() before building the message. + * + * @param message Informational log message. + * @param e Exception + */ + public void statistics(CharSequence message, Throwable e) { + log(Level.STATISTICS, message, e); + } + + /** + * Log a message at the 'STATISTICS' level. + * + * You should check isTime() before building the message. + * + * @param message Informational log message. + */ + public void statistics(CharSequence message) { + log(Level.STATISTICS, message); + } + + /** * Log a message at the 'info' ('verbose') level. * * You should check isVerbose() before building the message. @@ -285,6 +374,29 @@ public class Logging { } /** + * Log a message at the 'veryverbose' level. + * + * You should check isVeryVerbose() before building the message. + * + * @param message Informational log message. + * @param e Exception + */ + public void veryverbose(CharSequence message, Throwable e) { + log(Level.VERYVERBOSE, message, e); + } + + /** + * Log a message at the 'veryverbose' level. + * + * You should check isVeryVerbose() before building the message. + * + * @param message Informational log message. + */ + public void veryverbose(CharSequence message) { + log(Level.VERYVERBOSE, message); + } + + /** * Log a message at the 'fine' debugging level. * * You should check isDebugging() before building the message. @@ -466,7 +578,7 @@ public class Logging { } /** - * Log a Progress object. + * Log a Progress object. * * @param pgr Progress to log. */ @@ -475,9 +587,36 @@ public class Logging { } /** - * @return the wrapped {@link java.util.logging.Logger} + * Generate a new counter. + * + * @param key Key to use + * @return Counter. */ - public Logger getWrappedLogger() { - return logger; + public Counter newCounter(String key) { + return new UnsynchronizedLongCounter(key); + } + + /** + * Generate a new duration statistic. + * + * @param key Key to use + * @return Duration statistic. + */ + public Duration newDuration(String key) { + return new MillisTimeDuration(key); + } + + /** + * Log a statistics object. + * + * @param stats Statistics object to report. + */ + public void statistics(Statistic stats) { + log(Level.STATISTICS, stats.getKey() + ": " + stats.formatValue()); + } + + @Override + public String toString() { + return "Logging(" + logger.getName() + ", " + logger.getLevel() + ")"; } -}
\ No newline at end of file +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java b/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java index b0e7936b..1c609b80 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java +++ b/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,10 +28,10 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Properties; import java.util.logging.Handler; -import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; +import de.lmu.ifi.dbs.elki.logging.Logging.Level; import de.lmu.ifi.dbs.elki.utilities.FileUtil; /** @@ -56,6 +56,21 @@ public final class LoggingConfiguration { private static final String TOPLEVEL_PACKAGE = "de.lmu.ifi.dbs.elki"; /** + * Top level logger. + */ + private static final Logger LOGGER_GLOBAL_TOP = Logger.getLogger(""); + + /** + * Logger for ELKI top level package. + */ + private static final Logger LOGGER_ELKI_TOP = Logger.getLogger(TOPLEVEL_PACKAGE); + + /** + * Logger for ELKI timing. + */ + private static final Logger LOGGER_TIME_TOP = Logger.getLogger(TOPLEVEL_PACKAGE + ".workflow.AlgorithmStep"); + + /** * Configuration base */ private static final String confbase = LoggingConfiguration.class.getPackage().getName(); @@ -92,15 +107,14 @@ public final class LoggingConfiguration { LogManager logManager = LogManager.getLogManager(); Logger logger = Logger.getLogger(LoggingConfiguration.class.getName()); // allow null as package name. - if(pkg == null) { + if (pkg == null) { pkg = ""; } // Load logging configuration from current directory String cfgfile = name; - if(new File(name).exists()) { + if (new File(name).exists()) { cfgfile = name; - } - else { + } else { // Fall back to full path / resources. cfgfile = pkg.replace('.', File.separatorChar) + File.separatorChar + name; } @@ -115,11 +129,9 @@ public final class LoggingConfiguration { DEBUG = Boolean.parseBoolean(cfgprop.getProperty("debug")); logger.info("Logging configuration read."); - } - catch(FileNotFoundException e) { + } catch (FileNotFoundException e) { logger.log(Level.SEVERE, "Could not find logging configuration file: " + cfgfile, e); - } - catch(Exception e) { + } catch (Exception e) { logger.log(Level.SEVERE, "Failed to configure logging from file: " + cfgfile, e); } } @@ -134,49 +146,47 @@ public final class LoggingConfiguration { /** * Reconfigure logging to enable 'verbose' logging at the top level. * - * @param verbose verbose flag - */ - public static void setVerbose(boolean verbose) { - Logger logger1 = Logger.getLogger(""); - Logger logger2 = Logger.getLogger(TOPLEVEL_PACKAGE); - if(verbose) { - // decrease to INFO if it was higher - if(logger1.getLevel() == null || logger1.getLevel().intValue() > Level.INFO.intValue()) { - logger1.setLevel(Level.INFO); + * @param verbose verbosity level. + */ + public static void setVerbose(java.util.logging.Level verbose) { + if (verbose.intValue() <= Level.VERBOSE.intValue()) { + // decrease to VERBOSE if it was higher, otherwise further to VERYVERBOSE + if (LOGGER_GLOBAL_TOP.getLevel() == null || LOGGER_GLOBAL_TOP.getLevel().intValue() > verbose.intValue()) { + LOGGER_GLOBAL_TOP.setLevel(verbose); } - if(logger2.getLevel() == null || logger2.getLevel().intValue() > Level.INFO.intValue()) { - logger2.setLevel(Level.INFO); + if (LOGGER_ELKI_TOP.getLevel() == null || LOGGER_ELKI_TOP.getLevel().intValue() > verbose.intValue()) { + LOGGER_ELKI_TOP.setLevel(verbose); } - } - else { - // increase to warning level if it was INFO. - if(logger1.getLevel() == null || Level.INFO.equals(logger1.getLevel())) { - logger1.setLevel(Level.WARNING); + } else { + // re-increase to given level if it was verbose or "very verbose". + if (LOGGER_GLOBAL_TOP.getLevel() != null && (// + Level.VERBOSE.equals(LOGGER_GLOBAL_TOP.getLevel()) || // + Level.VERYVERBOSE.equals(LOGGER_GLOBAL_TOP.getLevel()) // + )) { + LOGGER_GLOBAL_TOP.setLevel(verbose); } - if(logger2.getLevel() == null || Level.INFO.equals(logger2.getLevel())) { - logger2.setLevel(Level.WARNING); + if (LOGGER_ELKI_TOP.getLevel() != null && (// + Level.VERBOSE.equals(LOGGER_ELKI_TOP.getLevel()) || // + Level.VERYVERBOSE.equals(LOGGER_ELKI_TOP.getLevel()) // + )) { + LOGGER_ELKI_TOP.setLevel(verbose); } } } /** * Enable runtime performance logging. - * - * @param time Flag - */ - public static void setTime(boolean time) { - Logger logger1 = Logger.getLogger("de.lmu.ifi.dbs.elki.workflow.AlgorithmStep"); - if(time) { - // decrease to INFO if it was higher - if(logger1.getLevel() == null || logger1.getLevel().intValue() > Level.INFO.intValue()) { - logger1.setLevel(Level.INFO); - } + */ + public static void setStatistics() { + // decrease to INFO if it was higher + if (LOGGER_GLOBAL_TOP.getLevel() == null || LOGGER_GLOBAL_TOP.getLevel().intValue() > Level.STATISTICS.intValue()) { + LOGGER_GLOBAL_TOP.setLevel(Level.STATISTICS); } - else { - // increase to warning level if it was INFO. - if(logger1.getLevel() != null || logger1.getLevel() == Level.INFO) { - logger1.setLevel(Level.WARNING); - } + if (LOGGER_ELKI_TOP.getLevel() == null || LOGGER_ELKI_TOP.getLevel().intValue() > Level.STATISTICS.intValue()) { + LOGGER_ELKI_TOP.setLevel(Level.STATISTICS); + } + if (LOGGER_TIME_TOP.getLevel() == null || LOGGER_TIME_TOP.getLevel().intValue() > Level.STATISTICS.intValue()) { + LOGGER_TIME_TOP.setLevel(Level.STATISTICS); } } @@ -199,8 +209,8 @@ public final class LoggingConfiguration { */ public static void replaceDefaultHandler(Handler handler) { Logger rootlogger = LogManager.getLogManager().getLogger(""); - for(Handler h : rootlogger.getHandlers()) { - if(h instanceof CLISmartHandler) { + for (Handler h : rootlogger.getHandlers()) { + if (h instanceof CLISmartHandler) { rootlogger.removeHandler(h); } } @@ -216,11 +226,11 @@ public final class LoggingConfiguration { */ public static void setLevelFor(String pkg, String level) throws IllegalArgumentException { Logger logr = Logger.getLogger(pkg); - if(logr == null) { + if (logr == null) { throw new IllegalArgumentException("Logger not found."); } // Can also throw an IllegalArgumentException - Level lev = Level.parse(level); + java.util.logging.Level lev = Level.parse(level); logr.setLevel(lev); } @@ -229,7 +239,7 @@ public final class LoggingConfiguration { * * @param level level */ - public static void setDefaultLevel(Level level) { + public static void setDefaultLevel(java.util.logging.Level level) { Logger.getLogger(TOPLEVEL_PACKAGE).setLevel(level); } -}
\ No newline at end of file +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java b/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java index 1a48fc7a..ce62f419 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java +++ b/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java b/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java index 9c1f6046..6df68224 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java +++ b/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java b/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java index 7bd09da0..7c618ec1 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java +++ b/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/package-info.java b/src/de/lmu/ifi/dbs/elki/logging/package-info.java index cb6f3377..8e20cb09 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/logging/package-info.java @@ -56,7 +56,7 @@ if (verbose) { This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java index 1d196533..ce97b84c 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java index 1ddc02f7..83419ef4 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java index 1dd61674..673ceea7 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java index 74125798..bb2151ba 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java index 64e8214e..8512ba9f 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java index ad3f7c37..c44fd1fd 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -40,7 +40,7 @@ public class ProgressTracker { /** * Set of potentially active progresses. */ - private ArrayList<WeakReference<Progress>> progresses = new ArrayList<WeakReference<Progress>>(); + private ArrayList<WeakReference<Progress>> progresses = new ArrayList<>(); /** * Get a list of progresses tracked. @@ -48,7 +48,7 @@ public class ProgressTracker { * @return List of progresses. */ public synchronized Collection<Progress> getProgresses() { - List<Progress> list = new ArrayList<Progress>(progresses.size()); + List<Progress> list = new ArrayList<>(progresses.size()); Iterator<WeakReference<Progress>> iter = progresses.iterator(); while(iter.hasNext()) { WeakReference<Progress> ref = iter.next(); @@ -82,7 +82,7 @@ public class ProgressTracker { } } } - progresses.add(new WeakReference<Progress>(p)); + progresses.add(new WeakReference<>(p)); } /** @@ -91,7 +91,7 @@ public class ProgressTracker { * @return List of progresses removed. */ public synchronized Collection<Progress> removeCompleted() { - List<Progress> list = new ArrayList<Progress>(progresses.size()); + List<Progress> list = new ArrayList<>(progresses.size()); Iterator<WeakReference<Progress>> iter = progresses.iterator(); while(iter.hasNext()) { WeakReference<Progress> ref = iter.next(); diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java index 1a0d3101..ee1225b6 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java b/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java index 8b25c703..61c53d8d 100644 --- a/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/AbstractStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/AbstractStatistic.java new file mode 100644 index 00000000..8f0b7939 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/AbstractStatistic.java @@ -0,0 +1,56 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Abstract base class for statistics tracking. + * + * @author Erich Schubert + */ +public abstract class AbstractStatistic implements Statistic { + /** + * Key to report the statistic with. + */ + String key; + + /** + * Constructor. + * + * @param key Tracking key + */ + public AbstractStatistic(String key) { + super(); + this.key = key; + } + + @Override + public String getKey() { + return key; + } + + @Override + public String toString() { + return key + ": " + formatValue(); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/AtomicLongCounter.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/AtomicLongCounter.java new file mode 100644 index 00000000..e200d93e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/AtomicLongCounter.java @@ -0,0 +1,72 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.concurrent.atomic.AtomicLong; + +/** + * Class to count events in a thread-safe counter. + * + * @author Erich Schubert + */ +public class AtomicLongCounter extends AbstractStatistic implements Counter { + /** + * The counter to use. + */ + AtomicLong counter = new AtomicLong(0); + + /** + * Constructor. + * + * @param key Key to report. + */ + public AtomicLongCounter(String key) { + super(key); + } + + @Override + public long increment() { + return counter.incrementAndGet(); + } + + @Override + public long decrement() { + return counter.decrementAndGet(); + } + + @Override + public long increment(long i) { + return counter.addAndGet(i); + } + + @Override + public long getValue() { + return counter.get(); + } + + @Override + public String formatValue() { + return Long.toString(getValue()); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java new file mode 100644 index 00000000..0a39f1bd --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java @@ -0,0 +1,62 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Simple statistic by counting. For example: invocations of a method. + * + * @author Erich Schubert + */ +public interface Counter extends Statistic { + /** + * Increment the counter. + * + * @return Current value. + */ + long increment(); + + /** + * Decrement the counter. + * + * @return Current value. + */ + long decrement(); + + /** + * Get the current count. + * + * @return Current count. + */ + long getValue(); + + /** + * Increment the counter by i. + * + * Note: the increment may be negative! + * + * @param i increment. + * @return Current count. + */ + long increment(long i); +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java new file mode 100644 index 00000000..7754ccf1 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java @@ -0,0 +1,72 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.utilities.FormatUtil; + +/** + * Trivial double-valued statistic. + * + * @author Erich Schubert + */ +public class DoubleStatistic extends AbstractStatistic { + /** + * Statistic value. + */ + double value; + + /** + * Constructor. + * + * @param key Key + */ + public DoubleStatistic(String key) { + super(key); + } + + /** + * Constructor. + * + * @param key Key + * @param value Value + */ + public DoubleStatistic(String key, double value) { + super(key); + this.value = value; + } + + /** + * Set the statistics. + * + * @param value New value + */ + public void setDouble(double value) { + this.value = value; + } + + @Override + public String formatValue() { + return FormatUtil.NF.format(value); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java new file mode 100644 index 00000000..24799408 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java @@ -0,0 +1,64 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class that tracks the duration of a task. + * + * TODO: add support for different time units? + * + * @author Erich Schubert + */ +public interface Duration extends Statistic { + /** + * Start the timer. + */ + void begin(); + + /** + * Finish the timer. + */ + void end(); + + /** + * Get the begin of the interval. + * + * @return Begin + */ + long getBegin(); + + /** + * Get the end of the interval. + * + * @return End + */ + long getEnd(); + + /** + * Get the duration of the interval. + * + * @return Duration + */ + long getDuration(); +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java new file mode 100644 index 00000000..5ac805e8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java @@ -0,0 +1,70 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Trivial long-valued statistic. + * + * @author Erich Schubert + */ +public class LongStatistic extends AbstractStatistic { + /** + * Statistic value. + */ + long value; + + /** + * Constructor. + * + * @param key Key + */ + public LongStatistic(String key) { + super(key); + } + + /** + * Constructor. + * + * @param key Key + * @param value Value + */ + public LongStatistic(String key, long value) { + super(key); + this.value = value; + } + + /** + * Set the statistics. + * + * @param value New value + */ + public void setLong(long value) { + this.value = value; + } + + @Override + public String formatValue() { + return Long.toString(value); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java new file mode 100644 index 00000000..9f2cfd64 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java @@ -0,0 +1,75 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class that tracks the runtime of a task with {@code System.nanoTime()} + * + * @author Erich Schubert + */ +public class MillisTimeDuration extends AbstractStatistic implements Duration { + /** + * Tracking variables. + */ + long begin = -1, end = -2; + + /** + * Constructor. + * + * @param key Key + */ + public MillisTimeDuration(String key) { + super(key); + } + + @Override + public void begin() { + begin = System.currentTimeMillis(); + } + + @Override + public void end() { + end = System.currentTimeMillis(); + } + + @Override + public long getBegin() { + return begin; + } + + @Override + public long getEnd() { + return end; + } + + @Override + public long getDuration() { + return (end - begin); + } + + @Override + public String formatValue() { + return getDuration() + " ms"; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java new file mode 100644 index 00000000..77acbbdb --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java @@ -0,0 +1,75 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class that tracks the runtime of a task with {@code System.nanoTime()} + * + * @author Erich Schubert + */ +public class NanoDuration extends AbstractStatistic implements Duration { + /** + * Tracking variables. + */ + long begin = -1, end = -2; + + /** + * Constructor. + * + * @param key Key + */ + public NanoDuration(String key) { + super(key); + } + + @Override + public void begin() { + begin = System.nanoTime(); + } + + @Override + public void end() { + end = System.nanoTime(); + } + + @Override + public long getBegin() { + return begin; + } + + @Override + public long getEnd() { + return end; + } + + @Override + public long getDuration() { + return (end - begin); + } + + @Override + public String formatValue() { + return getDuration() + " ns"; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/Statistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/Statistic.java new file mode 100644 index 00000000..0d1a191a --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/Statistic.java @@ -0,0 +1,45 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Abstract base interface for statistics tracking. + * + * @author Erich Schubert + */ +public interface Statistic { + /** + * Get the key of this statistic. + * + * @return Key + */ + String getKey(); + + /** + * Get a formatted version of the value, for output. + * + * @return Value + */ + String formatValue(); +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java new file mode 100644 index 00000000..2b7faed3 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java @@ -0,0 +1,70 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Trivial string based statistic. + * + * @author Erich Schubert + */ +public class StringStatistic extends AbstractStatistic { + /** + * Storage + */ + private String val; + + /** + * Constructor. + * + * @param key Key + * @param val Value + */ + public StringStatistic(String key, String val) { + super(key); + this.val = val; + } + + /** + * Constructor. + * + * @param key Key + */ + public StringStatistic(String key) { + super(key); + } + + /** + * Set the value. + * + * @param val Value + */ + public void setString(String val) { + this.val = val; + } + + @Override + public String formatValue() { + return val; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/UnsynchronizedLongCounter.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/UnsynchronizedLongCounter.java new file mode 100644 index 00000000..6068b652 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/UnsynchronizedLongCounter.java @@ -0,0 +1,71 @@ +package de.lmu.ifi.dbs.elki.logging.statistics; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class to count events in a thread-safe counter. + * + * @author Erich Schubert + */ +public class UnsynchronizedLongCounter extends AbstractStatistic implements Counter { + /** + * The counter to use. + */ + long counter = 0; + + /** + * Constructor. + * + * @param key Key to report. + */ + public UnsynchronizedLongCounter(String key) { + super(key); + } + + @Override + public long increment() { + return ++counter; + } + + @Override + public long decrement() { + return --counter; + } + + @Override + public long increment(long i) { + counter += i; + return counter; + } + + @Override + public long getValue() { + return counter; + } + + @Override + public String formatValue() { + return Long.toString(getValue()); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java new file mode 100644 index 00000000..ef9f5d98 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java @@ -0,0 +1,24 @@ +/** Classes for logging various statistics. */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.logging.statistics;
\ No newline at end of file |