>From Hussain Towaileb <[email protected]>:

Hussain Towaileb has submitted this change. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20517?usp=email )

Change subject: [ASTERIXDB-3662][EXT]: Add external stats tracker
......................................................................

[ASTERIXDB-3662][EXT]: Add external stats tracker

Details:
- External statss tracker can be used to collect
  different statistics about external data operations.

Ext-ref: MB-68345
Change-Id: Ifca24a07d733f5652030032784676c0b3aea47f8
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20517
Reviewed-by: Murtadha Hubail <[email protected]>
Reviewed-by: Hussain Towaileb <[email protected]>
Tested-by: Jenkins <[email protected]>
Integration-Tests: Jenkins <[email protected]>
---
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java
A 
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/external/ExternalStatsTracker.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
M 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IApplicationContext.java
D 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCache.java
R 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalStatsTracker.java
M 
asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/aws/AwsUtils.java
8 files changed, 135 insertions(+), 81 deletions(-)

Approvals:
  Hussain Towaileb: Looks good to me, but someone else must approve
  Jenkins: Verified; Verified
  Murtadha Hubail: Looks good to me, approved




diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java
index 6ea7aeb..0126b6e 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/cc/CcApplicationContext.java
@@ -24,6 +24,7 @@
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.function.Supplier;

+import org.apache.asterix.app.external.ExternalStatsTracker;
 import org.apache.asterix.app.result.ResultReader;
 import org.apache.asterix.common.api.IConfigValidator;
 import org.apache.asterix.common.api.IConfigValidatorFactory;
@@ -55,6 +56,7 @@
 import org.apache.asterix.common.dataflow.ICcApplicationContext;
 import org.apache.asterix.common.dataflow.IDataPartitioningProvider;
 import org.apache.asterix.common.external.IAdapterFactoryService;
+import org.apache.asterix.common.external.IExternalStatsTracker;
 import org.apache.asterix.common.metadata.IMetadataBootstrap;
 import org.apache.asterix.common.metadata.IMetadataLockUtil;
 import org.apache.asterix.common.replication.INcLifecycleCoordinator;
