1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 package org.rocksdb;
7 
8 /**
9  * <p>This class provides a custom logger functionality
10  * in Java which wraps {@code RocksDB} logging facilities.
11  * </p>
12  *
13  * <p>Using this class RocksDB can log with common
14  * Java logging APIs like Log4j or Slf4j without keeping
15  * database logs in the filesystem.</p>
16  *
17  * <strong>Performance</strong>
18  * <p>There are certain performance penalties using a Java
19  * {@code Logger} implementation within production code.
20  * </p>
21  *
22  * <p>
23  * A log level can be set using {@link org.rocksdb.Options} or
24  * {@link Logger#setInfoLogLevel(InfoLogLevel)}. The set log level
25  * influences the underlying native code. Each log message is
26  * checked against the set log level and if the log level is more
27  * verbose as the set log level, native allocations will be made
28  * and data structures are allocated.
29  * </p>
30  *
31  * <p>Every log message which will be emitted by native code will
32  * trigger expensive native to Java transitions. So the preferred
33  * setting for production use is either
34  * {@link org.rocksdb.InfoLogLevel#ERROR_LEVEL} or
35  * {@link org.rocksdb.InfoLogLevel#FATAL_LEVEL}.
36  * </p>
37  */
38 public abstract class Logger extends RocksCallbackObject {
39 
40   private final static long WITH_OPTIONS = 0;
41   private final static long WITH_DBOPTIONS = 1;
42 
43   /**
44    * <p>AbstractLogger constructor.</p>
45    *
46    * <p><strong>Important:</strong> the log level set within
47    * the {@link org.rocksdb.Options} instance will be used as
48    * maximum log level of RocksDB.</p>
49    *
50    * @param options {@link org.rocksdb.Options} instance.
51    */
Logger(final Options options)52   public Logger(final Options options) {
53     super(options.nativeHandle_, WITH_OPTIONS);
54 
55   }
56 
57   /**
58    * <p>AbstractLogger constructor.</p>
59    *
60    * <p><strong>Important:</strong> the log level set within
61    * the {@link org.rocksdb.DBOptions} instance will be used
62    * as maximum log level of RocksDB.</p>
63    *
64    * @param dboptions {@link org.rocksdb.DBOptions} instance.
65    */
Logger(final DBOptions dboptions)66   public Logger(final DBOptions dboptions) {
67     super(dboptions.nativeHandle_, WITH_DBOPTIONS);
68   }
69 
70   @Override
initializeNative(long... nativeParameterHandles)71   protected long initializeNative(long... nativeParameterHandles) {
72     if(nativeParameterHandles[1] == WITH_OPTIONS) {
73       return createNewLoggerOptions(nativeParameterHandles[0]);
74     } else if(nativeParameterHandles[1] == WITH_DBOPTIONS) {
75       return createNewLoggerDbOptions(nativeParameterHandles[0]);
76     } else {
77       throw new IllegalArgumentException();
78     }
79   }
80 
81   /**
82    * Set {@link org.rocksdb.InfoLogLevel} to AbstractLogger.
83    *
84    * @param infoLogLevel {@link org.rocksdb.InfoLogLevel} instance.
85    */
setInfoLogLevel(final InfoLogLevel infoLogLevel)86   public void setInfoLogLevel(final InfoLogLevel infoLogLevel) {
87       setInfoLogLevel(nativeHandle_, infoLogLevel.getValue());
88   }
89 
90   /**
91    * Return the loggers log level.
92    *
93    * @return {@link org.rocksdb.InfoLogLevel} instance.
94    */
infoLogLevel()95   public InfoLogLevel infoLogLevel() {
96     return InfoLogLevel.getInfoLogLevel(
97         infoLogLevel(nativeHandle_));
98   }
99 
log(InfoLogLevel infoLogLevel, String logMsg)100   protected abstract void log(InfoLogLevel infoLogLevel,
101       String logMsg);
102 
createNewLoggerOptions( long options)103   protected native long createNewLoggerOptions(
104       long options);
createNewLoggerDbOptions( long dbOptions)105   protected native long createNewLoggerDbOptions(
106       long dbOptions);
setInfoLogLevel(long handle, byte infoLogLevel)107   protected native void setInfoLogLevel(long handle,
108       byte infoLogLevel);
infoLogLevel(long handle)109   protected native byte infoLogLevel(long handle);
110 
111   /**
112    * We override {@link RocksCallbackObject#disposeInternal()}
113    * as disposing of a rocksdb::LoggerJniCallback requires
114    * a slightly different approach as it is a std::shared_ptr
115    */
116   @Override
disposeInternal()117   protected void disposeInternal() {
118     disposeInternal(nativeHandle_);
119   }
120 
disposeInternal(final long handle)121   private native void disposeInternal(final long handle);
122 }
123