Skip to content

Commit 758b829

Browse files
Frank-Gu-81QuChen88
authored andcommitted
added metrics JdbcCachedQueryCount, JdbcCacheMissCount, JdbcCacheBypassCount, and JdbcCachedQueryAfterUpdate (PR #3)
JdbcCachedQueryAfterUpdate feature removed Add OpenTelemetry integration for cache latency monitoring fixed variable naming, added one more context for latency tracking took out cacheMissContext and removed dbContext setSuccess logging removed redundant variables handled closing cacheContext for SQLException and removed dbContext error handling minor syntax fix updated unit tests for the latest telemetry metrics
1 parent 5409868 commit 758b829

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)