Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: add metrics to capture acquired and released sessions data (#67)
* add acquired and released sessions data

* update the description

* update the description

* Apply skuruppu@'s recommendations

* apply olavloite@'s recommendations

* minor fix

* attempt to fix build
  • Loading branch information
mayurkale22 committed Feb 27, 2020
1 parent 3f32f51 commit 94d0557
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
Expand Up @@ -46,6 +46,8 @@ class MetricRegistryConstants {
static final String MAX_ALLOWED_SESSIONS = "cloud.google.com/java/spanner/max_allowed_sessions";
static final String IN_USE_SESSIONS = "cloud.google.com/java/spanner/in_use_sessions";
static final String GET_SESSION_TIMEOUTS = "cloud.google.com/java/spanner/get_session_timeouts";
static final String NUM_ACQUIRED_SESSIONS = "cloud.google.com/java/spanner/num_acquired_sessions";
static final String NUM_RELEASED_SESSIONS = "cloud.google.com/java/spanner/num_released_sessions";

static final String MAX_IN_USE_SESSIONS_DESCRIPTION =
"The maximum number of sessions in use during the last 10 minute interval.";
Expand All @@ -54,4 +56,8 @@ class MetricRegistryConstants {
static final String IN_USE_SESSIONS_DESCRIPTION = "The number of sessions currently in use.";
static final String SESSIONS_TIMEOUTS_DESCRIPTION =
"The number of get sessions timeouts due to pool exhaustion";
static final String NUM_ACQUIRED_SESSIONS_DESCRIPTION =
"The number of sessions acquired from the session pool.";
static final String NUM_RELEASED_SESSIONS_DESCRIPTION =
"The number of sessions released by the user and pool maintainer.";
}
Expand Up @@ -24,6 +24,10 @@
import static com.google.cloud.spanner.MetricRegistryConstants.MAX_ALLOWED_SESSIONS_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.MAX_IN_USE_SESSIONS;
import static com.google.cloud.spanner.MetricRegistryConstants.MAX_IN_USE_SESSIONS_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_ACQUIRED_SESSIONS;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_ACQUIRED_SESSIONS_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_RELEASED_SESSIONS;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_RELEASED_SESSIONS_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.SESSIONS_TIMEOUTS_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.SPANNER_DEFAULT_LABEL_VALUES;
import static com.google.cloud.spanner.MetricRegistryConstants.SPANNER_LABEL_KEYS;
Expand Down Expand Up @@ -796,6 +800,7 @@ public ApiFuture<Empty> asyncClose() {
public void close() {
synchronized (lock) {
numSessionsInUse--;
numSessionsReleased++;
}
leakedException = null;
if (lastException != null && isSessionNotFound(lastException)) {
Expand Down Expand Up @@ -1122,6 +1127,12 @@ private static enum Position {
@GuardedBy("lock")
private int maxSessionsInUse = 0;

@GuardedBy("lock")
private long numSessionsAcquired = 0;

@GuardedBy("lock")
private long numSessionsReleased = 0;

private AtomicLong numWaiterTimeouts = new AtomicLong();

@GuardedBy("lock")
Expand Down Expand Up @@ -1448,6 +1459,7 @@ private PooledSession replaceSession(
if (!options.isFailIfSessionNotFound() && session.allowReplacing) {
synchronized (lock) {
numSessionsInUse--;
numSessionsReleased++;
}
session.leakedException = null;
invalidateSession(session);
Expand All @@ -1468,6 +1480,7 @@ private void incrementNumSessionsInUse() {
if (maxSessionsInUse < ++numSessionsInUse) {
maxSessionsInUse = numSessionsInUse;
}
numSessionsAcquired++;
}
}

Expand Down Expand Up @@ -1857,6 +1870,24 @@ private void initMetricsCollection(MetricRegistry metricRegistry, List<LabelValu
.setLabelKeys(SPANNER_LABEL_KEYS)
.build());

DerivedLongCumulative numAcquiredSessionsMetric =
metricRegistry.addDerivedLongCumulative(
NUM_ACQUIRED_SESSIONS,
MetricOptions.builder()
.setDescription(NUM_ACQUIRED_SESSIONS_DESCRIPTION)
.setUnit(COUNT)
.setLabelKeys(SPANNER_LABEL_KEYS)
.build());

DerivedLongCumulative numReleasedSessionsMetric =
metricRegistry.addDerivedLongCumulative(
NUM_RELEASED_SESSIONS,
MetricOptions.builder()
.setDescription(NUM_RELEASED_SESSIONS_DESCRIPTION)
.setUnit(COUNT)
.setLabelKeys(SPANNER_LABEL_KEYS)
.build());

// The value of a maxSessionsInUse is observed from a callback function. This function is
// invoked whenever metrics are collected.
maxInUseSessionsMetric.createTimeSeries(
Expand Down Expand Up @@ -1904,5 +1935,25 @@ public long applyAsLong(SessionPool sessionPool) {
return sessionPool.getNumWaiterTimeouts();
}
});

numAcquiredSessionsMetric.createTimeSeries(
labelValues,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.numSessionsAcquired;
}
});

numReleasedSessionsMetric.createTimeSeries(
labelValues,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.numSessionsReleased;
}
});
}
}
Expand Up @@ -1585,10 +1585,14 @@ public void testSessionMetrics() throws Exception {
Session session2 = pool.getReadSession();

MetricsRecord record = metricRegistry.pollRecord();
assertThat(record.getMetrics().size()).isEqualTo(4);
assertThat(record.getMetrics().size()).isEqualTo(6);
assertThat(record.getMetrics()).containsEntry(MetricRegistryConstants.IN_USE_SESSIONS, 2L);
assertThat(record.getMetrics()).containsEntry(MetricRegistryConstants.MAX_IN_USE_SESSIONS, 2L);
assertThat(record.getMetrics()).containsEntry(MetricRegistryConstants.GET_SESSION_TIMEOUTS, 0L);
assertThat(record.getMetrics())
.containsEntry(MetricRegistryConstants.NUM_ACQUIRED_SESSIONS, 2L);
assertThat(record.getMetrics())
.containsEntry(MetricRegistryConstants.NUM_RELEASED_SESSIONS, 0L);
assertThat(record.getMetrics())
.containsEntry(
MetricRegistryConstants.MAX_ALLOWED_SESSIONS, (long) options.getMaxSessions());
Expand Down Expand Up @@ -1625,6 +1629,10 @@ public Void call() {
session1.close();
assertThat(record.getMetrics().get(MetricRegistryConstants.GET_SESSION_TIMEOUTS).longValue())
.isAtLeast(1L);
assertThat(record.getMetrics())
.containsEntry(MetricRegistryConstants.NUM_ACQUIRED_SESSIONS, 3L);
assertThat(record.getMetrics())
.containsEntry(MetricRegistryConstants.NUM_RELEASED_SESSIONS, 3L);
assertThat(record.getMetrics()).containsEntry(MetricRegistryConstants.IN_USE_SESSIONS, 0L);
assertThat(record.getMetrics()).containsEntry(MetricRegistryConstants.MAX_IN_USE_SESSIONS, 2L);
}
Expand Down
Expand Up @@ -255,7 +255,6 @@ public void singleUse() {
}
}
Map<String, Boolean> spans = failOnOverkillTraceComponent.getSpans();
assertThat(spans.size()).isEqualTo(5);
assertThat(spans).containsEntry("CloudSpanner.ReadOnlyTransaction", true);
assertThat(spans).containsEntry("CloudSpannerOperation.BatchCreateSessions", true);
assertThat(spans).containsEntry("SessionPool.WaitForSession", true);
Expand All @@ -274,7 +273,6 @@ public void multiUse() {
}

