Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the export logic for per-connection error rate metric #2121

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions google-cloud-bigtable-deps-bom/pom.xml
Expand Up @@ -77,6 +77,12 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Other opencensus packages' versions are pulled through com.google.cloud:third-party-dependencies, but has to be manually specified for this one. -->
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-contrib-resource-util</artifactId>
<version>0.31.1</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
4 changes: 4 additions & 0 deletions google-cloud-bigtable-stats/pom.xml
Expand Up @@ -38,6 +38,10 @@
<groupId>io.opencensus</groupId>
<artifactId>opencensus-exporter-stats-stackdriver</artifactId>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-contrib-resource-util</artifactId>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl</artifactId>
Expand Down
Expand Up @@ -33,13 +33,20 @@ final class BigtableCreateTimeSeriesExporter extends MetricExporter {
private static final Logger logger =
Logger.getLogger(BigtableCreateTimeSeriesExporter.class.getName());
private final MetricServiceClient metricServiceClient;
private final MonitoredResource monitoredResource;
private final MonitoredResource bigtableMonitoredResource;
private final MonitoredResource gceMonitoredResource;
private final MonitoredResource gkeMonitoredResource;
private final String clientId;

BigtableCreateTimeSeriesExporter(
MetricServiceClient metricServiceClient, MonitoredResource monitoredResource) {
MetricServiceClient metricServiceClient,
MonitoredResource bigtableMonitoredResource,
MonitoredResource gceMonitoredResource,
MonitoredResource gkeMonitoredResource) {
this.metricServiceClient = metricServiceClient;
this.monitoredResource = monitoredResource;
this.bigtableMonitoredResource = bigtableMonitoredResource;
this.gceMonitoredResource = gceMonitoredResource;
this.gkeMonitoredResource = gkeMonitoredResource;
this.clientId = BigtableStackdriverExportUtils.getDefaultTaskValue();
}

Expand All @@ -48,11 +55,7 @@ public void export(Collection<Metric> metrics) {

for (Metric metric : metrics) {
// only export bigtable metrics
if (!metric.getMetricDescriptor().getName().contains("bigtable")) {
continue;
}
// TODO: temporarily skip exporting per connection metrics.
if (metric.getMetricDescriptor().getName().contains("per_connection_error_count")) {
if (!BigtableStackdriverExportUtils.shouldExportMetric(metric.getMetricDescriptor())) {
continue;
}

Expand All @@ -69,7 +72,9 @@ public void export(Collection<Metric> metrics) {
metric.getMetricDescriptor(),
timeSeries,
clientId,
monitoredResource),
bigtableMonitoredResource,
gceMonitoredResource,
gkeMonitoredResource),
Collectors.toList())));

