Skip to content

Commit 752c1ea

Browse files
authored
Merge pull request #6 from oracle/feature/clientStats
Add client statistics feature. The following stats are collected for each type of request: count, latencies, request and response sizes, errors, retries, retry delay, rate limit delay, these stats can also be shown per query and also number of used concomitent opened connections. Stats are collected on the client application, when system property -Dcom.oracle.nosql.sdk.nosqldriver.stats.profile=[none|regular|more|all] is used, for an interval of time, set by -Dcom.oracle.nosql.sdk.nosqldriver.stats.interval=600 in seconds. NoSQLHandleConfig and StatsControl also provides an API to programmatically configure the statistics collection, to selectively start and stop collection and get access to collected statistics.
2 parents 040f979 + 7fe4557 commit 752c1ea

26 files changed

+1505
-15
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
All notable changes to this project will be documented in this file.
33

44
The format is based on [Keep a Changelog](http://keepachangelog.com/).
5+
6+
## [Unreleased]
7+
8+
### Added
9+
- Added client statistics. Users can enable internal driver statistics by
10+
using system property -Dcom.oracle.nosql.sdk.nosqldriver.stats.profile=
11+
[none|regular|more|all] or by using the NoSQLConfig.setStatsProfile() api.
12+
513
## [5.2.29-SNAPSHOT] 2021-09-30
614

715
### Changed

driver/src/main/java/oracle/nosql/driver/NoSQLHandle.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,13 @@ public SystemResult doSystemRequest(String statement,
571571
int timeoutMs,
572572
int pollIntervalMs);
573573

574+
/**
575+
* Returns an object that allows control over how statistics are collected.
576+
*
577+
* @return the StatsControl object
578+
*/
579+
public StatsControl getStatsControl();
580+
574581
/**
575582
* Closes the handle, releasing its memory and network resources. Once
576583
* this method is closed the handle is no longer usable. Any attempt to

driver/src/main/java/oracle/nosql/driver/NoSQLHandleConfig.java

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
import java.util.HashSet;
1717
import java.util.List;
1818
import java.util.Set;
19+
import java.util.logging.Level;
1920
import java.util.logging.Logger;
2021

21-
import io.netty.handler.ssl.SslContext;
2222
import oracle.nosql.driver.Region.RegionProvider;
2323
import oracle.nosql.driver.iam.SignatureProvider;
2424

25+
import io.netty.handler.ssl.SslContext;
26+
2527
/**
2628
* NoSQLHandleConfig groups parameters used to configure a {@link
2729
* NoSQLHandle}. It also provides a way to default common parameters for use by
@@ -196,6 +198,21 @@ public class NoSQLHandleConfig implements Cloneable {
196198
private String proxyUsername;
197199
private String proxyPassword;
198200

201+
/**
202+
* Statistics configuration, optional.
203+
*/
204+
private final static String PROFILE_PROPERTY =
205+
"com.oracle.nosql.sdk.nosqldriver.stats.profile";
206+
private final static String INTERVAL_PROPERTY =
207+
"com.oracle.nosql.sdk.nosqldriver.stats.interval";
208+
private final static String PRETTY_PRINT_PROPERTY =
209+
"com.oracle.nosql.sdk.nosqldriver.stats.pretty-print";
210+
/* Statistics logging interval in seconds. Default 600 sec, ie. 10 min. */
211+
private int statsInterval = 600;
212+
private StatsControl.Profile statsProfile = StatsControl.Profile.NONE;
213+
private boolean statsPrettyPrint = false;
214+
private StatsControl.StatsHandler statsHandler = null;
215+
199216
/**
200217
* Specifies an endpoint or region id to use to connect to the Oracle
201218
* NoSQL Database Cloud Service or, if on-premise, the Oracle NoSQL
@@ -240,6 +257,7 @@ public NoSQLHandleConfig(String endpoint) {
240257
super();
241258
endpoint = checkRegionId(endpoint, null);
242259
this.serviceURL = createURL(endpoint, "/");
260+
setConfigFromEnvironment();
243261
}
244262

245263
/**
@@ -290,6 +308,7 @@ public NoSQLHandleConfig(String endpoint, AuthorizationProvider provider) {
290308
endpoint = checkRegionId(endpoint, provider);
291309
this.serviceURL = createURL(endpoint, "/");
292310
this.authProvider = provider;
311+
setConfigFromEnvironment();
293312
}
294313

295314
/**
@@ -313,6 +332,7 @@ public NoSQLHandleConfig(Region region, AuthorizationProvider provider) {
313332
this.serviceURL = createURL(region.endpoint(), "/");
314333
this.region = region;
315334
this.authProvider = provider;
335+
setConfigFromEnvironment();
316336
}
317337

318338
/**
@@ -339,6 +359,7 @@ public NoSQLHandleConfig(AuthorizationProvider provider) {
339359
}
340360
this.serviceURL = createURL(region.endpoint(), "/");
341361
this.authProvider = provider;
362+
setConfigFromEnvironment();
342363
}
343364

344365
/**
@@ -1184,6 +1205,100 @@ public SslContext getSslContext() {
11841205
return sslCtx;
11851206
}
11861207

1208+
/**
1209+
* Sets interval size in seconds for logging statistics.
1210+
* Default interval is 600 seconds, i.e. 10 min.
1211+
*
1212+
* @param statsInterval stats logging interval in seconds
1213+
* @return this
1214+
*/
1215+
public NoSQLHandleConfig setStatsInterval(int statsInterval) {
1216+
if (statsInterval < 1) {
1217+
throw new IllegalArgumentException("Stats interval can not be " +
1218+
"less than 1 second.");
1219+
}
1220+
this.statsInterval = statsInterval;
1221+
return this;
1222+
}
1223+
1224+
/**
1225+
* Returns the current interval for logging statistics.
1226+
* Default interval is 600 seconds, i.e. 10 min.
1227+
*
1228+
* @return the current interval in seconds
1229+
*/
1230+
public int getStatsInterval() {
1231+
return this.statsInterval;
1232+
}
1233+
1234+
/**
1235+
* Set the statistics collection profile.
1236+
* Default profile is NONE.
1237+
*
1238+
* @param statsProfile profile to use
1239+
* @return this
1240+
*/
1241+
public NoSQLHandleConfig setStatsProfile(StatsControl.Profile statsProfile)
1242+
{
1243+
this.statsProfile = statsProfile;
1244+
return this;
1245+
}
1246+
1247+
/**
1248+
* Returns the statistics collection profile.
1249+
* Default profile is NONE.
1250+
*
1251+
* @return the current profile
1252+
*/
1253+
public StatsControl.Profile getStatsProfile() {
1254+
return this.statsProfile;
1255+
}
1256+
1257+
/**
1258+
* Enable JSON pretty print for easier human reading when logging
1259+
* statistics.
1260+
* Default is disabled.
1261+
*
1262+
* @param statsPrettyPrint flag to enable JSON pretty print
1263+
* @return this
1264+
*/
1265+
public NoSQLHandleConfig setStatsPrettyPrint(boolean statsPrettyPrint) {
1266+
this.statsPrettyPrint = statsPrettyPrint;
1267+
return this;
1268+
}
1269+
1270+
/**
1271+
* Returns the current JSON pretty print flag for logging statistics.
1272+
* Default is disabled.
1273+
*
1274+
* @return the current JSON pretty print flag
1275+
*/
1276+
public boolean getStatsPrettyPrint() {
1277+
return this.statsPrettyPrint;
1278+
}
1279+
1280+
/**
1281+
* Registers a handler that is called every time the statistics are logged.
1282+
* Note: setting a stats handler will not affect the stats log entries.
1283+
* @param statsHandler User defined StatsHandler.
1284+
*
1285+
* @return this
1286+
*/
1287+
public NoSQLHandleConfig setStatsHandler(
1288+
StatsControl.StatsHandler statsHandler) {
1289+
this.statsHandler = statsHandler;
1290+
return this;
1291+
}
1292+
1293+
/**
1294+
* Returns the registered statistics handler, otherwise null.
1295+
*
1296+
* @return this
1297+
*/
1298+
public StatsControl.StatsHandler getStatsHandler() {
1299+
return this.statsHandler;
1300+
}
1301+
11871302
@Override
11881303
public NoSQLHandleConfig clone() {
11891304
try {
@@ -1220,4 +1335,39 @@ static private void checkRegion(Region region,
12201335
}
12211336
}
12221337

1338+
private void setConfigFromEnvironment() {
1339+
String profileProp = System.getProperty(PROFILE_PROPERTY);
1340+
if (profileProp != null) {
1341+
try {
1342+
setStatsProfile(StatsControl.Profile.valueOf(
1343+
profileProp.toUpperCase()));
1344+
} catch (IllegalArgumentException iae) {
1345+
if (logger != null) {
1346+
logger.log(Level.SEVERE, StatsControl.LOG_PREFIX +
1347+
"Invalid profile value for system property " +
1348+
PROFILE_PROPERTY + ": " + profileProp);
1349+
}
1350+
}
1351+
}
1352+
1353+
String intervalProp = System.getProperty(INTERVAL_PROPERTY);
1354+
if (intervalProp != null) {
1355+
try {
1356+
setStatsInterval(Integer.valueOf(intervalProp));
1357+
} catch (NumberFormatException nfe) {
1358+
if (logger != null) {
1359+
logger.log(Level.SEVERE, "Invalid integer value for " +
1360+
"system property " + INTERVAL_PROPERTY + ": " +
1361+
intervalProp);
1362+
}
1363+
}
1364+
}
1365+
1366+
String ppProp = System.getProperty(PRETTY_PRINT_PROPERTY);
1367+
if (ppProp != null &&
1368+
("true".equals(ppProp.toLowerCase()) || "1".equals(ppProp) ||
1369+
"on".equals(ppProp.toLowerCase()))) {
1370+
statsPrettyPrint = Boolean.valueOf(ppProp);
1371+
}
1372+
}
12231373
}

0 commit comments

Comments
 (0)