Skip to content

Commit

Permalink
Add native logger support to RocksJava (#12213)
Browse files Browse the repository at this point in the history
Summary:
## Overview

In this PR, we introduce support for setting the RocksDB native logger through Java. As mentioned in the discussion on the [Google Group discussion](https://groups.google.com/g/rocksdb/c/xYmbEs4sqRM/m/e73E4whJAQAJ), this work is primarily motivated by the  JDK 17 [performance regression in JNI thread attach/detach calls](https://bugs.openjdk.org/browse/JDK-8314859): the only existing RocksJava logging configuration call, `setLogger`, invokes the provided logger over the JNI.

## Changes

Specifically, these changes add support for the `devnull` and `stderr` native loggers. For the `stderr` logger, we add the ability to prefix every log with a `logPrefix`, so that it becomes possible know which database a particular log is coming from (if multiple databases are in use). The  API looks like the following:

```java
Options opts = new Options();

NativeLogger stderrNativeLogger = NativeLogger.newStderrLogger(
  InfoLogLevel.DEBUG_LEVEL, "[my prefix here]");
options.setLogger(stderrNativeLogger);

try (final RocksDB db = RocksDB.open(options, ...))  {...}

// Cleanup
stderrNativeLogger.close()
opts.close();
```

Note that the API to set the logger is the same, via `Options::setLogger` (or `DBOptions::setLogger`). However, it will set the RocksDB logger to be native when  the provided logger is an instance of `NativeLogger`.

## Testing

Two tests have been added in `NativeLoggerTest.java`. The first test creates both the `devnull` and `stderr` loggers, and sets them on the associated `Options`. However, to avoid polluting the testing output with logs from `stderr`, only the `devnull` logger is actually used in the test. The second test does the same logic, but for `DBOptions`.

It is possible to manually verify the `stderr` logger by modifying the tests slightly, and observing that the console indeed gets cluttered with logs from `stderr`.

Pull Request resolved: #12213

Reviewed By: cbi42

Differential Revision: D52772306

Pulled By: ajkr

fbshipit-source-id: 4026895f78f9cc250daf6bfa57427957e2d8b053
  • Loading branch information
neilramaswamy authored and facebook-github-bot committed Jan 18, 2024
1 parent 59ba1d2 commit 4835c11
Show file tree
Hide file tree
Showing 17 changed files with 474 additions and 94 deletions.
6 changes: 6 additions & 0 deletions java/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ set(JNI_NATIVE_SOURCES
rocksjni/sst_partitioner.cc
rocksjni/statistics.cc
rocksjni/statisticsjni.cc
rocksjni/stderr_logger.cc
rocksjni/table.cc
rocksjni/table_filter.cc
rocksjni/table_filter_jnicallback.cc
Expand Down Expand Up @@ -188,6 +189,8 @@ set(JAVA_MAIN_CLASSES
src/main/java/org/rocksdb/LiveFileMetaData.java
src/main/java/org/rocksdb/LogFile.java
src/main/java/org/rocksdb/Logger.java
src/main/java/org/rocksdb/LoggerInterface.java
src/main/java/org/rocksdb/LoggerType.java
src/main/java/org/rocksdb/LRUCache.java
src/main/java/org/rocksdb/MemoryUsageType.java
src/main/java/org/rocksdb/MemoryUtil.java
Expand Down Expand Up @@ -302,6 +305,7 @@ set(JAVA_MAIN_CLASSES
src/test/java/org/rocksdb/WriteBatchTest.java
src/test/java/org/rocksdb/RocksNativeLibraryResource.java
src/test/java/org/rocksdb/util/CapturingWriteBatchHandler.java
src/main/java/org/rocksdb/util/StdErrLogger.java
src/test/java/org/rocksdb/util/WriteBatchGetter.java
)

Expand Down Expand Up @@ -413,6 +417,7 @@ set(JAVA_TEST_CLASSES
src/test/java/org/rocksdb/MemoryUtilTest.java
src/test/java/org/rocksdb/TableFilterTest.java
src/test/java/org/rocksdb/TtlDBTest.java
src/test/java/org/rocksdb/util/StdErrLoggerTest.java
)

set(JAVA_TEST_RUNNING_CLASSES
Expand Down Expand Up @@ -511,6 +516,7 @@ set(JAVA_TEST_RUNNING_CLASSES
org.rocksdb.MemoryUtilTest
org.rocksdb.TableFilterTest
org.rocksdb.TtlDBTest
org.rocksdb.util.StdErrLoggerTest
)

include(FindJava)
Expand Down
6 changes: 4 additions & 2 deletions java/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ NATIVE_JAVA_CLASSES = \
org.rocksdb.WriteOptions\
org.rocksdb.WriteBatchWithIndex\
org.rocksdb.WriteBufferManager\
org.rocksdb.WBWIRocksIterator
org.rocksdb.WBWIRocksIterator\
org.rocksdb.util.StdErrLogger

NATIVE_JAVA_TEST_CLASSES = \
org.rocksdb.RocksDBExceptionTest\
Expand Down Expand Up @@ -206,7 +207,8 @@ JAVA_TESTS = \
org.rocksdb.WriteBatchTest\
org.rocksdb.WriteBatchThreadedTest\
org.rocksdb.WriteOptionsTest\
org.rocksdb.WriteBatchWithIndexTest
org.rocksdb.WriteBatchWithIndexTest\
org.rocksdb.util.StdErrLoggerTest

MAIN_SRC = src/main/java
TEST_SRC = src/test/java
Expand Down
32 changes: 5 additions & 27 deletions java/rocksjni/loggerjnicallback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -224,37 +224,15 @@ LoggerJniCallback::~LoggerJniCallback() {

/*
* Class: org_rocksdb_Logger
* Method: createNewLoggerOptions
* Method: newLogger
* Signature: (J)J
*/
jlong Java_org_rocksdb_Logger_createNewLoggerOptions(JNIEnv* env, jobject jobj,
jlong joptions) {
jlong Java_org_rocksdb_Logger_newLogger(JNIEnv* env, jobject jobj,
jlong jlog_level) {
auto* sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>(
new ROCKSDB_NAMESPACE::LoggerJniCallback(env, jobj));

// set log level
auto* options = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(joptions);
sptr_logger->get()->SetInfoLogLevel(options->info_log_level);

return GET_CPLUSPLUS_POINTER(sptr_logger);
}

/*
* Class: org_rocksdb_Logger
* Method: createNewLoggerDbOptions
* Signature: (J)J
*/
jlong Java_org_rocksdb_Logger_createNewLoggerDbOptions(JNIEnv* env,
jobject jobj,
jlong jdb_options) {
auto* sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>(
new ROCKSDB_NAMESPACE::LoggerJniCallback(env, jobj));

// set log level
auto* db_options =
reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jdb_options);
sptr_logger->get()->SetInfoLogLevel(db_options->info_log_level);

auto log_level = static_cast<ROCKSDB_NAMESPACE::InfoLogLevel>(jlog_level);
sptr_logger->get()->SetInfoLogLevel(log_level);
return GET_CPLUSPLUS_POINTER(sptr_logger);
}

Expand Down
63 changes: 49 additions & 14 deletions java/rocksjni/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "rocksjni/statisticsjni.h"
#include "rocksjni/table_filter_jnicallback.h"
#include "rocksjni/table_properties_collector_factory.h"
#include "util/stderr_logger.h"
#include "utilities/merge_operators.h"

/*
Expand Down Expand Up @@ -1084,14 +1085,31 @@ void Java_org_rocksdb_Options_setSstFileManager(
/*
* Class: org_rocksdb_Options
* Method: setLogger
* Signature: (JJ)V
* Signature: (JJB)V
*/
void Java_org_rocksdb_Options_setLogger(JNIEnv*, jobject, jlong jhandle,
jlong jlogger_handle) {
std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>* pLogger =
reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
jlogger_handle);
reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(jhandle)->info_log = *pLogger;
void Java_org_rocksdb_Options_setLogger(JNIEnv* env, jobject, jlong jhandle,
jlong jlogger_handle,
jbyte jlogger_type) {
auto* options = reinterpret_cast<ROCKSDB_NAMESPACE::Options*>(jhandle);
switch (jlogger_type) {
case 0x1:
// JAVA_IMPLEMENTATION
options->info_log =
*(reinterpret_cast<
std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
jlogger_handle));
break;
case 0x2:
// STDERR_IMPLEMENTATION
options->info_log =
*(reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>*>(
jlogger_handle));
break;
default:
ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
ROCKSDB_NAMESPACE::Slice("Unknown value for LoggerType")));
}
}

/*
Expand Down Expand Up @@ -6148,14 +6166,31 @@ void Java_org_rocksdb_DBOptions_setSstFileManager(
/*
* Class: org_rocksdb_DBOptions
* Method: setLogger
* Signature: (JJ)V
* Signature: (JJB)V
*/
void Java_org_rocksdb_DBOptions_setLogger(JNIEnv*, jobject, jlong jhandle,
jlong jlogger_handle) {
std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>* pLogger =
reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
jlogger_handle);
reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jhandle)->info_log = *pLogger;
void Java_org_rocksdb_DBOptions_setLogger(JNIEnv* env, jobject, jlong jhandle,
jlong jlogger_handle,
jbyte jlogger_type) {
auto* options = reinterpret_cast<ROCKSDB_NAMESPACE::DBOptions*>(jhandle);
switch (jlogger_type) {
case 0x1:
// JAVA_IMPLEMENTATION
options->info_log =
*(reinterpret_cast<
std::shared_ptr<ROCKSDB_NAMESPACE::LoggerJniCallback>*>(
jlogger_handle));
break;
case 0x2:
// STDERR_IMPLEMENTATION
options->info_log =
*(reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>*>(
jlogger_handle));
break;
default:
ROCKSDB_NAMESPACE::IllegalArgumentExceptionJni::ThrowNew(
env, ROCKSDB_NAMESPACE::Status::InvalidArgument(
ROCKSDB_NAMESPACE::Slice("Unknown value for LoggerType")));
}
}

/*
Expand Down
85 changes: 85 additions & 0 deletions java/rocksjni/stderr_logger.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

#include "util/stderr_logger.h"

#include <jni.h>

#include <memory>

#include "include/org_rocksdb_util_StdErrLogger.h"
#include "rocksjni/cplusplus_to_java_convert.h"
#include "rocksjni/portal.h"

/*
* Class: org_rocksdb_util_StdErrLogger
* Method: newStdErrLogger
* Signature: (BLjava/lang/String;)J
*/
jlong Java_org_rocksdb_util_StdErrLogger_newStdErrLogger(JNIEnv* env,
jclass /*jcls*/,
jbyte jlog_level,
jstring jlog_prefix) {
auto log_level = static_cast<ROCKSDB_NAMESPACE::InfoLogLevel>(jlog_level);
std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>* sptr_logger = nullptr;
if (jlog_prefix == nullptr) {
sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>(
new ROCKSDB_NAMESPACE::StderrLogger(log_level));
} else {
jboolean has_exception = JNI_FALSE;
auto log_prefix = ROCKSDB_NAMESPACE::JniUtil::copyStdString(
env, jlog_prefix, &has_exception); // also releases jlog_prefix
if (has_exception == JNI_TRUE) {
return 0;
}
sptr_logger = new std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>(
new ROCKSDB_NAMESPACE::StderrLogger(log_level, log_prefix));
}
return GET_CPLUSPLUS_POINTER(sptr_logger);
}

/*
* Class: org_rocksdb_util_StdErrLogger
* Method: setInfoLogLevel
* Signature: (JB)V
*/
void Java_org_rocksdb_util_StdErrLogger_setInfoLogLevel(JNIEnv* /*env*/,
jclass /*jcls*/,
jlong jhandle,
jbyte jlog_level) {
auto* handle =
reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>*>(
jhandle);
handle->get()->SetInfoLogLevel(
static_cast<ROCKSDB_NAMESPACE::InfoLogLevel>(jlog_level));
}

/*
* Class: org_rocksdb_util_StdErrLogger
* Method: infoLogLevel
* Signature: (J)B
*/
jbyte Java_org_rocksdb_util_StdErrLogger_infoLogLevel(JNIEnv* /*env*/,
jclass /*jcls*/,
jlong jhandle) {
auto* handle =
reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>*>(
jhandle);
return static_cast<jbyte>(handle->get()->GetInfoLogLevel());
}

/*
* Class: org_rocksdb_util_StdErrLogger
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_util_StdErrLogger_disposeInternal(JNIEnv* /*env*/,
jobject /*jobj*/,
jlong jhandle) {
auto* handle =
reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::StderrLogger>*>(
jhandle);
delete handle; // delete std::shared_ptr
}
7 changes: 3 additions & 4 deletions java/src/main/java/org/rocksdb/DBOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,9 @@ public DBOptions setSstFileManager(final SstFileManager sstFileManager) {
}

@Override
public DBOptions setLogger(final Logger logger) {
public DBOptions setLogger(final LoggerInterface logger) {
assert(isOwningHandle());
setLogger(nativeHandle_, logger.nativeHandle_);
setLogger(nativeHandle_, logger.getNativeHandle(), logger.getLoggerType().getValue());
return this;
}

Expand Down Expand Up @@ -1275,8 +1275,7 @@ private native void setRateLimiter(long handle,
long rateLimiterHandle);
private native void setSstFileManager(final long handle,
final long sstFileManagerHandle);
private native void setLogger(long handle,
long loggerHandle);
private native void setLogger(final long handle, final long loggerHandle, final byte loggerType);
private native void setInfoLogLevel(long handle, byte logLevel);
private native byte infoLogLevel(long handle);
private native void setMaxOpenFiles(long handle, int maxOpenFiles);
Expand Down
4 changes: 2 additions & 2 deletions java/src/main/java/org/rocksdb/DBOptionsInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,10 @@ public interface DBOptionsInterface<T extends DBOptionsInterface<T>> {
*
* <p>Default: nullptr</p>
*
* @param logger {@link Logger} instance.
* @param logger {@link LoggerInterface} instance.
* @return the instance of the current object.
*/
T setLogger(Logger logger);
T setLogger(LoggerInterface logger);

/**
* <p>Sets the RocksDB log level. Default level is INFO</p>
Expand Down
Loading

0 comments on commit 4835c11

Please sign in to comment.