Skip to content

Commit

Permalink
feat: add num_sessions_in_pool metric (#128)
Browse files Browse the repository at this point in the history
* feat: add num_sessions_in_pool metric

* add tests
  • Loading branch information
mayurkale22 committed Jun 11, 2020
1 parent 0e58788 commit 3a7a8ad
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 63 deletions.
Expand Up @@ -30,12 +30,21 @@ class MetricRegistryConstants {
LabelKey.create("instance_id", "Name of the instance");
private static final LabelKey LIBRARY_VERSION =
LabelKey.create("library_version", "Library version");
private static final LabelKey SESSION_TYPE = LabelKey.create("Type", "Type of the Sessions");

/** The label value is used to represent missing value. */
private static final LabelValue UNSET_LABEL = LabelValue.create(null);

static final LabelValue NUM_IN_USE_SESSIONS = LabelValue.create("num_in_use_sessions");
static final LabelValue NUM_SESSIONS_BEING_PREPARED =
LabelValue.create("num_sessions_being_prepared");
static final LabelValue NUM_READ_SESSIONS = LabelValue.create("num_read_sessions");
static final LabelValue NUM_WRITE_SESSIONS = LabelValue.create("num_write_prepared_sessions");

static final ImmutableList<LabelKey> SPANNER_LABEL_KEYS =
ImmutableList.of(CLIENT_ID, DATABASE, INSTANCE_ID, LIBRARY_VERSION);
static final ImmutableList<LabelKey> SPANNER_LABEL_KEYS_WITH_TYPE =
ImmutableList.of(CLIENT_ID, DATABASE, INSTANCE_ID, LIBRARY_VERSION, SESSION_TYPE);

static final ImmutableList<LabelValue> SPANNER_DEFAULT_LABEL_VALUES =
ImmutableList.of(UNSET_LABEL, UNSET_LABEL, UNSET_LABEL, UNSET_LABEL);
Expand All @@ -46,20 +55,20 @@ class MetricRegistryConstants {
// The Metric name and description
static final String MAX_IN_USE_SESSIONS = "cloud.google.com/java/spanner/max_in_use_sessions";
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 NUM_SESSIONS_IN_POOL = "cloud.google.com/java/spanner/num_sessions_in_pool";

static final String MAX_IN_USE_SESSIONS_DESCRIPTION =
"The maximum number of sessions in use during the last 10 minute interval.";
static final String MAX_ALLOWED_SESSIONS_DESCRIPTION =
"The maximum number of sessions allowed. Configurable by the user.";
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.";
static final String NUM_SESSIONS_IN_POOL_DESCRIPTION = "The number of sessions in the pool.";
}
Expand Up @@ -18,19 +18,24 @@

import static com.google.cloud.spanner.MetricRegistryConstants.COUNT;
import static com.google.cloud.spanner.MetricRegistryConstants.GET_SESSION_TIMEOUTS;
import static com.google.cloud.spanner.MetricRegistryConstants.IN_USE_SESSIONS;
import static com.google.cloud.spanner.MetricRegistryConstants.IN_USE_SESSIONS_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.MAX_ALLOWED_SESSIONS;
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_IN_USE_SESSIONS;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_READ_SESSIONS;
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.NUM_SESSIONS_BEING_PREPARED;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_SESSIONS_IN_POOL;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_SESSIONS_IN_POOL_DESCRIPTION;
import static com.google.cloud.spanner.MetricRegistryConstants.NUM_WRITE_SESSIONS;
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;
import static com.google.cloud.spanner.MetricRegistryConstants.SPANNER_LABEL_KEYS_WITH_TYPE;
import static com.google.cloud.spanner.SpannerExceptionFactory.newSpannerException;

import com.google.api.core.ApiFuture;
Expand Down Expand Up @@ -71,6 +76,7 @@
import io.opencensus.trace.Status;
import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
Expand Down Expand Up @@ -2030,15 +2036,6 @@ private void initMetricsCollection(MetricRegistry metricRegistry, List<LabelValu
.setLabelKeys(SPANNER_LABEL_KEYS)
.build());

DerivedLongGauge numInUseSessionsMetric =
metricRegistry.addDerivedLongGauge(
IN_USE_SESSIONS,
MetricOptions.builder()
.setDescription(IN_USE_SESSIONS_DESCRIPTION)
.setUnit(COUNT)
.setLabelKeys(SPANNER_LABEL_KEYS)
.build());

DerivedLongCumulative sessionsTimeouts =
metricRegistry.addDerivedLongCumulative(
GET_SESSION_TIMEOUTS,
Expand Down Expand Up @@ -2066,6 +2063,15 @@ private void initMetricsCollection(MetricRegistry metricRegistry, List<LabelValu
.setLabelKeys(SPANNER_LABEL_KEYS)
.build());

DerivedLongGauge numSessionsInPoolMetric =
metricRegistry.addDerivedLongGauge(
NUM_SESSIONS_IN_POOL,
MetricOptions.builder()
.setDescription(NUM_SESSIONS_IN_POOL_DESCRIPTION)
.setUnit(COUNT)
.setLabelKeys(SPANNER_LABEL_KEYS_WITH_TYPE)
.build());

// The value of a maxSessionsInUse is observed from a callback function. This function is
// invoked whenever metrics are collected.
maxInUseSessionsMetric.createTimeSeries(
Expand All @@ -2090,18 +2096,6 @@ public long applyAsLong(SessionPoolOptions options) {
}
});

// The value of a numSessionsInUse is observed from a callback function. This function is
// invoked whenever metrics are collected.
numInUseSessionsMetric.createTimeSeries(
labelValues,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.numSessionsInUse;
}
});

