Skip to content

Commit c9ea8f7

Browse files
committed
Adds support for logging to the embedded driver
JAVA-2842
1 parent a60d5a7 commit c9ea8f7

File tree

8 files changed

+179
-35
lines changed

8 files changed

+179
-35
lines changed

config/findbugs-exclude.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
<Bug pattern="DE_MIGHT_IGNORE"/>
100100
</Match>
101101

102+
<Match>
103+
<Class name="com.mongodb.embedded.client.MongoDBCAPIHelper$MongoDBCAPIInitParams"/>
104+
<Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"/>
105+
</Match>
102106

103107
<!-- Test exclusions -->
104108
<!-- All bugs in test classes, except for JUnit-specific bugs -->

driver-embedded/src/main/com/mongodb/embedded/client/EmbeddedDatabase.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.io.File;
2626

2727
import static java.lang.String.format;
28-
import static java.util.Arrays.asList;
2928

3029
final class EmbeddedDatabase implements Closeable {
3130
private static final Logger LOGGER = Loggers.getLogger("embedded.client");
@@ -41,8 +40,8 @@ final class EmbeddedDatabase implements Closeable {
4140
throw new MongoException(format("Could not validate / create the dbpath: %s", mongoClientSettings.getDbPath()));
4241
}
4342

44-
String[] cmdArgs = createCmdArgs(mongoClientSettings);
45-
this.databasePointer = MongoDBCAPIHelper.db_new(cmdArgs.length, cmdArgs, createEnvArgs());
43+
String yamlConfig = createYamlConfig(mongoClientSettings);
44+
this.databasePointer = MongoDBCAPIHelper.db_new(yamlConfig);
4645
}
4746

4847
public EmbeddedConnection createConnection() {
@@ -61,15 +60,8 @@ public void close() {
6160
}
6261
}
6362

64-
private String[] createCmdArgs(final MongoClientSettings mongoClientSettings) {
65-
return asList(
66-
"--port=0",
67-
"--storageEngine=mobile",
68-
"--dbpath=" + mongoClientSettings.getDbPath()
69-
).toArray(new String[0]);
63+
private String createYamlConfig(final MongoClientSettings mongoClientSettings) {
64+
return format("{ storage: { dbPath: %s } }", mongoClientSettings.getDbPath());
7065
}
7166

72-
private String[] createEnvArgs() {
73-
return new String[0];
74-
}
7567
}