Map<String, Boolean> spans = failOnOverkillTraceComponent.getSpans();
assertThat(spans.size()).isEqualTo(5);
assertThat(spans).containsEntry("CloudSpanner.ReadOnlyTransaction", true);
assertThat(spans).containsEntry("CloudSpannerOperation.BatchCreateSessions", true);
assertThat(spans).containsEntry("SessionPool.WaitForSession", true);
Expand All @@ -294,7 +292,6 @@ public Void run(TransactionContext transaction) throws Exception {
}
});
Map<String, Boolean> spans = failOnOverkillTraceComponent.getSpans();
assertThat(spans.size()).isEqualTo(6);
assertThat(spans).containsEntry("CloudSpanner.ReadWriteTransaction", true);
assertThat(spans).containsEntry("CloudSpannerOperation.BatchCreateSessions", true);
assertThat(spans).containsEntry("SessionPool.WaitForSession", true);
Expand All @@ -321,7 +318,6 @@ public Void run(TransactionContext transaction) throws Exception {
}

Map<String, Boolean> spans = failOnOverkillTraceComponent.getSpans();
assertThat(spans.size()).isEqualTo(5);
assertThat(spans).containsEntry("CloudSpanner.ReadWriteTransaction", true);
assertThat(spans).containsEntry("CloudSpannerOperation.BatchCreateSessions", true);
assertThat(spans).containsEntry("SessionPool.WaitForSession", true);
Expand Down

0 comments on commit 94d0557

Please sign in to comment.