for (Map.Entry<String, List<com.google.monitoring.v3.TimeSeries>> entry :
Expand Down
Expand Up @@ -15,6 +15,8 @@
*/
package com.google.cloud.bigtable.stats;

import static com.google.cloud.bigtable.stats.BuiltinViewConstants.PER_CONNECTION_ERROR_COUNT_VIEW;

import com.google.api.Distribution.BucketOptions;
import com.google.api.Distribution.BucketOptions.Explicit;
import com.google.api.Metric;
Expand Down Expand Up @@ -90,8 +92,8 @@ class BigtableStackdriverExportUtils {
return builder.build();
};

// promote the following metric labels to monitored resource labels
private static final Set<String> PROMOTED_RESOURCE_LABELS =
// promote the following metric labels to Bigtable monitored resource labels
private static final Set<String> PROMOTED_BIGTABLE_RESOURCE_LABELS =
ImmutableSet.of(
BuiltinMeasureConstants.PROJECT_ID.getName(),
BuiltinMeasureConstants.INSTANCE_ID.getName(),
Expand All @@ -102,25 +104,71 @@ class BigtableStackdriverExportUtils {
private static final LabelKey CLIENT_UID_LABEL_KEY =
LabelKey.create(BuiltinMeasureConstants.CLIENT_UID.getName(), "client uid");

static boolean isBigtableTableMetric(MetricDescriptor metricDescriptor) {
return !metricDescriptor.getName().equals(PER_CONNECTION_ERROR_COUNT_VIEW.getName().asString());
rkaregar marked this conversation as resolved.
Show resolved Hide resolved
}

static boolean shouldExportMetric(MetricDescriptor metricDescriptor) {
return metricDescriptor.getName().contains("bigtable")
rkaregar marked this conversation as resolved.
Show resolved Hide resolved
&& (isBigtableTableMetric(metricDescriptor)
|| ConsumerEnvironmentUtils.isEnvGce()
|| ConsumerEnvironmentUtils.isEnvGke());
}

static com.google.monitoring.v3.TimeSeries convertTimeSeries(
MetricDescriptor metricDescriptor,
TimeSeries timeSeries,
String clientId,
MonitoredResource monitoredResource) {
String metricName = metricDescriptor.getName();
List<LabelKey> labelKeys = metricDescriptor.getLabelKeys();
MonitoredResource bigtableMonitoredResource,
MonitoredResource gceMonitoredResource,
MonitoredResource gkeMonitoredResource) {
Type metricType = metricDescriptor.getType();

MonitoredResource.Builder monitoredResourceBuilder = monitoredResource.toBuilder();
com.google.monitoring.v3.TimeSeries.Builder builder;
if (isBigtableTableMetric(metricDescriptor)) {
builder =
setupBuilderForBigtableResource(
metricDescriptor, bigtableMonitoredResource, timeSeries, clientId);
} else if (ConsumerEnvironmentUtils.isEnvGce()) {
builder =
setupBuilderForGceOrGKEResource(
metricDescriptor, gceMonitoredResource, timeSeries, clientId);
} else if (ConsumerEnvironmentUtils.isEnvGke()) {
builder =
setupBuilderForGceOrGKEResource(
metricDescriptor, gkeMonitoredResource, timeSeries, clientId);
} else {
logger.warning(
"Trying to export metric "
+ metricDescriptor.getName()
+ " in a non-GCE/GKE environment.");
return com.google.monitoring.v3.TimeSeries.newBuilder().build();
}
builder.setMetricKind(createMetricKind(metricType));
builder.setValueType(createValueType(metricType));
Timestamp startTimeStamp = timeSeries.getStartTimestamp();
for (Point point : timeSeries.getPoints()) {
builder.addPoints(createPoint(point, startTimeStamp));
}
return builder.build();
}

private static com.google.monitoring.v3.TimeSeries.Builder setupBuilderForBigtableResource(
MetricDescriptor metricDescriptor,
MonitoredResource bigtableMonitoredResource,
TimeSeries timeSeries,
String clientId) {
List<LabelKey> labelKeys = metricDescriptor.getLabelKeys();
String metricName = metricDescriptor.getName();
MonitoredResource.Builder monitoredResourceBuilder = bigtableMonitoredResource.toBuilder();
List<LabelKey> metricTagKeys = new ArrayList<>();
List<LabelValue> metricTagValues = new ArrayList<>();

List<LabelValue> labelValues = timeSeries.getLabelValues();
for (int i = 0; i < labelValues.size(); i++) {
// If the label is defined in the monitored resource, convert it to
// a monitored resource label. Otherwise, keep it as a metric label.
if (PROMOTED_RESOURCE_LABELS.contains(labelKeys.get(i).getKey())) {
if (PROMOTED_BIGTABLE_RESOURCE_LABELS.contains(labelKeys.get(i).getKey())) {
monitoredResourceBuilder.putLabels(
labelKeys.get(i).getKey(), labelValues.get(i).getValue());
} else {
Expand All @@ -135,13 +183,41 @@ static com.google.monitoring.v3.TimeSeries convertTimeSeries(
com.google.monitoring.v3.TimeSeries.newBuilder();
builder.setResource(monitoredResourceBuilder.build());
builder.setMetric(createMetric(metricName, metricTagKeys, metricTagValues));
builder.setMetricKind(createMetricKind(metricType));
builder.setValueType(createValueType(metricType));
Timestamp startTimeStamp = timeSeries.getStartTimestamp();
for (Point point : timeSeries.getPoints()) {
builder.addPoints(createPoint(point, startTimeStamp));

return builder;
}

private static com.google.monitoring.v3.TimeSeries.Builder setupBuilderForGceOrGKEResource(
MetricDescriptor metricDescriptor,
MonitoredResource monitoredResource,
TimeSeries timeSeries,
String clientId) {
List<LabelKey> labelKeys = metricDescriptor.getLabelKeys();
String metricName = metricDescriptor.getName();
MonitoredResource.Builder monitoredResourceBuilder = monitoredResource.toBuilder();
List<LabelKey> metricTagKeys = new ArrayList<>();
List<LabelValue> metricTagValues = new ArrayList<>();

List<LabelValue> labelValues = timeSeries.getLabelValues();
for (int i = 0; i < labelValues.size(); i++) {
metricTagKeys.add(labelKeys.get(i));
metricTagValues.add(labelValues.get(i));
}
return builder.build();
metricTagKeys.add(CLIENT_UID_LABEL_KEY);
metricTagValues.add(LabelValue.create(clientId));

if (ConsumerEnvironmentUtils.isEnvGce()) {
ConsumerEnvironmentUtils.putGceResourceLabels(monitoredResourceBuilder);
} else {
ConsumerEnvironmentUtils.putGkeResourceLabels(monitoredResourceBuilder);
}

com.google.monitoring.v3.TimeSeries.Builder builder =
com.google.monitoring.v3.TimeSeries.newBuilder();
builder.setResource(monitoredResourceBuilder.build());
builder.setMetric(createMetric(metricName, metricTagKeys, metricTagValues));

return builder;
}

static String getProjectId(MetricDescriptor metricDescriptor, TimeSeries timeSeries) {
Expand Down
Expand Up @@ -43,7 +43,9 @@ public class BigtableStackdriverStatsExporter {

// Default export interval is 1 minute
private static final Duration EXPORT_INTERVAL = Duration.create(60, 0);
private static final String RESOURCE_TYPE = "bigtable_client_raw";
private static final String BIGTABLE_RESOURCE_TYPE = "bigtable_client_raw";
private static final String GCE_RESOURCE_TYPE = "gce_instance";
private static final String GKE_RESOURCE_TYPE = "k8s_container";

private static final String MONITORING_ENDPOINT =
MoreObjects.firstNonNull(
Expand All @@ -55,13 +57,19 @@ public class BigtableStackdriverStatsExporter {
private BigtableStackdriverStatsExporter(
MetricServiceClient metricServiceClient,
Duration exportInterval,
MonitoredResource monitoredResource) {
MonitoredResource bigtableMonitoredResource,
MonitoredResource gceMonitoredResource,
MonitoredResource gkeMonitoredResource) {
IntervalMetricReader.Options.Builder intervalMetricReaderOptionsBuilder =
IntervalMetricReader.Options.builder();
intervalMetricReaderOptionsBuilder.setExportInterval(exportInterval);
this.intervalMetricReader =
IntervalMetricReader.create(
new BigtableCreateTimeSeriesExporter(metricServiceClient, monitoredResource),
new BigtableCreateTimeSeriesExporter(
metricServiceClient,
bigtableMonitoredResource,
gceMonitoredResource,
gkeMonitoredResource),
MetricReader.create(
MetricReader.Options.builder()
.setMetricProducerManager(
Expand All @@ -76,9 +84,15 @@ public static void register(Credentials credentials) throws IOException {
instance == null, "Bigtable Stackdriver stats exporter is already created");
// Default timeout for creating a client is 1 minute
MetricServiceClient client = createMetricServiceClient(credentials, Duration.create(60L, 0));
MonitoredResource resourceType =
MonitoredResource.newBuilder().setType(RESOURCE_TYPE).build();
instance = new BigtableStackdriverStatsExporter(client, EXPORT_INTERVAL, resourceType);
MonitoredResource bigtableResourceType =
MonitoredResource.newBuilder().setType(BIGTABLE_RESOURCE_TYPE).build();
MonitoredResource gceResourceType =
MonitoredResource.newBuilder().setType(GCE_RESOURCE_TYPE).build();
MonitoredResource gkeResourceType =
MonitoredResource.newBuilder().setType(GKE_RESOURCE_TYPE).build();
instance =
new BigtableStackdriverStatsExporter(
rkaregar marked this conversation as resolved.
Show resolved Hide resolved
client, EXPORT_INTERVAL, bigtableResourceType, gceResourceType, gkeResourceType);
}
}

Expand Down
Expand Up @@ -15,7 +15,25 @@
*/
package com.google.cloud.bigtable.stats;

import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.*;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.APPLICATION_LATENCIES;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.APP_PROFILE;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.ATTEMPT_LATENCIES;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.CLIENT_NAME;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.CLUSTER;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.CONNECTIVITY_ERROR_COUNT;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.FIRST_RESPONSE_LATENCIES;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.INSTANCE_ID;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.METHOD;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.OPERATION_LATENCIES;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.PER_CONNECTION_ERROR_COUNT;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.PROJECT_ID;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.RETRY_COUNT;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.SERVER_LATENCIES;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.STATUS;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.STREAMING;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.TABLE;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.THROTTLING_LATENCIES;
import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.ZONE;
import static io.opencensus.stats.Aggregation.Distribution;
import static io.opencensus.stats.Aggregation.Sum;

Expand Down
Expand Up @@ -37,18 +37,28 @@ public class BuiltinViews {
BuiltinViewConstants.CONNECTIVITY_ERROR_COUNT_VIEW,
BuiltinViewConstants.APPLICATION_LATENCIES_VIEW,
BuiltinViewConstants.THROTTLING_LATENCIES_VIEW);
// We store views that don't use the Bigtable schema and need different tags in a separate set to
// simplify testing.
static final ImmutableSet<View> NON_BIGTABLE_BUILTIN_VIEWS =
ImmutableSet.of(BuiltinViewConstants.PER_CONNECTION_ERROR_COUNT_VIEW);

@VisibleForTesting
void registerPrivateViews(ViewManager viewManager) {
for (View view : BIGTABLE_BUILTIN_VIEWS) {
viewManager.registerView(view);
}
for (View view : NON_BIGTABLE_BUILTIN_VIEWS) {
viewManager.registerView(view);
}
}

public static void registerBigtableBuiltinViews() {
ViewManager viewManager = Stats.getViewManager();
for (View view : BIGTABLE_BUILTIN_VIEWS) {
viewManager.registerView(view);
}
for (View view : NON_BIGTABLE_BUILTIN_VIEWS) {
viewManager.registerView(view);
}
}
}