@@ -89,31 +91,31 @@
  */
 public class CcApplicationContext implements ICcApplicationContext {

-    private ICCServiceContext ccServiceCtx;
-    private IStorageComponentProvider storageComponentProvider;
-    private IGlobalRecoveryManager globalRecoveryManager;
-    private IResourceIdManager resourceIdManager;
-    private CompilerProperties compilerProperties;
-    private ExternalProperties externalProperties;
-    private MetadataProperties metadataProperties;
-    private StorageProperties storageProperties;
-    private TransactionProperties txnProperties;
-    private ActiveProperties activeProperties;
-    private BuildProperties buildProperties;
-    private ReplicationProperties replicationProperties;
-    private ExtensionProperties extensionProperties;
-    private MessagingProperties messagingProperties;
-    private NodeProperties nodeProperties;
+    private final ICCServiceContext ccServiceCtx;
+    private final IStorageComponentProvider storageComponentProvider;
+    private final IGlobalRecoveryManager globalRecoveryManager;
+    private final IResourceIdManager resourceIdManager;
+    private final CompilerProperties compilerProperties;
+    private final ExternalProperties externalProperties;
+    private final MetadataProperties metadataProperties;
+    private final StorageProperties storageProperties;
+    private final TransactionProperties txnProperties;
+    private final ActiveProperties activeProperties;
+    private final BuildProperties buildProperties;
+    private final ReplicationProperties replicationProperties;
+    private final ExtensionProperties extensionProperties;
+    private final MessagingProperties messagingProperties;
+    private final NodeProperties nodeProperties;
     private final CloudProperties cloudProperties;
-    private Supplier<IMetadataBootstrap> metadataBootstrapSupplier;
+    private final Supplier<IMetadataBootstrap> metadataBootstrapSupplier;
     private volatile HyracksConnection hcc;
     private volatile ResultSet resultSet;
-    private Object extensionManager;
-    private INcLifecycleCoordinator ftStrategy;
-    private IJobLifecycleListener activeLifeCycleListener;
-    private IMetadataLockManager mdLockManager;
-    private IMetadataLockUtil mdLockUtil;
-    private IClusterStateManager clusterStateManager;
+    private final Object extensionManager;
+    private final INcLifecycleCoordinator ftStrategy;
+    private final IJobLifecycleListener activeLifeCycleListener;
+    private final IMetadataLockManager mdLockManager;
+    private final IMetadataLockUtil mdLockUtil;
+    private final IClusterStateManager clusterStateManager;
     private final INodeJobTracker nodeJobTracker;
     private final ITxnIdFactory txnIdFactory;
     private final ICompressionManager compressionManager;
@@ -127,6 +129,7 @@
     private final IOManager ioManager;
     private final INamespacePathResolver namespacePathResolver;
     private final INamespaceResolver namespaceResolver;
+    private final IExternalStatsTracker externalStatsTracker;

     public CcApplicationContext(ICCServiceContext ccServiceCtx, 
HyracksConnection hcc,
             Supplier<IMetadataBootstrap> metadataBootstrapSupplier, 
IGlobalRecoveryManager globalRecoveryManager,
@@ -177,6 +180,7 @@
         this.globalTxManager = globalTxManager;
         this.ioManager = ioManager;
         dataPartitioningProvider = DataPartitioningProvider.create(this);
+        externalStatsTracker = new ExternalStatsTracker();
     }

     @Override
@@ -415,4 +419,9 @@
     public IOManager getIoManager() {
         return ioManager;
     }
+
+    @Override
+    public IExternalStatsTracker getExternalStatsTracker() {
+        return externalStatsTracker;
+    }
 }
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/external/ExternalStatsTracker.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/external/ExternalStatsTracker.java
new file mode 100644
index 0000000..ec88b8f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/external/ExternalStatsTracker.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.asterix.app.external;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.asterix.common.external.IExternalStatsTracker;
+import org.apache.asterix.external.util.ExternalDataConstants;
+
+public class ExternalStatsTracker implements IExternalStatsTracker {
+
+    private final Map<String, Map<String, AtomicLong>> 
totalAwsAssumeRoleFailures;
+
+    public ExternalStatsTracker() {
+        totalAwsAssumeRoleFailures = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public String resolveName(Map<String, String> configuration) {
+        // if dataset name is not in the configuration, it means we are still 
creating the dataset, return empty string
+        if (!configuration.containsKey(ExternalDataConstants.KEY_DATASET)) {
+            return "";
+        }
+
+        String database = 
configuration.get(ExternalDataConstants.KEY_DATASET_DATABASE);
+        String dataverse = 
configuration.get(ExternalDataConstants.KEY_DATASET_DATAVERSE);
+        String dataset = configuration.get(ExternalDataConstants.KEY_DATASET);
+        String name;
+        if (database != null && !database.isEmpty()) {
+            name = database + "." + dataverse + "." + dataset;
+        } else {
+            name = dataverse + "." + dataset;
+        }
+        return name;
+    }
+
+    @Override
+    public void incrementAwsAssumeRoleFailure(String name, String roleArn) {
+        // empty name means we are creating the external collection still
+        if (name.isEmpty()) {
+            return;
+        }
+        Map<String, AtomicLong> map =
+                totalAwsAssumeRoleFailures.computeIfAbsent(name, key -> new 
ConcurrentHashMap<>());
+        map.computeIfAbsent(roleArn, key -> new 
AtomicLong()).incrementAndGet();
+    }
+}
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
index f669d48..fa573a0 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/nc/NCAppRuntimeContext.java
@@ -31,6 +31,7 @@
 import java.util.concurrent.ExecutorService;

 import org.apache.asterix.active.ActiveManager;
+import org.apache.asterix.app.external.ExternalStatsTracker;
 import org.apache.asterix.app.result.ResultReader;
 import org.apache.asterix.cloud.CloudConfigurator;
 import org.apache.asterix.cloud.LocalPartitionBootstrapper;
@@ -62,8 +63,7 @@
 import org.apache.asterix.common.context.DiskWriteRateLimiterProvider;
 import org.apache.asterix.common.context.GlobalVirtualBufferCache;
 import org.apache.asterix.common.context.IStorageComponentProvider;
-import org.apache.asterix.common.external.IExternalCredentialsCache;
-import org.apache.asterix.common.external.IExternalCredentialsCacheUpdater;
+import org.apache.asterix.common.external.IExternalStatsTracker;
 import org.apache.asterix.common.library.ILibraryManager;
 import org.apache.asterix.common.replication.IReplicationChannel;
 import org.apache.asterix.common.replication.IReplicationManager;
@@ -193,8 +193,7 @@
     private final INamespacePathResolver namespacePathResolver;
     private final INamespaceResolver namespaceResolver;
     private IDiskCacheMonitoringService diskCacheService;
-    protected IExternalCredentialsCache externalCredentialsCache;
-    protected IExternalCredentialsCacheUpdater externalCredentialsCacheUpdater;
+    private final IExternalStatsTracker externalStatsTracker;

     public NCAppRuntimeContext(INCServiceContext ncServiceContext, 
NCExtensionManager extensionManager,
             IPropertiesFactory propertiesFactory, INamespaceResolver 
namespaceResolver,
@@ -219,6 +218,7 @@
         cacheManager = new CacheManager();
         this.namespacePathResolver = namespacePathResolver;
         this.namespaceResolver = namespaceResolver;
+        externalStatsTracker = new ExternalStatsTracker();
     }

     @Override
@@ -770,6 +770,11 @@
         return partitionBootstrapper;
     }

