1616
1717package com .google .cloud .spanner ;
1818
19+ import static com .google .cloud .spanner .MetricRegistryConstants .COUNT ;
20+ import static com .google .cloud .spanner .MetricRegistryConstants .IN_USE_SESSIONS ;
21+ import static com .google .cloud .spanner .MetricRegistryConstants .IN_USE_SESSIONS_DESCRIPTION ;
22+ import static com .google .cloud .spanner .MetricRegistryConstants .MAX_ALLOWED_SESSIONS ;
23+ import static com .google .cloud .spanner .MetricRegistryConstants .MAX_ALLOWED_SESSIONS_DESCRIPTION ;
24+ import static com .google .cloud .spanner .MetricRegistryConstants .MAX_IN_USE_SESSIONS ;
25+ import static com .google .cloud .spanner .MetricRegistryConstants .MAX_IN_USE_SESSIONS_DESCRIPTION ;
26+ import static com .google .cloud .spanner .MetricRegistryConstants .SPANNER_DEFAULT_LABEL_VALUES ;
27+ import static com .google .cloud .spanner .MetricRegistryConstants .SPANNER_LABEL_KEYS ;
1928import static com .google .cloud .spanner .SpannerExceptionFactory .newSpannerException ;
2029
2130import com .google .api .core .ApiFuture ;
4049import com .google .common .util .concurrent .Uninterruptibles ;
4150import com .google .protobuf .Empty ;
4251import io .opencensus .common .Scope ;
52+ import io .opencensus .common .ToLongFunction ;
53+ import io .opencensus .metrics .DerivedLongGauge ;
54+ import io .opencensus .metrics .LabelValue ;
55+ import io .opencensus .metrics .MetricOptions ;
56+ import io .opencensus .metrics .MetricRegistry ;
57+ import io .opencensus .metrics .Metrics ;
4358import io .opencensus .trace .Annotation ;
4459import io .opencensus .trace .AttributeValue ;
4560import io .opencensus .trace .Span ;
4964import java .util .HashSet ;
5065import java .util .Iterator ;
5166import java .util .LinkedList ;
67+ import java .util .List ;
5268import java .util .Queue ;
5369import java .util .Random ;
5470import java .util .Set ;
@@ -1116,11 +1132,15 @@ private static enum Position {
11161132 * Return pool is immediately ready for use, though getting a session might block for sessions to
11171133 * be created.
11181134 */
1119- static SessionPool createPool (SpannerOptions spannerOptions , SessionClient sessionClient ) {
1135+ static SessionPool createPool (
1136+ SpannerOptions spannerOptions , SessionClient sessionClient , List <LabelValue > labelValues ) {
11201137 return createPool (
11211138 spannerOptions .getSessionPoolOptions (),
11221139 ((GrpcTransportOptions ) spannerOptions .getTransportOptions ()).getExecutorFactory (),
1123- sessionClient );
1140+ sessionClient ,
1141+ new Clock (),
1142+ Metrics .getMetricRegistry (),
1143+ labelValues );
11241144 }
11251145
11261146 static SessionPool createPool (
@@ -1135,8 +1155,31 @@ static SessionPool createPool(
11351155 ExecutorFactory <ScheduledExecutorService > executorFactory ,
11361156 SessionClient sessionClient ,
11371157 Clock clock ) {
1158+ return createPool (
1159+ poolOptions ,
1160+ executorFactory ,
1161+ sessionClient ,
1162+ clock ,
1163+ Metrics .getMetricRegistry (),
1164+ SPANNER_DEFAULT_LABEL_VALUES );
1165+ }
1166+
1167+ static SessionPool createPool (
1168+ SessionPoolOptions poolOptions ,
1169+ ExecutorFactory <ScheduledExecutorService > executorFactory ,
1170+ SessionClient sessionClient ,
1171+ Clock clock ,
1172+ MetricRegistry metricRegistry ,
1173+ List <LabelValue > labelValues ) {
11381174 SessionPool pool =
1139- new SessionPool (poolOptions , executorFactory , executorFactory .get (), sessionClient , clock );
1175+ new SessionPool (
1176+ poolOptions ,
1177+ executorFactory ,
1178+ executorFactory .get (),
1179+ sessionClient ,
1180+ clock ,
1181+ metricRegistry ,
1182+ labelValues );
11401183 pool .initPool ();
11411184 return pool ;
11421185 }
@@ -1146,13 +1189,16 @@ private SessionPool(
11461189 ExecutorFactory <ScheduledExecutorService > executorFactory ,
11471190 ScheduledExecutorService executor ,
11481191 SessionClient sessionClient ,
1149- Clock clock ) {
1192+ Clock clock ,
1193+ MetricRegistry metricRegistry ,
1194+ List <LabelValue > labelValues ) {
11501195 this .options = options ;
11511196 this .executorFactory = executorFactory ;
11521197 this .executor = executor ;
11531198 this .sessionClient = sessionClient ;
11541199 this .clock = clock ;
11551200 this .poolMaintainer = new PoolMaintainer ();
1201+ this .initMetricsCollection (metricRegistry , labelValues );
11561202 }
11571203
11581204 @ VisibleForTesting
@@ -1766,4 +1812,73 @@ public void onSessionCreateFailure(Throwable t, int createFailureForSessionCount
17661812 }
17671813 }
17681814 }
1815+
1816+ /**
1817+ * Initializes and creates Spanner session relevant metrics. When coupled with an exporter, it
1818+ * allows users to monitor client behavior.
1819+ */
1820+ private void initMetricsCollection (MetricRegistry metricRegistry , List <LabelValue > labelValues ) {
1821+ DerivedLongGauge maxInUseSessionsMetric =
1822+ metricRegistry .addDerivedLongGauge (
1823+ MAX_IN_USE_SESSIONS ,
1824+ MetricOptions .builder ()
1825+ .setDescription (MAX_IN_USE_SESSIONS_DESCRIPTION )
1826+ .setUnit (COUNT )
1827+ .setLabelKeys (SPANNER_LABEL_KEYS )
1828+ .build ());
1829+
1830+ DerivedLongGauge maxAllowedSessionsMetric =
1831+ metricRegistry .addDerivedLongGauge (
1832+ MAX_ALLOWED_SESSIONS ,
1833+ MetricOptions .builder ()
1834+ .setDescription (MAX_ALLOWED_SESSIONS_DESCRIPTION )
1835+ .setUnit (COUNT )
1836+ .setLabelKeys (SPANNER_LABEL_KEYS )
1837+ .build ());
1838+
1839+ DerivedLongGauge numInUseSessionsMetric =
1840+ metricRegistry .addDerivedLongGauge (
1841+ IN_USE_SESSIONS ,
1842+ MetricOptions .builder ()
1843+ .setDescription (IN_USE_SESSIONS_DESCRIPTION )
1844+ .setUnit (COUNT )
1845+ .setLabelKeys (SPANNER_LABEL_KEYS )
1846+ .build ());
1847+
1848+ // The value of a maxSessionsInUse is observed from a callback function. This function is
1849+ // invoked whenever metrics are collected.
1850+ maxInUseSessionsMetric .createTimeSeries (
1851+ labelValues ,
1852+ this ,
1853+ new ToLongFunction <SessionPool >() {
1854+ @ Override
1855+ public long applyAsLong (SessionPool sessionPool ) {
1856+ return sessionPool .maxSessionsInUse ;
1857+ }
1858+ });
1859+
1860+ // The value of a maxSessions is observed from a callback function. This function is invoked
1861+ // whenever metrics are collected.
1862+ maxAllowedSessionsMetric .createTimeSeries (
1863+ labelValues ,
1864+ options ,
1865+ new ToLongFunction <SessionPoolOptions >() {
1866+ @ Override
1867+ public long applyAsLong (SessionPoolOptions options ) {
1868+ return options .getMaxSessions ();
1869+ }
1870+ });
1871+
1872+ // The value of a numSessionsInUse is observed from a callback function. This function is
1873+ // invoked whenever metrics are collected.
1874+ numInUseSessionsMetric .createTimeSeries (
1875+ labelValues ,
1876+ this ,
1877+ new ToLongFunction <SessionPool >() {
1878+ @ Override
1879+ public long applyAsLong (SessionPool sessionPool ) {
1880+ return sessionPool .numSessionsInUse ;
1881+ }
1882+ });
1883+ }
17691884}
0 commit comments