diff --git a/app/enrichment/app.py b/app/enrichment/app.py index d4f9ed29..27138483 100644 --- a/app/enrichment/app.py +++ b/app/enrichment/app.py @@ -4,6 +4,8 @@ import json import logging import os +import threading +import time import re from datetime import datetime from typing import List @@ -276,9 +278,17 @@ def get_tags_and_upload_to_cosmos(blob_service_client, blob_path): tagsHelper.upsert_document(blob_path, tags_list) return tags_list - @app.on_event("startup") -@repeat_every(seconds=5, logger=log, raise_exceptions=True) +def startup_event(): + poll_thread = threading.Thread(target=poll_queue_thread) + poll_thread.daemon = True + poll_thread.start() + +def poll_queue_thread(): + while True: + poll_queue() + time.sleep(5) + def poll_queue() -> None: """Polls the queue for messages and embeds them""" @@ -294,6 +304,11 @@ def poll_queue() -> None: response = queue_client.receive_messages(max_messages=int(ENV["DEQUEUE_MESSAGE_BATCH_SIZE"])) messages = [x for x in response] + if not messages: + log.debug("No messages to process. Waiting for a couple of minutes...") + time.sleep(120) # Sleep for 2 minutes + return + target_embeddings_model = re.sub(r'[^a-zA-Z0-9_\-.]', '_', ENV["TARGET_EMBEDDINGS_MODEL"]) # Remove from queue to prevent duplicate processing from any additional instances diff --git a/app/frontend/src/components/filepicker/file-picker.tsx b/app/frontend/src/components/filepicker/file-picker.tsx index f8473a9e..def593b3 100644 --- a/app/frontend/src/components/filepicker/file-picker.tsx +++ b/app/frontend/src/components/filepicker/file-picker.tsx @@ -24,17 +24,17 @@ const FilePicker = ({folderPath, tags}: Props) => { // handler called when files are selected via the Dropzone component const handleOnChange = useCallback((files: any) => { + let filesArray = Array.from(files); filesArray = filesArray.map((file) => ({ id: nanoid(), file - })); - + })); setFiles(filesArray as any); setProgress(0); setUploadStarted(false); - }, []); +}, []); // handle for removing files form the files list view const handleClearFile = useCallback((id: any) => { diff --git a/docs/deployment/autoscale_sku.md b/docs/deployment/autoscale_sku.md new file mode 100644 index 00000000..688d4213 --- /dev/null +++ b/docs/deployment/autoscale_sku.md @@ -0,0 +1,149 @@ +# Autoscale Settings Documentation + +These are the current out of the box Autoscale settings. +You may find better settings to fit your needs. This document explains how this can be accomplished. + +## Azure Functions Service Plan Autoscale + +### Overview + +The Azure Functions Service Plan Autoscale settings are defined in the file located at `/infra/core/host/funcserviceplan.bicep`. These settings enable automatic scaling of the Azure Functions Service Plan based on CPU usage metrics. + + + + **File Location:** `/infra/core/host/funcserviceplan.bicep` + +#### Scaling Rules + +1. **Increase Capacity Rule:** + - **Metric:** `CpuPercentage` + - **Operator:** `GreaterThan` + - **Threshold:** `60%` + - **Time Window:** `5 minutes` + - **Scaling Action:** Increase capacity by `2` with a cooldown of `5 minutes`. + +2. **Decrease Capacity Rule:** + - **Metric:** `CpuPercentage` + - **Operator:** `LessThan` + - **Threshold:** `40%` + - **Time Window:** `5 minutes` + - **Scaling Action:** Decrease capacity by `2` with a cooldown of `2 minutes`. + + +## App Service Plan Autoscale for Enrichment App + +### Overview + +The App Service Plan Autoscale settings for the enrichment app are defined in the file located at `/infra/core/host.enrichmentappserviceplan.bicep`. These settings enable automatic scaling of the App Service Plan based on CPU usage metrics. + +### Key Parameters + +**File Location:** `/infra/core/host.enrichmentappserviceplan.bicep` + +#### Scaling Rules + +1. **Increase Capacity Rule:** + - **Metric:** `CpuPercentage` + - **Operator:** `GreaterThan` + - **Threshold:** `60%` + - **Time Window:** `5 minutes` + - **Scaling Action:** Increase capacity by `1` with a cooldown of `5 minutes`. + +2. **Decrease Capacity Rule:** + - **Metric:** `CpuPercentage` + - **Operator:** `LessThan` + - **Threshold:** `20%` + - **Time Window:** `10 minutes` + - **Scaling Action:** Decrease capacity by `1` with a cooldown of `15 minutes`. + +### Customization + +To customize the App Service Plan Autoscale settings, modify the parameters mentioned above in the specified Bicep file. And Run the `make infrastructure` command. + + + +# SKU Settings Documentation + +### Overview + +The SKU settings for all Service Plans are defined in the file located at `/infra/main.bicep`. The SKU (Stock Keeping Unit) represents the pricing tier or plan for your App Service. It defines the performance, features, and capacity of the App Service. +More information can be found [here.](https://azure.microsoft.com/en-us/pricing/details/app-service/windows/#purchase-options) + +## Web App Service Plan SKU + + +**File Location:** `/infra/main.bicep` + +#### SKU Settings + +- **Name:** `S1` +- **Capacity:** `3` + + +## Functions Service Plan SKU + + +**File Location:** `/infra/main.bicep` + +#### SKU Settings + +- **Name:** `S2` +- **Capacity:** `2` + +## Enrichment App Service Plan SKU + + +**File Location:** `/infra/main.bicep` + +#### SKU Settings + +- **Name:** `P1v3` +- **Tier:** `PremiumV3` +- **Size:** `P1v3` +- **Family:** `Pv3` +- **Capacity:** `1` + +### Enrichment Message Dequeue Parameter +There exist a property that can be set in the local.env file called `DEQUEUE_MESSAGE_BATCH_SIZE` and is defaulted in the `infra/main.bicep` and `app/enrichment/app.py` to the value of **3**. This means the app will process 3 messages from the queue at a time. This is found to be the most opitmal with the existing configuration but can be increased if you also increase the enrichment app service SKU. It is important to note that there will be issues if it is increased more than the app service SKU can handle. + +### Customization + +To customize the App Service Plans SKU settings, modify the `sku` parameters in the specified Bicep file and run the `make deploy` or `make infrastructure`command. + +This can also be adjusted in the Azure Portal. + +**Note:** Adjusting the scale or Tier can cause outages until the redeployment occurrs. + + +### Steps to Scale Up: + +>1. **Sign in to the Azure Portal:** +> - Open a web browser and navigate to the [Azure Portal](https://portal.azure.com/). +> - Log in with your Azure account credentials. + +>2. **Navigate to the App Service:** +> - In the left navigation pane, select "App Services." +> - Click on the specific App Service you want to scale. + +>3. **Access the Scale Up Blade:** +> - In the App Service menu, find and click on "Scale up (App Service plan)" in the left sidebar. + +>4. **Choose a New Pricing Tier:** +> - On the "Scale Up" blade, you'll see different pricing tiers representing various levels of resources. +> - Select the desired pricing tier that corresponds to the scale you need. + +>5. **Review and Apply Changes:** +> - Review the information about the selected pricing tier, including its features and costs. +> - Click the "Apply" or "Save" button to apply the changes. + + +### Considerations: +- **Cost Implications:** + - Be aware of the cost implications associated with higher pricing tiers. Review the Azure Pricing documentation for details on costs. + +- **Resource Limits:** + - Ensure that the new pricing tier aligns with the resource requirements of your application. Some tiers may have limitations on resources. + +- **Performance Impact:** + - Scaling up provides additional resources, potentially improving performance. However, it's essential to assess whether your application benefits from the increased resources. + diff --git a/docs/features/optional_features.md b/docs/features/optional_features.md index b0634a3b..21fc6c50 100644 --- a/docs/features/optional_features.md +++ b/docs/features/optional_features.md @@ -10,6 +10,7 @@ Please see below sections for coverage of IA Accelerator optional features. * [Customer Usage Attribution](/docs/features/features.md#customer-usage-attribution) * [Sovereign Region Deployment](/docs/features/features.md#sovereign-region-deployment) * [Configure REST API access](#configure-rest-api-access) +* [Customize Autoscale and App Service SKU's](#customize-autoscale) ## Configuring your own language ENV file @@ -45,3 +46,8 @@ Check out how to [setup Sovereign Region Deployment](/docs/deployment/enable_sov If you are wanting to use the API stand-alone or use a custom UI. Check out how to [enable OAuth Client Credentials Flow](/docs/deployment/client_credentials_flow.md) + +## Customize Autoscale + +If you want to learn more about Autoscale Settings and App Service SKU's +Check out how to [customize Autoscale settings](/docs/deployment/autoscale_sku.md) diff --git a/functions/host.json b/functions/host.json index 58badc32..b13fe7ee 100644 --- a/functions/host.json +++ b/functions/host.json @@ -12,9 +12,14 @@ "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[3.*, 4.0.0)" }, + "extensions": { + "queues": { + "batchSize": 3 + } + }, "concurrency": { - "dynamicConcurrencyEnabled": true, - "snapshotPersistenceEnabled": true + "dynamicConcurrencyEnabled": false, + "snapshotPersistenceEnabled": false }, - "functionTimeout": "01:00:00" + "functionTimeout": "02:00:00" } \ No newline at end of file diff --git a/infra/core/host/enrichmentappserviceplan.bicep b/infra/core/host/enrichmentappserviceplan.bicep index fcf18b10..c01ebe20 100644 --- a/infra/core/host/enrichmentappserviceplan.bicep +++ b/infra/core/host/enrichmentappserviceplan.bicep @@ -6,8 +6,6 @@ param kind string = '' param reserved bool = true param sku object -param storageAccountId string - // Create an App Service Plan to group applications under the same payment plan and SKU, specifically for containers resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = { @@ -40,29 +38,45 @@ resource scaleOutRule 'Microsoft.Insights/autoscalesettings@2022-10-01' = { { name: 'Scale out condition' capacity: { - maximum: '3' + maximum: '5' default: '1' minimum: '1' } rules: [ { + metricTrigger: { + metricName: 'CpuPercentage' + metricResourceUri: appServicePlan.id + timeGrain: 'PT1M' + statistic: 'Average' + timeWindow: 'PT5M' + timeAggregation: 'Average' + operator: 'GreaterThan' + threshold: 60 + } scaleAction: { direction: 'Increase' type: 'ChangeCount' value: '1' cooldown: 'PT5M' } + } + { metricTrigger: { - metricName: 'ApproximateMessageCount' - metricNamespace: '' - metricResourceUri: storageAccountId - operator: 'GreaterThan' - statistic: 'Average' - threshold: 10 - timeAggregation: 'Average' + metricName: 'CpuPercentage' + metricResourceUri: appServicePlan.id timeGrain: 'PT1M' + statistic: 'Average' timeWindow: 'PT10M' - dividePerInstance: true + timeAggregation: 'Average' + operator: 'LessThan' + threshold: 20 + } + scaleAction: { + direction: 'Decrease' + type: 'ChangeCount' + value: '1' + cooldown: 'PT15M' } } ] diff --git a/infra/core/host/funcserviceplan.bicep b/infra/core/host/funcserviceplan.bicep index 72ae143b..4379b828 100644 --- a/infra/core/host/funcserviceplan.bicep +++ b/infra/core/host/funcserviceplan.bicep @@ -17,5 +17,62 @@ resource funcServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = { } } +resource autoscaleSettings 'Microsoft.Insights/autoscalesettings@2022-10-01' = { + name: '${funcServicePlan.name}-Autoscale' + location: location + properties: { + enabled: true + profiles: [ + { + name: '${funcServicePlan.name}-Autoscale' + capacity: { + default: '2' + minimum: '2' + maximum: '10' + } + rules: [ + { + metricTrigger: { + metricName: 'CpuPercentage' + metricResourceUri: funcServicePlan.id + timeGrain: 'PT1M' + statistic: 'Average' + timeWindow: 'PT5M' + timeAggregation: 'Average' + operator: 'GreaterThan' + threshold: 60 + } + scaleAction: { + direction: 'Increase' + type: 'ChangeCount' + value: '2' + cooldown: 'PT5M' + } + } + { + metricTrigger: { + metricName: 'CpuPercentage' + metricResourceUri: funcServicePlan.id + timeGrain: 'PT1M' + statistic: 'Average' + timeWindow: 'PT5M' + timeAggregation: 'Average' + operator: 'LessThan' + threshold: 40 + } + scaleAction: { + direction: 'Decrease' + type: 'ChangeCount' + value: '2' + cooldown: 'PT2M' + } + } + ] + } + ] + targetResourceUri: funcServicePlan.id + } +} + output id string = funcServicePlan.id output name string = funcServicePlan.name diff --git a/infra/main.bicep b/infra/main.bicep index 9b50a0c7..fafd99fc 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -155,8 +155,8 @@ module funcServicePlan 'core/host/funcserviceplan.bicep' = { location: location tags: tags sku: { - name: 'S3' - capacity: 5 + name: 'S2' + capacity: 2 } kind: 'linux' } @@ -175,11 +175,10 @@ module enrichmentAppServicePlan 'core/host/enrichmentappserviceplan.bicep' = { tier: 'PremiumV3' size: 'P1v3' family: 'Pv3' - capacity: 3 + capacity: 1 } kind: 'linux' reserved: true - storageAccountId: '/subscriptions/${subscriptionId}/resourceGroups/${rg.name}/providers/Microsoft.Storage/storageAccounts/${storage.outputs.name}/services/queue/queues/${embeddingsQueue}' } } @@ -204,7 +203,7 @@ module enrichmentApp 'core/host/enrichmentappservice.bicep' = { AZURE_BLOB_STORAGE_KEY: storage.outputs.key EMBEDDINGS_QUEUE: embeddingsQueue LOG_LEVEL: 'DEBUG' - DEQUEUE_MESSAGE_BATCH_SIZE: 1 + DEQUEUE_MESSAGE_BATCH_SIZE: 3 AZURE_BLOB_STORAGE_ACCOUNT: storage.outputs.name AZURE_BLOB_STORAGE_CONTAINER: containerName AZURE_BLOB_STORAGE_UPLOAD_CONTAINER: uploadContainerName diff --git a/scripts/inf-create.sh b/scripts/inf-create.sh index 1cc9c2de..197fca9e 100755 --- a/scripts/inf-create.sh +++ b/scripts/inf-create.sh @@ -216,4 +216,4 @@ results=$(az deployment sub create --location $LOCATION --template-file main.bic #save deployment output printInfo "Writing output to infra_output.json" pushd "$DIR/.." -echo $results > infra_output.json +echo $results > infra_output.json \ No newline at end of file