driver-embedded/src/main/com/mongodb/embedded/client/MongoClients.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ public final class MongoClients {
3535
* @param mongoEmbeddedSettings the settings for the embedded driver.
3636
*/
3737
public static void init(final MongoEmbeddedSettings mongoEmbeddedSettings) {
38-
// TODO - support yaml
39-
MongoDBCAPIHelper.init(mongoEmbeddedSettings, "");
38+
MongoDBCAPIHelper.init(mongoEmbeddedSettings);
4039
}
4140

4241
/**

driver-embedded/src/main/com/mongodb/embedded/client/MongoDBCAPI.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,24 @@
1818

1919
import com.sun.jna.Library;
2020
import com.sun.jna.Pointer;
21+
import com.sun.jna.Structure;
2122
import com.sun.jna.ptr.IntByReference;
2223
import com.sun.jna.ptr.PointerByReference;
2324

2425
interface MongoDBCAPI extends Library {
2526

2627

2728
// CHECKSTYLE.OFF: MethodName
28-
2929
/**
3030
* Initializes the mongodbcapi library, required before any other call. Cannot be called again
3131
* without libmongodbcapi_fini() being called first.
3232
*
33-
* @param config the YAML formatted MongoDB configuration string. See documentation for valid options.
34-
*
33+
* @param initParams the embedded mongod initialization parameters.
34+
3535
* @note This function is not thread safe.
36-
*
3736
* @return the error, or 0 if success
3837
*/
39-
int libmongodbcapi_init(String config);
38+
int libmongodbcapi_init(Structure initParams);
4039

4140
/**
4241
* Tears down the state of the library, all databases must be closed before calling this.
@@ -48,12 +47,10 @@ interface MongoDBCAPI extends Library {
4847
/**
4948
* Create a new db instance.
5049
*
51-
* @param argc the number of arguments
52-
* @param argv the arguments
53-
* @param envp the environment variables
50+
* @param yamlConfig null-terminated YAML formatted MongoDB configuration string
5451
* @return the db pointer
5552
*/
56-
Pointer libmongodbcapi_db_new(int argc, String[] argv, String[] envp);
53+
Pointer libmongodbcapi_db_new(String yamlConfig);
5754

5855
/**
5956
* Destroy a db instance.

driver-embedded/src/main/com/mongodb/embedded/client/MongoDBCAPIHelper.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,23 @@
1818

1919
import com.mongodb.MongoClientException;
2020
import com.mongodb.MongoException;
21+
import com.mongodb.diagnostics.logging.Logger;
22+
import com.mongodb.diagnostics.logging.Loggers;
23+
import com.sun.jna.Callback;
2124
import com.sun.jna.Native;
2225
import com.sun.jna.NativeLibrary;
2326
import com.sun.jna.Pointer;
27+
import com.sun.jna.Structure;
2428
import com.sun.jna.ptr.IntByReference;
2529
import com.sun.jna.ptr.PointerByReference;
2630

31+
import java.util.List;
32+
2733
import static java.lang.String.format;
34+
import static java.util.Arrays.asList;
2835

2936
final class MongoDBCAPIHelper {
37+
private static final Logger LOGGER = Loggers.getLogger("embedded.server");
3038
private static final String NATIVE_LIBRARY_NAME = "mongo_embedded_capi";
3139
private static volatile MongoDBCAPI mongoDBCAPI;
3240

@@ -35,8 +43,7 @@ static synchronized void checkHasBeenInitialized() {
3543
}
3644

3745
// CHECKSTYLE.OFF: MethodName
38-
39-
static synchronized void init(final MongoEmbeddedSettings mongoEmbeddedSettings, final String config) {
46+
static synchronized void init(final MongoEmbeddedSettings mongoEmbeddedSettings) {
4047
if (mongoDBCAPI != null) {
4148
throw new MongoClientException("MongoDBCAPI has been initialized but not closed");
4249
}
@@ -57,7 +64,7 @@ static synchronized void init(final MongoEmbeddedSettings mongoEmbeddedSettings,
5764
+ "%n", NATIVE_LIBRARY_NAME, e.getMessage()), e);
5865
}
5966
try {
60-
validateErrorCode(mongoDBCAPI.libmongodbcapi_init(config));
67+
validateErrorCode(mongoDBCAPI.libmongodbcapi_init(new MongoDBCAPIInitParams(mongoEmbeddedSettings)));
6168
} catch (Throwable t) {
6269
throw createError("init", t);
6370
}
@@ -73,10 +80,10 @@ static synchronized void fini() {
7380
}
7481
}
7582

76-
static Pointer db_new(final int argc, final String[] argv, final String[] envp) {
83+
static Pointer db_new(final String yamlConfig) {
7784
checkInitialized();
7885
try {
79-
return mongoDBCAPI.libmongodbcapi_db_new(argc, argv, envp);
86+
return mongoDBCAPI.libmongodbcapi_db_new(yamlConfig);
8087
} catch (Throwable t) {
8188
throw createError("db_new", t);
8289
}
@@ -165,4 +172,45 @@ private static void checkInitialized() {
165172

166173
private MongoDBCAPIHelper() {
167174
}
175+
176+
/**
177+
* Represents libmongodbcapi_init_params
178+
*/
179+
public static class MongoDBCAPIInitParams extends Structure {
180+
// CHECKSTYLE.OFF: VisibilityModifier
181+
public String yamlConfig;
182+
public long logFlags;
183+
public Callback logCallback;
184+
public String userData;
185+
// CHECKSTYLE.ON: VisibilityModifier
186+
187+
MongoDBCAPIInitParams(final MongoEmbeddedSettings settings) {
188+
super();
189+
this.yamlConfig = settings.getYamlConfig();
190+
this.logFlags = settings.getLogLevel().getLevel();
191+
this.logCallback = settings.getLogLevel() == MongoEmbeddedSettings.LogLevel.LOGGER ? new LogCallback() : null;
192+
}
193+
194+
protected List<String> getFieldOrder() {
195+
return asList("yamlConfig", "logFlags", "logCallback", "userData");
196+
}
197+
}
198+
199+
static class LogCallback implements Callback {
200+
201+
public void apply(final String userData, final String message, final String component, final String context,
202+
final int severity) {
203+
String logMessage = format("%-9s [%s] %s", component.toUpperCase(), context, message).trim();
204+
205+
if (severity < -2) {
206+
LOGGER.error(logMessage); // Severe/Fatal & Error messages
207+
} else if (severity == -2) {
208+
LOGGER.warn(logMessage); // Warning messages
209+
} else if (severity < 1) {
210+
LOGGER.info(logMessage); // Info / Log messages
211+
} else {
212+
LOGGER.debug(logMessage); // Debug messages
213+
}
214+
}
215+
}
168216
}

