Skip to content

Commit 59cdb03

Browse files
authored
Merge pull request #3 from QuChen88/shpenggu
Build metrics for JdbcCachedQueryCount, JdbcCacheMissCount, JdbcCacheBypassCount, and query latency metrics
2 parents 9bc7de1 + d92863e commit 59cdb03

File tree

2 files changed

+268
-89
lines changed

2 files changed

+268
-89
lines changed

wrapper/src/main/java/software/amazon/jdbc/plugin/cache/DataRemoteCachePlugin.java

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@
3636
import software.amazon.jdbc.util.WrapperUtils;
3737
import software.amazon.jdbc.util.telemetry.TelemetryCounter;
3838
import software.amazon.jdbc.util.telemetry.TelemetryFactory;
39+
import software.amazon.jdbc.util.telemetry.TelemetryContext;
40+
import software.amazon.jdbc.util.telemetry.TelemetryTraceLevel;
3941

4042
public class DataRemoteCachePlugin extends AbstractConnectionPlugin {
4143
private static final Logger LOGGER = Logger.getLogger(DataRemoteCachePlugin.class.getName());
44+
private static final int MAX_CACHEABLE_QUERY_SIZE = 16000;
4245
private static final String QUERY_HINT_START_PATTERN = "/*+";
4346
private static final String QUERY_HINT_END_PATTERN = "*/";
4447
private static final String CACHE_PARAM_PATTERN = "CACHE_PARAM(";
48+
private static final String TELEMETRY_CACHE_LOOKUP = "jdbc-cache-lookup";
49+
private static final String TELEMETRY_DATABASE_QUERY = "jdbc-database-query";
4550
private static final Set<String> subscribedMethods = Collections.unmodifiableSet(new HashSet<>(
4651
Arrays.asList(JdbcMethod.STATEMENT_EXECUTEQUERY.methodName,
4752
JdbcMethod.STATEMENT_EXECUTE.methodName,
@@ -52,10 +57,11 @@ public class DataRemoteCachePlugin extends AbstractConnectionPlugin {
5257

5358
private PluginService pluginService;
5459
private TelemetryFactory telemetryFactory;
55-
private TelemetryCounter hitCounter;
56-
private TelemetryCounter missCounter;
57-
private TelemetryCounter totalCallsCounter;
60+
private TelemetryCounter cacheHitCounter;
61+
private TelemetryCounter cacheMissCounter;
62+
private TelemetryCounter totalQueryCounter;
5863
private TelemetryCounter malformedHintCounter;
64+
private TelemetryCounter cacheBypassCounter;
5965
private CacheConnection cacheConnection;
6066

6167
public DataRemoteCachePlugin(final PluginService pluginService, final Properties properties) {
@@ -67,10 +73,11 @@ public DataRemoteCachePlugin(final PluginService pluginService, final Properties
6773
}
6874
this.pluginService = pluginService;
6975
this.telemetryFactory = pluginService.getTelemetryFactory();
70-
this.hitCounter = telemetryFactory.createCounter("remoteCache.cache.hit");
71-
this.missCounter = telemetryFactory.createCounter("remoteCache.cache.miss");
72-
this.totalCallsCounter = telemetryFactory.createCounter("remoteCache.cache.totalCalls");
76+
this.cacheHitCounter = telemetryFactory.createCounter("JdbcCachedQueryCount");
77+
this.cacheMissCounter = telemetryFactory.createCounter("JdbcCacheMissCount");
78+
this.totalQueryCounter = telemetryFactory.createCounter("JdbcCacheTotalQueryCount");
7379
this.malformedHintCounter = telemetryFactory.createCounter("JdbcCacheMalformedQueryHint");
80+
this.cacheBypassCounter = telemetryFactory.createCounter("JdbcCacheBypassCount");
7481
this.cacheConnection = new CacheConnection(properties);
7582
}
7683

@@ -223,45 +230,77 @@ public <T, E extends Exception> T execute(
223230
boolean needToCache = false;
224231
final String sql = getQuery(jdbcMethodArgs);
225232

233+
TelemetryContext cacheContext = null;
234+
TelemetryContext dbContext = null;
226235
// If the query is cacheable, we try to fetch the query result from the cache.
227236
boolean isInTransaction = pluginService.isInTransaction();
228237
// Get the query hint part in front of the query itself
229238
String mainQuery = sql; // The main part of the query with the query hint prefix trimmed
230239
int endOfQueryHint = 0;
231240
Integer configuredQueryTtl = null;
232241
// Queries longer than 16KB is not cacheable
233-
if ((sql.length() < 16000) && sql.startsWith(QUERY_HINT_START_PATTERN)) {
242+
if ((sql.length() < MAX_CACHEABLE_QUERY_SIZE) && sql.startsWith(QUERY_HINT_START_PATTERN)) {
234243
endOfQueryHint = sql.indexOf(QUERY_HINT_END_PATTERN);
235244
if (endOfQueryHint > 0) {
236245
configuredQueryTtl = getTtlForQuery(sql.substring(2, endOfQueryHint).trim());
237246
mainQuery = sql.substring(endOfQueryHint + 2).trim();
238247
}
239248
}
240249

250+
incrCounter(totalQueryCounter);
251+
241252
// Query result can be served from the cache if it has a configured TTL value, and it is
242253
// not executed in a transaction as a transaction typically need to return consistent results.
243254
if (!isInTransaction && (configuredQueryTtl != null)) {
244-
incrCounter(totalCallsCounter);
245-
result = fetchResultSetFromCache(mainQuery);
246-
if (result == null) {
247-
// Cache miss. Need to fetch result from the database
248-
needToCache = true;
249-
incrCounter(missCounter);
250-
LOGGER.finest("Got a cache miss for SQL: " + sql);
251-
} else {
252-
LOGGER.finest("Got a cache hit for SQL: " + sql);
253-
// Cache hit. Return the cached result
254-
incrCounter(hitCounter);
255-
try {
256-
result.beforeFirst();
257-
} catch (final SQLException ex) {
258-
throw WrapperUtils.wrapExceptionIfNeeded(exceptionClass, ex);
255+
cacheContext = telemetryFactory.openTelemetryContext(
256+
TELEMETRY_CACHE_LOOKUP, TelemetryTraceLevel.TOP_LEVEL);
257+
Exception cacheException = null;
258+
try{
259+
result = fetchResultSetFromCache(mainQuery);
260+
if (result == null) {
261+
// Cache miss. Need to fetch result from the database
262+
needToCache = true;
263+
incrCounter(cacheMissCounter);
264+
LOGGER.finest("Got a cache miss for SQL: " + sql);
265+
} else {
266+
LOGGER.finest("Got a cache hit for SQL: " + sql);
267+
// Cache hit. Return the cached result
268+
incrCounter(cacheHitCounter);
269+
try {
270+
result.beforeFirst();
271+
} catch (final SQLException ex) {
272+
cacheException = ex;
273+
throw WrapperUtils.wrapExceptionIfNeeded(exceptionClass, ex);
274+
}
275+
return resultClass.cast(result);
276+
}
277+
} finally {
278+
if (cacheContext != null) {
279+
if (cacheException != null) {
280+
cacheContext.setSuccess(false);
281+
cacheContext.setException(cacheException);
282+
cacheContext.closeContext();
283+
} else if (!needToCache) { // Cache hit
284+
cacheContext.setSuccess(true);
285+
cacheContext.closeContext();
286+
} else { // Cache miss - leave context open
287+
cacheContext.setSuccess(false);
288+
}
259289
}
260-
return resultClass.cast(result);
261290
}
291+
} else {
292+
incrCounter(cacheBypassCounter);
262293
}
263294

264-
result = (ResultSet) jdbcMethodFunc.call();
295+
dbContext = telemetryFactory.openTelemetryContext(
296+
TELEMETRY_DATABASE_QUERY, TelemetryTraceLevel.TOP_LEVEL);
297+
298+
try {
299+
result = (ResultSet) jdbcMethodFunc.call();
300+
} finally {
301+
if (dbContext != null) dbContext.closeContext();
302+
if (cacheContext != null) cacheContext.closeContext();
303+
}
265304

266305
// We need to cache the query result if we got a cache miss for the query result,
267306
// or the query is cacheable and executed inside a transaction.

0 commit comments

Comments
 (0)