// The value of a numWaiterTimeouts is observed from a callback function. This function is
// invoked whenever metrics are collected.
sessionsTimeouts.createTimeSeries(
Expand Down Expand Up @@ -2133,5 +2127,53 @@ public long applyAsLong(SessionPool sessionPool) {
return sessionPool.numSessionsReleased;
}
});

List<LabelValue> labelValuesWithBeingPreparedType = new ArrayList<>(labelValues);
labelValuesWithBeingPreparedType.add(NUM_SESSIONS_BEING_PREPARED);
numSessionsInPoolMetric.createTimeSeries(
labelValuesWithBeingPreparedType,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.numSessionsBeingPrepared;
}
});

List<LabelValue> labelValuesWithInUseType = new ArrayList<>(labelValues);
labelValuesWithInUseType.add(NUM_IN_USE_SESSIONS);
numSessionsInPoolMetric.createTimeSeries(
labelValuesWithInUseType,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.numSessionsInUse;
}
});

List<LabelValue> labelValuesWithReadType = new ArrayList<>(labelValues);
labelValuesWithReadType.add(NUM_READ_SESSIONS);
numSessionsInPoolMetric.createTimeSeries(
labelValuesWithReadType,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.readSessions.size();
}
});

List<LabelValue> labelValuesWithWriteType = new ArrayList<>(labelValues);
labelValuesWithWriteType.add(NUM_WRITE_SESSIONS);
numSessionsInPoolMetric.createTimeSeries(
labelValuesWithWriteType,
this,
new ToLongFunction<SessionPool>() {
@Override
public long applyAsLong(SessionPool sessionPool) {
return sessionPool.writePreparedSessions.size();
}
});
}
}
Expand Up @@ -29,6 +29,7 @@
import io.opencensus.metrics.LongGauge;
import io.opencensus.metrics.MetricOptions;
import io.opencensus.metrics.MetricRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

Expand All @@ -37,36 +38,39 @@ class MetricRegistryTestUtils {
static class PointWithFunction<T> {
private final T ref;
private final ToLongFunction<T> function;
private final List<LabelKey> key;
private final List<LabelValue> values;

PointWithFunction(T obj, ToLongFunction<T> function) {
PointWithFunction(
T obj, ToLongFunction<T> function, List<LabelKey> keys, List<LabelValue> values) {
this.ref = obj;
this.function = function;
this.key = keys;
this.values = values;
}

long get() {
long value() {
return function.applyAsLong(ref);
}

List<LabelKey> keys() {
return key;
}

List<LabelValue> values() {
return values;
}
}

static class MetricsRecord {
private final Map<String, PointWithFunction> metrics;
private final Map<List<LabelKey>, List<LabelValue>> labels;
private final Map<String, List<PointWithFunction>> metrics;

private MetricsRecord() {
this.metrics = Maps.newHashMap();
this.labels = Maps.newHashMap();
}

Map<String, Number> getMetrics() {
Map<String, Number> copy = Maps.newHashMap();
for (Map.Entry<String, PointWithFunction> entry : metrics.entrySet()) {
copy.put(entry.getKey(), entry.getValue().get());
}
return copy;
}

Map<List<LabelKey>, List<LabelValue>> getLabels() {
return this.labels;
Map<String, List<PointWithFunction>> getMetrics() {
return metrics;
}
}

Expand All @@ -85,8 +89,13 @@ private FakeDerivedLongGauge(
@Override
public <T> void createTimeSeries(
List<LabelValue> labelValues, T t, ToLongFunction<T> toLongFunction) {
this.record.metrics.put(this.name, new PointWithFunction(t, toLongFunction));
this.record.labels.put(this.labelKeys, labelValues);
if (!this.record.metrics.containsKey(this.name)) {
this.record.metrics.put(this.name, new ArrayList<PointWithFunction>());
}
this.record
.metrics
.get(this.name)
.add(new PointWithFunction(t, toLongFunction, labelKeys, labelValues));
}

@Override
Expand All @@ -111,8 +120,13 @@ private FakeDerivedLongCumulative(
@Override
public <T> void createTimeSeries(
List<LabelValue> labelValues, T t, ToLongFunction<T> toLongFunction) {
this.record.metrics.put(this.name, new PointWithFunction(t, toLongFunction));
this.record.labels.put(this.labelKeys, labelValues);
if (!this.record.metrics.containsKey(this.name)) {
this.record.metrics.put(this.name, new ArrayList<PointWithFunction>());
}
this.record
.metrics
.get(this.name)
.add(new PointWithFunction(t, toLongFunction, labelKeys, labelValues));
}

@Override
Expand Down

0 comments on commit 3a7a8ad

Please sign in to comment.