driver-embedded/src/main/com/mongodb/embedded/client/MongoEmbeddedSettings.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,48 @@
3030
@Immutable
3131
public final class MongoEmbeddedSettings {
3232
private final String libraryPath;
33+
private final String yamlConfig;
34+
private final LogLevel logLevel;
35+
36+
/**
37+
* LogLevel represents the supported logging levels for the embedded mongod
38+
*/
39+
public enum LogLevel {
40+
/**
41+
* Turn off logging
42+
*/
43+
NONE(0),
44+
45+
/**
46+
* Log to stdout
47+
*/
48+
STDOUT(1),
49+
50+
/**
51+
* Log to stderr
52+
*/
53+
STDERR(2),
54+
55+
/**
56+
* Log via the {@code org.mongodb.embedded.server} logger
57+
*
58+
* @see com.mongodb.diagnostics.logging.Logger
59+
*/
60+
LOGGER(4);
61+
62+
private final int level;
63+
64+
/**
65+
* @return the logging level
66+
*/
67+
public int getLevel(){
68+
return level;
69+
}
70+
71+
LogLevel(final int level){
72+
this.level = level;
73+
}
74+
}
3375

3476
/**
3577
* Convenience method to create a Builder.
@@ -57,13 +99,17 @@ public static Builder builder(final MongoEmbeddedSettings settings) {
5799
@NotThreadSafe
58100
public static final class Builder {
59101
private String libraryPath;
102+
private String yamlConfig;
103+
private LogLevel logLevel = LogLevel.LOGGER;
60104

61105
private Builder() {
62106
}
63107

64108
private Builder(final MongoEmbeddedSettings settings) {
65109
notNull("settings", settings);
66110
libraryPath = settings.libraryPath;
111+
yamlConfig = settings.yamlConfig;
112+
logLevel = settings.logLevel;
67113
}
68114

69115
/**
@@ -77,6 +123,29 @@ public Builder libraryPath(final String libraryPath) {
77123
return this;
78124
}
79125

126+
/**
127+
* Sets the yaml configuration for mongod.
128+
*
129+
* @param yamlConfig the yaml configuration for mongod
130+
* @return this
131+
* @mongodb.driver.manual reference/configuration-options/
132+
*/
133+
public Builder yamlConfig(final String yamlConfig) {
134+
this.yamlConfig = yamlConfig;
135+
return this;
136+
}
137+
138+
/**
139+
* Sets the logging level for the mongod.
140+
*
141+
* @param logLevel the library path for mongod
142+
* @return this
143+
*/
144+
public Builder logLevel(final LogLevel logLevel) {
145+
this.logLevel = logLevel;
146+
return this;
147+
}
148+
80149
/**
81150
* Build an instance of {@code MongoClientSettings}.
82151
*
@@ -96,7 +165,28 @@ public String getLibraryPath() {
96165
return libraryPath;
97166
}
98167

168+
/**
169+
* Returns the yaml configuration for mongod.
170+
*
171+
* @return the yaml configuration for mongod
172+
* @mongodb.driver.manual reference/configuration-options/
173+
*/
174+
public String getYamlConfig() {
175+
return yamlConfig;
176+
}
177+
178+
/**
179+
* Gets the logging level for the embedded mongod
180+
*
181+
* @return the logging level
182+
*/
183+
public LogLevel getLogLevel() {
184+
return logLevel;
185+
}
186+
99187
private MongoEmbeddedSettings(final Builder builder) {
100188
this.libraryPath = builder.libraryPath;
189+
this.yamlConfig = builder.yamlConfig;
190+
this.logLevel = builder.logLevel;
101191
}
102192
}

driver-embedded/src/test/functional/com/mongodb/embedded/client/Fixture.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import com.mongodb.client.MongoClient;
2222
import com.mongodb.client.MongoDatabase;
2323
import com.mongodb.connection.ServerVersion;
24-
import com.sun.jna.Native;
2524
import org.bson.BsonDocument;
2625
import org.bson.BsonValue;
2726
import org.bson.Document;
@@ -53,7 +52,6 @@ private Fixture() {
5352
static synchronized MongoClient getMongoClient() {
5453
if (mongoClient == null) {
5554
cleanDBPath();
56-
Native.setProtected(true);
5755
MongoClients.init(getMongoEmbeddedSettings());
5856
mongoClient = MongoClients.create(getMongoClientSettings());
5957
Runtime.getRuntime().addShutdownHook(new ShutdownHook());
@@ -126,7 +124,10 @@ static synchronized MongoClientSettings getMongoClientSettings() {
126124

127125
static synchronized MongoEmbeddedSettings getMongoEmbeddedSettings() {
128126
if (mongoEmbeddedSettings == null) {
129-
mongoEmbeddedSettings = MongoEmbeddedSettings.builder().libraryPath(System.getProperty(EMBEDDED_PATH_PROPERTY_NAME)).build();
127+
mongoEmbeddedSettings = MongoEmbeddedSettings.builder()
128+
.libraryPath(System.getProperty(EMBEDDED_PATH_PROPERTY_NAME))
129+
.logLevel(MongoEmbeddedSettings.LogLevel.LOGGER)
130+
.build();
130131
}
131132
return mongoEmbeddedSettings;
132133
}

0 commit comments

Comments
 (0)