+    @Override
+    public IExternalStatsTracker getExternalStatsTracker() {
+        return externalStatsTracker;
+    }
+
     private int getResourceIdBlockSize() {
         return isCloudDeployment() ? 
storageProperties.getStoragePartitionsCount()
                 : ncServiceContext.getIoManager().getIODevices().size();
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index 731f411..b55d763 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -6046,7 +6046,6 @@
         String adapter = externalDetails.getAdapter();
         Map<String, String> details = new HashMap<>(properties);
         details.put(ExternalDataConstants.KEY_EXTERNAL_SOURCE_TYPE, adapter);
-        metadataProvider.setExternalEntityId(details);
         validateAdapterSpecificProperties(details, srcLoc, appCtx);
     }

@@ -6057,7 +6056,6 @@
         String adapterName = externalDetailsDecl.getAdapter();
         Map<String, String> properties = externalDetailsDecl.getProperties();
         properties.put(ExternalDataConstants.KEY_EXTERNAL_SOURCE_TYPE, 
adapterName);
-        md.setExternalEntityId(properties);
         WriterValidationUtil.validateWriterConfiguration(adapterName, 
supportedAdapters, properties, sourceLocation);
         return properties;
     }
diff --git 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IApplicationContext.java
 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IApplicationContext.java
index eabebf7..3e9f719 100644
--- 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IApplicationContext.java
+++ 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IApplicationContext.java
@@ -29,6 +29,7 @@
 import org.apache.asterix.common.config.ReplicationProperties;
 import org.apache.asterix.common.config.StorageProperties;
 import org.apache.asterix.common.config.TransactionProperties;
+import org.apache.asterix.common.external.IExternalStatsTracker;
 import org.apache.hyracks.api.application.IServiceContext;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -106,4 +107,6 @@
     INamespaceResolver getNamespaceResolver();

     INamespacePathResolver getNamespacePathResolver();
+
+    IExternalStatsTracker getExternalStatsTracker();
 }
diff --git 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCache.java
 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCache.java
