diff --git a/presto-hive/src/main/java/com/facebook/presto/hive/aws/AbstractSdkMetricsCollector.java b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/aws/AbstractSdkMetricsCollector.java similarity index 100% rename from presto-hive/src/main/java/com/facebook/presto/hive/aws/AbstractSdkMetricsCollector.java rename to presto-hive-metastore/src/main/java/com/facebook/presto/hive/aws/AbstractSdkMetricsCollector.java diff --git a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueCatalogApiStats.java b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueCatalogApiStats.java new file mode 100644 index 0000000000000..b1709c68465c1 --- /dev/null +++ b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueCatalogApiStats.java @@ -0,0 +1,94 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.facebook.presto.hive.metastore.glue; + +import com.amazonaws.AmazonWebServiceRequest; +import com.amazonaws.handlers.AsyncHandler; +import com.facebook.airlift.stats.CounterStat; +import com.facebook.airlift.stats.TimeStat; +import org.weakref.jmx.Managed; +import org.weakref.jmx.Nested; + +import javax.annotation.concurrent.ThreadSafe; + +import java.util.function.Supplier; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +@ThreadSafe +public class GlueCatalogApiStats +{ + private final TimeStat time = new TimeStat(MILLISECONDS); + private final CounterStat totalFailures = new CounterStat(); + + public T record(Supplier action) + { + try (TimeStat.BlockTimer timer = time.time()) { + return action.get(); + } + catch (Exception e) { + recordException(e); + throw e; + } + } + + public void record(Runnable action) + { + try (TimeStat.BlockTimer timer = time.time()) { + action.run(); + } + catch (Exception e) { + recordException(e); + throw e; + } + } + + public AsyncHandler metricsAsyncHandler() + { + return new AsyncHandler() { + private final TimeStat.BlockTimer timer = time.time(); + @Override + public void onError(Exception exception) + { + timer.close(); + recordException(exception); + } + + @Override + public void onSuccess(R request, T result) + { + timer.close(); + } + }; + } + + @Managed + @Nested + public TimeStat getTime() + { + return time; + } + + @Managed + @Nested + public CounterStat getTotalFailures() + { + return totalFailures; + } + + private void recordException(Exception e) + { + totalFailures.update(1); + } +} diff --git a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueHiveMetastore.java b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueHiveMetastore.java index fce0b7e0d65df..1d110c1d5d00d 100644 --- a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueHiveMetastore.java +++ b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueHiveMetastore.java @@ -17,6 +17,7 @@ import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider; +import com.amazonaws.metrics.RequestMetricCollector; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.amazonaws.services.glue.AWSGlueAsync; @@ -90,6 +91,8 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import org.apache.hadoop.fs.Path; +import org.weakref.jmx.Flatten; +import org.weakref.jmx.Managed; import javax.annotation.Nullable; import javax.inject.Inject; @@ -145,6 +148,7 @@ public class GlueHiveMetastore private static final int BATCH_CREATE_PARTITION_MAX_PAGE_SIZE = 100; private static final Comparator PARTITION_COMPARATOR = comparing(Partition::getValues, lexicographical(String.CASE_INSENSITIVE_ORDER)); + private final GlueMetastoreStats stats = new GlueMetastoreStats(); private final HdfsEnvironment hdfsEnvironment; private final HdfsContext hdfsContext; private final AWSGlueAsync glueClient; @@ -158,29 +162,21 @@ public GlueHiveMetastore( HdfsEnvironment hdfsEnvironment, GlueHiveMetastoreConfig glueConfig, @ForGlueHiveMetastore Executor executor) - { - this(hdfsEnvironment, glueConfig, createAsyncGlueClient(glueConfig), executor); - } - - public GlueHiveMetastore( - HdfsEnvironment hdfsEnvironment, - GlueHiveMetastoreConfig glueConfig, - AWSGlueAsync glueClient, - @ForGlueHiveMetastore Executor executor) { this.hdfsEnvironment = requireNonNull(hdfsEnvironment, "hdfsEnvironment is null"); this.hdfsContext = new HdfsContext(new ConnectorIdentity(DEFAULT_METASTORE_USER, Optional.empty(), Optional.empty())); - this.glueClient = requireNonNull(glueClient, "glueClient is null"); + this.glueClient = createAsyncGlueClient(requireNonNull(glueConfig, "glueConfig is null"), stats.newRequestMetricsCollector()); this.defaultDir = glueConfig.getDefaultWarehouseDir(); this.catalogId = glueConfig.getCatalogId().orElse(null); this.partitionSegments = glueConfig.getPartitionSegments(); this.executor = requireNonNull(executor, "executor is null"); } - private static AWSGlueAsync createAsyncGlueClient(GlueHiveMetastoreConfig config) + private static AWSGlueAsync createAsyncGlueClient(GlueHiveMetastoreConfig config, RequestMetricCollector metricsCollector) { ClientConfiguration clientConfig = new ClientConfiguration().withMaxConnections(config.getMaxGlueConnections()); AWSGlueAsyncClientBuilder asyncGlueClientBuilder = AWSGlueAsyncClientBuilder.standard() + .withMetricsCollector(metricsCollector) .withClientConfiguration(clientConfig); if (config.getGlueRegion().isPresent()) { @@ -203,19 +199,28 @@ else if (config.getPinGlueClientToCurrentRegion()) { return asyncGlueClientBuilder.build(); } + @Managed + @Flatten + public GlueMetastoreStats getStats() + { + return stats; + } + @Override public Optional getDatabase(String databaseName) { - try { - GetDatabaseResult result = glueClient.getDatabase(new GetDatabaseRequest().withCatalogId(catalogId).withName(databaseName)); - return Optional.of(GlueToPrestoConverter.convertDatabase(result.getDatabase())); - } - catch (EntityNotFoundException e) { - return Optional.empty(); - } - catch (AmazonServiceException e) { - throw new PrestoException(HIVE_METASTORE_ERROR, e); - } + return stats.getGetDatabase().record(() -> { + try { + GetDatabaseResult result = glueClient.getDatabase(new GetDatabaseRequest().withCatalogId(catalogId).withName(databaseName)); + return Optional.of(GlueToPrestoConverter.convertDatabase(result.getDatabase())); + } + catch (EntityNotFoundException e) { + return Optional.empty(); + } + catch (AmazonServiceException e) { + throw new PrestoException(HIVE_METASTORE_ERROR, e); + } + }); } @Override @@ -223,14 +228,13 @@ public List getAllDatabases() { try { List databaseNames = new ArrayList<>(); - String nextToken = null; - + GetDatabasesRequest request = new GetDatabasesRequest().withCatalogId(catalogId); do { - GetDatabasesResult result = glueClient.getDatabases(new GetDatabasesRequest().withCatalogId(catalogId).withNextToken(nextToken)); - nextToken = result.getNextToken(); + GetDatabasesResult result = stats.getGetDatabases().record(() -> glueClient.getDatabases(request)); + request.setNextToken(result.getNextToken()); result.getDatabaseList().forEach(database -> databaseNames.add(database.getName())); } - while (nextToken != null); + while (request.getNextToken() != null); return databaseNames; } @@ -253,19 +257,21 @@ private com.amazonaws.services.glue.model.Table getGlueTableOrElseThrow(String d private Optional getGlueTable(String databaseName, String tableName) { - try { - GetTableResult result = glueClient.getTable(new GetTableRequest() - .withCatalogId(catalogId) - .withDatabaseName(databaseName) - .withName(tableName)); - return Optional.of(result.getTable()); - } - catch (EntityNotFoundException e) { - return Optional.empty(); - } - catch (AmazonServiceException e) { - throw new PrestoException(HIVE_METASTORE_ERROR, e); - } + return stats.getGetTable().record(() -> { + try { + GetTableResult result = glueClient.getTable(new GetTableRequest() + .withCatalogId(catalogId) + .withDatabaseName(databaseName) + .withName(tableName)); + return Optional.of(result.getTable()); + } + catch (EntityNotFoundException e) { + return Optional.empty(); + } + catch (AmazonServiceException e) { + throw new PrestoException(HIVE_METASTORE_ERROR, e); + } + }); } @Override @@ -315,10 +321,11 @@ public void updateTableStatistics(String databaseName, String tableName, Functio try { TableInput tableInput = GlueInputConverter.convertTable(table); tableInput.setParameters(updateStatisticsParameters(table.getParameters(), updatedStatistics.getBasicStatistics())); - glueClient.updateTable(new UpdateTableRequest() + UpdateTableRequest request = new UpdateTableRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) - .withTableInput(tableInput)); + .withTableInput(tableInput); + stats.getUpdateTable().record(() -> glueClient.updateTable(request)); } catch (EntityNotFoundException e) { throw new TableNotFoundException(new SchemaTableName(databaseName, tableName)); @@ -346,12 +353,12 @@ public void updatePartitionStatistics(String databaseName, String tableName, Str try { PartitionInput partitionInput = GlueInputConverter.convertPartition(partition); partitionInput.setParameters(updateStatisticsParameters(partition.getParameters(), updatedStatistics.getBasicStatistics())); - glueClient.updatePartition(new UpdatePartitionRequest() + stats.getUpdatePartition().record(() -> glueClient.updatePartition(new UpdatePartitionRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) .withTableName(tableName) .withPartitionValueList(partition.getValues()) - .withPartitionInput(partitionInput)); + .withPartitionInput(partitionInput))); } catch (EntityNotFoundException e) { throw new PartitionNotFoundException(new SchemaTableName(databaseName, tableName), partitionValues); @@ -366,17 +373,13 @@ public Optional> getAllTables(String databaseName) { try { List tableNames = new ArrayList<>(); - String nextToken = null; - + GetTablesRequest request = new GetTablesRequest().withCatalogId(catalogId).withDatabaseName(databaseName); do { - GetTablesResult result = glueClient.getTables(new GetTablesRequest() - .withCatalogId(catalogId) - .withDatabaseName(databaseName) - .withNextToken(nextToken)); + GetTablesResult result = stats.getGetTables().record(() -> glueClient.getTables(request)); + request.setNextToken(result.getNextToken()); result.getTableList().forEach(table -> tableNames.add(table.getName())); - nextToken = result.getNextToken(); } - while (nextToken != null); + while (request.getNextToken() != null); return Optional.of(tableNames); } @@ -394,19 +397,16 @@ public Optional> getAllViews(String databaseName) { try { List views = new ArrayList<>(); - String nextToken = null; + GetTablesRequest request = new GetTablesRequest().withCatalogId(catalogId).withDatabaseName(databaseName); do { - GetTablesResult result = glueClient.getTables(new GetTablesRequest() - .withCatalogId(catalogId) - .withDatabaseName(databaseName) - .withNextToken(nextToken)); + GetTablesResult result = stats.getGetTables().record(() -> glueClient.getTables(request)); + request.setNextToken(result.getNextToken()); result.getTableList().stream() .filter(table -> VIRTUAL_VIEW.name().equals(table.getTableType())) .forEach(table -> views.add(table.getName())); - nextToken = result.getNextToken(); } - while (nextToken != null); + while (request.getNextToken() != null); return Optional.of(views); } @@ -431,7 +431,7 @@ public void createDatabase(Database database) try { DatabaseInput databaseInput = GlueInputConverter.convertDatabase(database); - glueClient.createDatabase(new CreateDatabaseRequest().withCatalogId(catalogId).withDatabaseInput(databaseInput)); + stats.getCreateDatabase().record(() -> glueClient.createDatabase(new CreateDatabaseRequest().withCatalogId(catalogId).withDatabaseInput(databaseInput))); } catch (AlreadyExistsException e) { throw new SchemaAlreadyExistsException(database.getDatabaseName()); @@ -449,7 +449,7 @@ public void createDatabase(Database database) public void dropDatabase(String databaseName) { try { - glueClient.deleteDatabase(new DeleteDatabaseRequest().withCatalogId(catalogId).withName(databaseName)); + stats.getDeleteDatabase().record(() -> glueClient.deleteDatabase(new DeleteDatabaseRequest().withCatalogId(catalogId).withName(databaseName))); } catch (EntityNotFoundException e) { throw new SchemaNotFoundException(databaseName); @@ -465,10 +465,10 @@ public void renameDatabase(String databaseName, String newDatabaseName) try { Database database = getDatabase(databaseName).orElseThrow(() -> new SchemaNotFoundException(databaseName)); DatabaseInput renamedDatabase = GlueInputConverter.convertDatabase(database).withName(newDatabaseName); - glueClient.updateDatabase(new UpdateDatabaseRequest() + stats.getUpdateDatabase().record(() -> glueClient.updateDatabase(new UpdateDatabaseRequest() .withCatalogId(catalogId) .withName(databaseName) - .withDatabaseInput(renamedDatabase)); + .withDatabaseInput(renamedDatabase))); } catch (AmazonServiceException e) { throw new PrestoException(HIVE_METASTORE_ERROR, e); @@ -480,10 +480,10 @@ public void createTable(Table table, PrincipalPrivileges principalPrivileges) { try { TableInput input = GlueInputConverter.convertTable(table); - glueClient.createTable(new CreateTableRequest() + stats.getCreateTable().record(() -> glueClient.createTable(new CreateTableRequest() .withCatalogId(catalogId) .withDatabaseName(table.getDatabaseName()) - .withTableInput(input)); + .withTableInput(input))); } catch (AlreadyExistsException e) { throw new TableAlreadyExistsException(new SchemaTableName(table.getDatabaseName(), table.getTableName())); @@ -502,10 +502,10 @@ public void dropTable(String databaseName, String tableName, boolean deleteData) Table table = getTableOrElseThrow(databaseName, tableName); try { - glueClient.deleteTable(new DeleteTableRequest() + stats.getDeleteTable().record(() -> glueClient.deleteTable(new DeleteTableRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) - .withName(tableName)); + .withName(tableName))); } catch (AmazonServiceException e) { throw new PrestoException(HIVE_METASTORE_ERROR, e); @@ -538,10 +538,10 @@ public void replaceTable(String databaseName, String tableName, Table newTable, { try { TableInput newTableInput = GlueInputConverter.convertTable(newTable); - glueClient.updateTable(new UpdateTableRequest() + stats.getUpdateTable().record(() -> glueClient.updateTable(new UpdateTableRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) - .withTableInput(newTableInput)); + .withTableInput(newTableInput))); } catch (EntityNotFoundException e) { throw new TableNotFoundException(new SchemaTableName(databaseName, tableName)); @@ -620,10 +620,10 @@ public void dropColumn(String databaseName, String tableName, String columnName) private void replaceGlueTable(String databaseName, String tableName, com.amazonaws.services.glue.model.Table newTable) { try { - glueClient.updateTable(new UpdateTableRequest() + stats.getUpdateTable().record(() -> glueClient.updateTable(new UpdateTableRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) - .withTableInput(toTableInput(newTable))); + .withTableInput(toTableInput(newTable)))); } catch (EntityNotFoundException e) { throw new TableNotFoundException(new SchemaTableName(databaseName, tableName)); @@ -636,20 +636,22 @@ private void replaceGlueTable(String databaseName, String tableName, com.amazona @Override public Optional getPartition(String databaseName, String tableName, List partitionValues) { - try { - GetPartitionResult result = glueClient.getPartition(new GetPartitionRequest() - .withCatalogId(catalogId) - .withDatabaseName(databaseName) - .withTableName(tableName) - .withPartitionValues(partitionValues)); - return Optional.of(GlueToPrestoConverter.convertPartition(result.getPartition())); - } - catch (EntityNotFoundException e) { - return Optional.empty(); - } - catch (AmazonServiceException e) { - throw new PrestoException(HIVE_METASTORE_ERROR, e); - } + return stats.getGetPartition().record(() -> { + try { + GetPartitionResult result = glueClient.getPartition(new GetPartitionRequest() + .withCatalogId(catalogId) + .withDatabaseName(databaseName) + .withTableName(tableName) + .withPartitionValues(partitionValues)); + return Optional.of(GlueToPrestoConverter.convertPartition(result.getPartition())); + } + catch (EntityNotFoundException e) { + return Optional.empty(); + } + catch (AmazonServiceException e) { + throw new PrestoException(HIVE_METASTORE_ERROR, e); + } + }); } @Override @@ -728,21 +730,20 @@ private List getPartitions(String databaseName, String tableName, Str { try { List partitions = new ArrayList<>(); - String nextToken = null; + GetPartitionsRequest request = new GetPartitionsRequest() + .withCatalogId(catalogId) + .withDatabaseName(databaseName) + .withTableName(tableName) + .withExpression(expression) + .withSegment(segment); do { - GetPartitionsResult result = glueClient.getPartitions(new GetPartitionsRequest() - .withCatalogId(catalogId) - .withDatabaseName(databaseName) - .withTableName(tableName) - .withExpression(expression) - .withSegment(segment) - .withNextToken(nextToken)); + GetPartitionsResult result = stats.getGetPartitions().record(() -> glueClient.getPartitions(request)); + request.setNextToken(result.getNextToken()); result.getPartitions() .forEach(partition -> partitions.add(GlueToPrestoConverter.convertPartition(partition))); - nextToken = result.getNextToken(); } - while (nextToken != null); + while (request.getNextToken() != null); return partitions; } @@ -805,7 +806,7 @@ private List batchGetPartition(String databaseName, String tableName, .withCatalogId(catalogId) .withDatabaseName(databaseName) .withTableName(tableName) - .withPartitionsToGet(partitions))); + .withPartitionsToGet(partitions), stats.getBatchGetPartitions().metricsAsyncHandler())); } for (Future future : batchGetPartitionFutures) { @@ -836,7 +837,7 @@ public void addPartitions(String databaseName, String tableName, List future : futures) { @@ -877,11 +878,11 @@ public void dropPartition(String databaseName, String tableName, List pa .orElseThrow(() -> new PartitionNotFoundException(new SchemaTableName(databaseName, tableName), parts)); try { - glueClient.deletePartition(new DeletePartitionRequest() + stats.getDeletePartition().record(() -> glueClient.deletePartition(new DeletePartitionRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) .withTableName(tableName) - .withPartitionValues(parts)); + .withPartitionValues(parts))); } catch (AmazonServiceException e) { throw new PrestoException(HIVE_METASTORE_ERROR, e); @@ -898,12 +899,12 @@ public void alterPartition(String databaseName, String tableName, PartitionWithS { try { PartitionInput newPartition = GlueInputConverter.convertPartition(partition); - glueClient.updatePartition(new UpdatePartitionRequest() + stats.getUpdatePartition().record(() -> glueClient.updatePartition(new UpdatePartitionRequest() .withCatalogId(catalogId) .withDatabaseName(databaseName) .withTableName(tableName) .withPartitionInput(newPartition) - .withPartitionValueList(partition.getPartition().getValues())); + .withPartitionValueList(partition.getPartition().getValues()))); } catch (EntityNotFoundException e) { throw new PartitionNotFoundException(new SchemaTableName(databaseName, tableName), partition.getPartition().getValues()); diff --git a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreModule.java b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreModule.java index d41701b539e7e..54f9897a6312b 100644 --- a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreModule.java +++ b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreModule.java @@ -47,10 +47,13 @@ public GlueMetastoreModule(String connectorId) public void configure(Binder binder) { configBinder(binder).bindConfig(GlueHiveMetastoreConfig.class); + binder.bind(GlueHiveMetastore.class).in(Scopes.SINGLETON); binder.bind(ExtendedHiveMetastore.class).annotatedWith(ForCachingHiveMetastore.class).to(GlueHiveMetastore.class).in(Scopes.SINGLETON); binder.bind(ExtendedHiveMetastore.class).to(CachingHiveMetastore.class).in(Scopes.SINGLETON); newExporter(binder).export(ExtendedHiveMetastore.class) .as(generatedNameOf(CachingHiveMetastore.class, connectorId)); + newExporter(binder).export(GlueHiveMetastore.class) + .as(generatedNameOf(GlueHiveMetastore.class, connectorId)); } @Provides diff --git a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreStats.java b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreStats.java new file mode 100644 index 0000000000000..1c7ece62c038b --- /dev/null +++ b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueMetastoreStats.java @@ -0,0 +1,258 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.facebook.presto.hive.metastore.glue; + +import com.facebook.airlift.stats.CounterStat; +import com.facebook.airlift.stats.TimeStat; +import com.facebook.presto.hive.aws.AbstractSdkMetricsCollector; +import io.airlift.units.Duration; +import org.weakref.jmx.Managed; +import org.weakref.jmx.Nested; + +import static java.util.Objects.requireNonNull; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +public class GlueMetastoreStats +{ + private final GlueCatalogApiStats createDatabase = new GlueCatalogApiStats(); + private final GlueCatalogApiStats updateDatabase = new GlueCatalogApiStats(); + private final GlueCatalogApiStats deleteDatabase = new GlueCatalogApiStats(); + private final GlueCatalogApiStats getDatabases = new GlueCatalogApiStats(); + private final GlueCatalogApiStats getDatabase = new GlueCatalogApiStats(); + private final GlueCatalogApiStats createTable = new GlueCatalogApiStats(); + private final GlueCatalogApiStats updateTable = new GlueCatalogApiStats(); + private final GlueCatalogApiStats deleteTable = new GlueCatalogApiStats(); + private final GlueCatalogApiStats getTables = new GlueCatalogApiStats(); + private final GlueCatalogApiStats getTable = new GlueCatalogApiStats(); + private final GlueCatalogApiStats batchCreatePartitions = new GlueCatalogApiStats(); + private final GlueCatalogApiStats batchGetPartitions = new GlueCatalogApiStats(); + private final GlueCatalogApiStats updatePartition = new GlueCatalogApiStats(); + private final GlueCatalogApiStats deletePartition = new GlueCatalogApiStats(); + private final GlueCatalogApiStats getPartitions = new GlueCatalogApiStats(); + private final GlueCatalogApiStats getPartition = new GlueCatalogApiStats(); + + // see AWSRequestMetrics + private final CounterStat awsRequestCount = new CounterStat(); + private final CounterStat awsRetryCount = new CounterStat(); + private final CounterStat awsThrottleExceptions = new CounterStat(); + private final TimeStat awsRequestTime = new TimeStat(MILLISECONDS); + private final TimeStat awsClientExecuteTime = new TimeStat(MILLISECONDS); + private final TimeStat awsClientRetryPauseTime = new TimeStat(MILLISECONDS); + + @Managed + @Nested + public GlueCatalogApiStats getCreateDatabase() + { + return createDatabase; + } + + @Managed + @Nested + public GlueCatalogApiStats getUpdateDatabase() + { + return updateDatabase; + } + + @Managed + @Nested + public GlueCatalogApiStats getDeleteDatabase() + { + return deleteDatabase; + } + + @Managed + @Nested + public GlueCatalogApiStats getGetDatabases() + { + return getDatabases; + } + + @Managed + @Nested + public GlueCatalogApiStats getGetDatabase() + { + return getDatabase; + } + + @Managed + @Nested + public GlueCatalogApiStats getCreateTable() + { + return createTable; + } + + @Managed + @Nested + public GlueCatalogApiStats getUpdateTable() + { + return updateTable; + } + + @Managed + @Nested + public GlueCatalogApiStats getDeleteTable() + { + return deleteTable; + } + + @Managed + @Nested + public GlueCatalogApiStats getGetTables() + { + return getTables; + } + + @Managed + @Nested + public GlueCatalogApiStats getGetTable() + { + return getTable; + } + + @Managed + @Nested + public GlueCatalogApiStats getBatchCreatePartitions() + { + return batchCreatePartitions; + } + + @Managed + @Nested + public GlueCatalogApiStats getBatchGetPartitions() + { + return batchGetPartitions; + } + + @Managed + @Nested + public GlueCatalogApiStats getUpdatePartition() + { + return updatePartition; + } + + @Managed + @Nested + public GlueCatalogApiStats getDeletePartition() + { + return deletePartition; + } + + @Managed + @Nested + public GlueCatalogApiStats getGetPartitions() + { + return getPartitions; + } + + @Managed + @Nested + public GlueCatalogApiStats getGetPartition() + { + return getPartition; + } + + @Managed + @Nested + public CounterStat getAwsRequestCount() + { + return awsRequestCount; + } + + @Managed + @Nested + public CounterStat getAwsRetryCount() + { + return awsRetryCount; + } + + @Managed + @Nested + public CounterStat getAwsThrottleExceptions() + { + return awsThrottleExceptions; + } + + @Managed + @Nested + public TimeStat getAwsRequestTime() + { + return awsRequestTime; + } + + @Managed + @Nested + public TimeStat getAwsClientExecuteTime() + { + return awsClientExecuteTime; + } + + @Managed + @Nested + public TimeStat getAwsClientRetryPauseTime() + { + return awsClientRetryPauseTime; + } + + public GlueSdkClientMetricsCollector newRequestMetricsCollector() + { + return new GlueSdkClientMetricsCollector(this); + } + + public static class GlueSdkClientMetricsCollector + extends AbstractSdkMetricsCollector + { + private final GlueMetastoreStats stats; + + public GlueSdkClientMetricsCollector(GlueMetastoreStats stats) + { + this.stats = requireNonNull(stats, "stats is null"); + } + + @Override + protected void recordRequestCount(long count) + { + stats.awsRequestCount.update(count); + } + + @Override + protected void recordRetryCount(long count) + { + stats.awsRetryCount.update(count); + } + + @Override + protected void recordThrottleExceptionCount(long count) + { + stats.awsThrottleExceptions.update(count); + } + + @Override + protected void recordHttpRequestTime(Duration duration) + { + stats.awsRequestTime.add(duration); + } + + @Override + protected void recordClientExecutionTime(Duration duration) + { + stats.awsClientExecuteTime.add(duration); + } + + @Override + protected void recordRetryPauseTime(Duration duration) + { + stats.awsClientRetryPauseTime.add(duration); + } + } +}