deleted file mode 100644
index 689ff16..0000000
--- 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCache.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.asterix.common.external;
-
-public interface IExternalCredentialsCache {
-
-    /**
-     * Returns the cached credentials.
-     *
-     * @param key credentials key
-     * @return credentials if present and not expired/need refreshing, null 
otherwise
-     */
-    Object get(String key);
-
-    /**
-     * Deletes the cache for the provided entity
-     *
-     * @param key credentials key
-     */
-    void delete(String key);
-
-    /**
-     * Updates the credentials cache with the provided credentials for the 
specified name
-     *
-     * @param key credentials key
-     * @param credentials credentials to cache
-     */
-    void put(String key, Object credentials);
-}
diff --git 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCacheUpdater.java
 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalStatsTracker.java
similarity index 66%
rename from 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCacheUpdater.java
rename to 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalStatsTracker.java
index 48553c0..40493cc 100644
--- 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalCredentialsCacheUpdater.java
+++ 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/external/IExternalStatsTracker.java
@@ -20,16 +20,18 @@

 import java.util.Map;

-import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.hyracks.api.exceptions.HyracksDataException;
-
-public interface IExternalCredentialsCacheUpdater {
+public interface IExternalStatsTracker {

     /**
-     * Generates new credentials and caches them
+     * Resolves a name from the given configuration map
      *
-     * @param configuration configuration containing external collection 
details
+     * @param configuration The configuration map
+     * @return The resolved name
      */
-    Object generateAndCacheCredentials(Map<String, String> configuration)
-            throws HyracksDataException, CompilationException;
+    String resolveName(Map<String, String> configuration);
+
+    /**
+     * Increments the total AWS Assume Role failure count
+     */
+    void incrementAwsAssumeRoleFailure(String name, String roleArn);
 }
diff --git 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/aws/AwsUtils.java
 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/aws/AwsUtils.java
index 5ffd7e2..974eceb 100644
--- 
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/aws/AwsUtils.java
+++ 
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/aws/AwsUtils.java
@@ -43,6 +43,7 @@
 import org.apache.asterix.common.api.IApplicationContext;
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.external.IExternalStatsTracker;
 import org.apache.hyracks.api.util.CleanupUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -187,6 +188,22 @@
         // build sts client used for assuming role
         ClientOverrideConfiguration.Builder clientConfigurationBuilder = 
ClientOverrideConfiguration.builder();
         
clientConfigurationBuilder.addExecutionInterceptor(ASSUME_ROLE_INTERCEPTOR);
+        clientConfigurationBuilder.addExecutionInterceptor(new 
ExecutionInterceptor() {
+            @Override
+            public void onExecutionFailure(Context.FailedExecution context, 
ExecutionAttributes executionAttributes) {
+                SdkRequest req = context.request();
+                if (req instanceof AssumeRoleRequest assumeReq) {
+                    String roleArn = assumeReq.roleArn();
+                    Throwable th = context.exception();
+                    LOGGER.info("encountered issue assuming role ({}): {}", 
roleArn, getMessageOrToString(th));
+
+                    IExternalStatsTracker externalStatsTracker = 
appCtx.getExternalStatsTracker();
+                    String name = 
externalStatsTracker.resolveName(configuration);
+                    externalStatsTracker.incrementAwsAssumeRoleFailure(name, 
roleArn);
+                }
+                ExecutionInterceptor.super.onExecutionFailure(context, 
executionAttributes);
+            }
+        });
         ClientOverrideConfiguration clientConfiguration = 
clientConfigurationBuilder.build();

         StsClientBuilder stsClientBuilder = StsClient.builder();

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20517?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: asterixdb
Gerrit-Branch: phoenix
Gerrit-Change-Id: Ifca24a07d733f5652030032784676c0b3aea47f8
Gerrit-Change-Number: 20517
Gerrit-PatchSet: 5
Gerrit-Owner: Hussain Towaileb <[email protected]>
Gerrit-Reviewer: Anon. E. Moose #1000171
Gerrit-Reviewer: Hussain Towaileb <[email protected]>
Gerrit-Reviewer: Jenkins <[email protected]>
Gerrit-Reviewer: Murtadha Hubail <[email protected]>

Reply via email to