diff --git a/samples/databases/wide-world-importers/wwi-ssis/wwi-ssis/DailyETLMain.dtsx b/samples/databases/wide-world-importers/wwi-ssis/wwi-ssis/DailyETLMain.dtsx
index e3a97158..796d73cf 100644
--- a/samples/databases/wide-world-importers/wwi-ssis/wwi-ssis/DailyETLMain.dtsx
+++ b/samples/databases/wide-world-importers/wwi-ssis/wwi-ssis/DailyETLMain.dtsx
@@ -6829,4 +6829,6255 @@ WITH RESULT SETS
WITH RESULT SETS
(
(
- [WWI Stock Item ID] int,
\ No newline at end of file
+ [WWI Stock Item ID] int,
+ [Stock Item] nvarchar(100),
+ Color nvarchar(20),
+ [Selling Package] nvarchar(50),
+ [Buying Package] nvarchar(50),
+ Brand nvarchar(50),
+ Size nvarchar(20),
+ [Lead Time Days] int,
+ [Quantity Per Outer] int,
+ [Is Chiller Stock] bit,
+ Barcode nvarchar(50),
+ [Tax Rate] decimal(18,3),
+ [Unit Price] decimal(18,2),
+ [Recommended Retail Price] decimal(18,2),
+ [Typical Weight Per Unit] decimal(18,3),
+ Photo varbinary(max),
+ [Valid From] datetime2(7),
+ [Valid To] datetime2(7)
+ )
+);
+
+ 1252
+ false
+ 2
+ "@LastCutoff:Input",{60BD9010-4784-49A6-8FF2-340D7AB3B70D};"@NewCutoff:Input",{B96D08A3-EC4E-45C1-8E78-526920753C6B};
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ [Integration].[StockItem_Staging]
+
+
+ 1252
+ false
+ 3
+ false
+ false
+ CHECK_CONSTRAINTS
+ 2147483647
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+ EXEC Integration.GetSupplierUpdates ?, ?
+WITH RESULT SETS
+(
+ (
+ [WWI Supplier ID] int,
+ Supplier nvarchar(100),
+ Category nvarchar(50),
+ [Primary Contact] nvarchar(50),
+ [Supplier Reference] nvarchar(20),
+ [Payment Days] int,
+ [Postal Code] nvarchar(10),
+ [Valid From] datetime2(7),
+ [Valid To] datetime2(7)
+ )
+);
+
+ 1252
+ false
+ 2
+ "@LastCutoff:Input",{60BD9010-4784-49A6-8FF2-340D7AB3B70D};"@NewCutoff:Input",{B96D08A3-EC4E-45C1-8E78-526920753C6B};
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ [Integration].[Supplier_Staging]
+
+
+ 1252
+ false
+ 3
+ false
+ false
+ CHECK_CONSTRAINTS
+ 2147483647
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+ EXEC Integration.GetTransactionUpdates ?, ?
+WITH RESULT SETS
+(
+ (
+ [Date Key] date,
+ [WWI Customer Transaction ID] int,
+ [WWI Supplier Transaction ID] int,
+ [WWI Invoice ID] int,
+ [WWI Purchase Order ID] int,
+ [Supplier Invoice Number] nvarchar(20),
+ [Total Excluding Tax] decimal(18,2),
+ [Tax Amount] decimal(18,2),
+ [Total Including Tax] decimal(18,2),
+ [Outstanding Balance] decimal(18,2),
+ [Is Finalized] bit,
+ [WWI Customer ID] int,
+ [WWI Bill To Customer ID] int,
+ [WWI Supplier ID] int,
+ [WWI Transaction Type ID] int,
+ [WWI Payment Method ID] int,
+ [Last Modified When] datetime2(7)
+ )
+);
+
+ 1252
+ false
+ 2
+ "@LastCutoff:Input",{60BD9010-4784-49A6-8FF2-340D7AB3B70D};"@NewCutoff:Input",{B96D08A3-EC4E-45C1-8E78-526920753C6B};
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ [Integration].[Transaction_Staging]
+
+
+ 1252
+ false
+ 3
+ false
+ false
+ CHECK_CONSTRAINTS
+ 2147483647
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+ EXEC Integration.GetTransactionTypeUpdates ?, ?
+WITH RESULT SETS
+(
+ (
+ [WWI Transaction Type ID] int,
+ [Transaction Type] nvarchar(50),
+ [Valid From] datetime2(7),
+ [Valid To] datetime2(7)
+ )
+);
+
+ 1252
+ false
+ 2
+ "@LastCutoff:Input",{60BD9010-4784-49A6-8FF2-340D7AB3B70D};"@NewCutoff:Input",{B96D08A3-EC4E-45C1-8E78-526920753C6B};
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ [Integration].[TransactionType_Staging]
+
+
+ 1252
+ false
+ 3
+ false
+ false
+ CHECK_CONSTRAINTS
+ 2147483647
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DataSourceViewID
+
+
+ TableInfoObjectType
+ Table
+
+
+
+]]>
+
\ No newline at end of file
diff --git a/samples/demos/azure-sql-edge-demos/Wind Turbine Demo/webappsrc/SqlDbEdgeDemoWeb/SqlDbEdgeDemo.Web/ClientApp/package-lock.json b/samples/demos/azure-sql-edge-demos/Wind Turbine Demo/webappsrc/SqlDbEdgeDemoWeb/SqlDbEdgeDemo.Web/ClientApp/package-lock.json
index 1245a383..5dc1f9f1 100644
--- a/samples/demos/azure-sql-edge-demos/Wind Turbine Demo/webappsrc/SqlDbEdgeDemoWeb/SqlDbEdgeDemo.Web/ClientApp/package-lock.json
+++ b/samples/demos/azure-sql-edge-demos/Wind Turbine Demo/webappsrc/SqlDbEdgeDemoWeb/SqlDbEdgeDemo.Web/ClientApp/package-lock.json
@@ -4937,9 +4937,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
"ejs": {
- "version": "3.1.8",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
- "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
+ "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
"requires": {
"jake": "^10.8.5"
}
@@ -12762,9 +12762,9 @@
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="
},
"tar": {
- "version": "6.1.15",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
- "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
diff --git a/samples/features/azure-arc/dashboard/Arc - SQL Server Inventory.json b/samples/features/azure-arc/dashboard/Arc - SQL Server Inventory.json
index a171f5c1..03fb8669 100644
--- a/samples/features/azure-arc/dashboard/Arc - SQL Server Inventory.json
+++ b/samples/features/azure-arc/dashboard/Arc - SQL Server Inventory.json
@@ -731,7 +731,7 @@
},
"partHeader": {
"title": "SQL Server Instances by Location",
- "subtitle": "SQL Servers instasnces by \"Location\" tag values"
+ "subtitle": "SQL Servers instances by \"Location\" tag values"
}
}
},
@@ -785,7 +785,7 @@
"content": {}
},
"partHeader": {
- "title": "SQL Server Instasnces by Data Center",
+ "title": "SQL Server Instances by Data Center",
"subtitle": "SQL Servers instances by \"Datacenter\" tag values."
}
}
diff --git a/samples/features/azure-arc/dashboard/Arc - Server Deployment.json b/samples/features/azure-arc/dashboard/Arc - Server Deployment.json
index 5030e89f..a6033ae8 100644
--- a/samples/features/azure-arc/dashboard/Arc - Server Deployment.json
+++ b/samples/features/azure-arc/dashboard/Arc - Server Deployment.json
@@ -678,14 +678,14 @@
},
{
"name": "query",
- "value": "resources\r\n | where type == \"microsoft.hybridcompute/machines\"\r\n | where properties.detectedProperties.mssqldiscovered == true\r\n | extend serverId = tolower(tostring(id))\r\n | extend serverName = name\r\n | extend serverProvisioningState = tostring(properties.provisioningState)\r\n | extend serverServerStatus = tostring(properties.status)\r\n | extend serverProcessorCount = properties.detectedProperties.processorCount\r\n | extend serverCoreCount = toint(properties.detectedProperties.coreCount)\r\n | extend serverLogicalCoreCount = toint(properties.detectedProperties.logicalCoreCount)\r\n | join kind= leftouter (\r\n resources\r\n | where type == \"microsoft.hybridcompute/machines/extensions\"\r\n | where properties.type in (\"WindowsAgent.SqlServer\",\"LinuxAgent.SqlServer\")\r\n | extend extensionId = tolower(tostring(id))\r\n | extend extensionServerId = tolower(tostring (iff(id contains \"/extensions/WindowsAgent.SqlServer\" or id contains \"/extensions/LinuxAgent.SqlServer\", substring(id, 0, indexof(id, \"/extensions/\")), \"\")))\r\n | extend extensionProvisioningState = tostring(properties.provisioningState) \r\n | extend extensionLicenseType = tostring(properties.settings.LicenseType)\r\n )\r\n on $left.serverId == $right.extensionServerId\r\n | join kind= leftouter (\r\n resources\r\n | where type == 'microsoft.azurearcdata/sqlserverinstances' \r\n | extend sqlId = tolower(tostring(id))\r\n | extend sqlServerId = tolower(tostring(properties.containerResourceId))\r\n | extend sqlName = name\r\n | extend sqlProvisioningState = tostring(properties.provisioningState)\r\n | extend sqlServerStatus = tostring(properties.status)\r\n | extend sqlVersion = tostring(properties.version)\r\n | extend sqlLicenseType = tostring(properties.licenseType)\r\n | extend sqlEdition = tostring(properties.edition)\r\n | extend sqlvcore = toint(properties.vCore)\r\n )\r\n on $left.extensionServerId == $right.sqlServerId\r\n | where isnotempty(sqlServerId)\r\n //| project sqlEdition, serverName, sqlName, sqlLicenseType, extensionLicenseType, serverCoreCount, sqlvcore\r\n | where sqlLicenseType in (\"Paid\", \"ServerCAL\")\r\n | where sqlEdition in (\"Enterprise\", \"Standard\")\r\n | summarize count(sqlName), min(serverCoreCount), sum(sqlvcore) by serverName, extensionLicenseType\r\n | summarize [\"Number of Servers\"] = count(serverName), [\"Number of SQL Servers\"] = sum(count_sqlName), \r\n [\"Number of Windows Cores\"] = sum(min_serverCoreCount), [\"Number of SQL Cores\"] = sum(sum_sqlvcore) \r\n by [\"Extension License Type\"] = extensionLicenseType",
+ "value": "resources\r\n | where type == \"microsoft.hybridcompute/machines\"\r\n | where properties.detectedProperties.mssqldiscovered == true\r\n | extend serverId = tolower(tostring(id))\r\n | extend serverName = name\r\n | extend serverProvisioningState = tostring(properties.provisioningState)\r\n | extend serverServerStatus = tostring(properties.status)\r\n | extend serverProcessorCount = properties.detectedProperties.processorCount\r\n | extend serverCoreCount = toint(properties.detectedProperties.coreCount)\r\n | extend serverLogicalCoreCount = toint(properties.detectedProperties.logicalCoreCount)\r\n | join kind= leftouter (\r\n resources\r\n | where type == \"microsoft.hybridcompute/machines/extensions\"\r\n | where properties.type in (\"WindowsAgent.SqlServer\",\"LinuxAgent.SqlServer\")\r\n | extend extensionId = tolower(tostring(id))\r\n | extend extensionServerId = tolower(tostring (iff(id contains \"/extensions/WindowsAgent.SqlServer\" or id contains \"/extensions/LinuxAgent.SqlServer\", substring(id, 0, indexof(id, \"/extensions/\")), \"\")))\r\n | extend extensionProvisioningState = tostring(properties.provisioningState) \r\n | extend extensionLicenseType = tostring(properties.settings.LicenseType)\r\n )\r\n on $left.serverId == $right.extensionServerId\r\n | join kind= leftouter (\r\n resources\r\n | where type == 'microsoft.azurearcdata/sqlserverinstances' \r\n | extend sqlId = tolower(tostring(id))\r\n | extend sqlServerId = tolower(tostring(properties.containerResourceId))\r\n | extend sqlName = name\r\n | extend sqlProvisioningState = tostring(properties.provisioningState)\r\n | extend sqlServerStatus = tostring(properties.status)\r\n | extend sqlVersion = tostring(properties.version)\r\n | extend sqlLicenseType = tostring(properties.licenseType)\r\n | extend sqlEdition = tostring(properties.edition)\r\n | extend sqlvcore = toint(properties.vCore)\r\n )\r\n on $left.extensionServerId == $right.sqlServerId\r\n | where isnotempty(sqlServerId)\r\n //| project sqlEdition, serverName, sqlName, sqlLicenseType, extensionLicenseType, serverCoreCount, sqlvcore\r\n | where sqlLicenseType in (\"Paid\", \"ServerCAL\")\r\n | where sqlEdition in (\"Enterprise\", \"Standard\")\r\n | summarize count(sqlName), min(serverCoreCount) by serverName, extensionLicenseType\r\n | summarize [\"Number of Servers\"] = count(serverName), [\"Number of SQL Servers\"] = sum(count_sqlName), \r\n [\"Number of Windows Cores\"] = sum(min_serverCoreCount) \r\n by [\"Extension License Type\"] = extensionLicenseType",
"isOptional": true
}
],
"type": "Extension/HubsExtension/PartType/ArgQueryGridTile",
"settings": {},
"partHeader": {
- "title": "Number of Cores",
+ "title": "Number of Cores for Production Servers Only (EE/SE)",
"subtitle": "SQL License in (Paid and ServerCAL)"
}
}
@@ -1011,6 +1011,60 @@
"subtitle": "SQL Server 2014 ESU"
}
}
+ },
+ "19": {
+ "position": {
+ "x": 0,
+ "y": 38,
+ "colSpan": 18,
+ "rowSpan": 4
+ },
+ "metadata": {
+ "inputs": [
+ {
+ "name": "partTitle",
+ "value": "Query 2",
+ "isOptional": true
+ },
+ {
+ "name": "query",
+ "value": "resources\r\n | where type == \"microsoft.hybridcompute/machines\"\r\n | extend serverId = tolower(tostring(id))\r\n | extend serverName = name\r\n | extend serverSubscriptionId = subscriptionId\r\n | extend serverLocation = location\r\n | extend serverResourceGroup = resourceGroup\r\n | extend serverTags = tags\r\n | extend serverProvisioningState = tostring(properties.provisioningState)\r\n | extend serverServerStatus = tostring(properties.status)\r\n | extend serverDisplayName = tostring(properties.displayName)\r\n | extend serverMssqldiscovered = properties.detectedProperties.mssqldiscovered\r\n | extend serverComputerName = tostring(properties.osProfile.computerName)\r\n | project serverId, \r\n [\"Server Name\"] = serverName, [\"Display Name\"] = serverDisplayName, [\"Computer Name\"] = serverComputerName, \r\n [\"Server State\"] = serverProvisioningState, [\"Server Status\"] = serverServerStatus, [\"MSSQL Discovered\"] = serverMssqldiscovered,\r\n [\"Subscription Id\"] = serverSubscriptionId, [\"Location\"] = serverLocation, [\"Resource Group\"] = serverResourceGroup, [\"Server Tags\"] = serverTags\r\n | join kind= leftouter (\r\n resources\r\n | where type == \"microsoft.hybridcompute/machines/extensions\"\r\n | where properties.type in (\"WindowsAgent.SqlServer\",\"LinuxAgent.SqlServer\")\r\n | extend extensionId = tolower(tostring(id))\r\n | extend extensionServerId = tolower(tostring (iff(id contains \"/extensions/WindowsAgent.SqlServer\" or id contains \"/extensions/LinuxAgent.SqlServer\", \r\n substring(id, 0, indexof(id, \"/extensions/\")), \r\n \"\")))\r\n | extend extensionProvisioningState = tostring(properties.provisioningState) \r\n | extend extensionType = tostring(properties.type)\r\n | extend extensionVersion = properties.instanceView.typeHandlerVersion\r\n | parse properties with * 'SQL Server Extension Agent: ' sqlAgentStatus ';' *\r\n | parse properties with * 'uploadStatus : ' uploadStatus ';' *\r\n | extend extensionSQLAgentStatus = iff(isnotempty(sqlAgentStatus),sqlAgentStatus,\"Unhealthy\")\r\n | extend extensionUploadStatus = iff(isnotempty(uploadStatus),uploadStatus,\"Missing SQL Agent\")\r\n | extend extensionLicenseType = tostring(properties.settings.LicenseType)\r\n | project extensionId, extensionServerId,\r\n [\"Extension State\"] = extensionProvisioningState, [\"SQLExtension Status\"] = extensionSQLAgentStatus, [\"DPS Status\"] = extensionUploadStatus, \r\n [\"Extension Name\"] = extensionType, [\"Extension Version\"] = extensionVersion,\r\n [\"Extension License\"] = extensionLicenseType\r\n )\r\n on $left.serverId == $right.extensionServerId\r\n | summarize uploadStatusBreakdown = count() by [\"DPS Status\"]",
+ "isOptional": true
+ },
+ {
+ "name": "chartType",
+ "value": 1,
+ "isOptional": true
+ },
+ {
+ "name": "isShared",
+ "isOptional": true
+ },
+ {
+ "name": "queryId",
+ "value": "",
+ "isOptional": true
+ },
+ {
+ "name": "formatResults",
+ "isOptional": true
+ },
+ {
+ "name": "queryScope",
+ "value": {
+ "scope": 0,
+ "values": []
+ },
+ "isOptional": true
+ }
+ ],
+ "type": "Extension/HubsExtension/PartType/ArgQueryChartTile",
+ "settings": {},
+ "partHeader": {
+ "title": "Data Processing Service (DPS) Status",
+ "subtitle": ""
+ }
+ }
}
}
}
diff --git a/samples/features/azure-arc/dashboard/SQL Server Instances.json b/samples/features/azure-arc/dashboard/SQL Server Instances.json
index 6845ef6a..886cc071 100644
--- a/samples/features/azure-arc/dashboard/SQL Server Instances.json
+++ b/samples/features/azure-arc/dashboard/SQL Server Instances.json
@@ -741,6 +741,60 @@
"subtitle": ""
}
}
+ },
+ "14": {
+ "position": {
+ "x": 0,
+ "y": 30,
+ "colSpan": 19,
+ "rowSpan": 4
+ },
+ "metadata": {
+ "inputs": [
+ {
+ "name": "partTitle",
+ "value": "Query 1",
+ "isOptional": true
+ },
+ {
+ "name": "chartType",
+ "isOptional": true
+ },
+ {
+ "name": "isShared",
+ "isOptional": true
+ },
+ {
+ "name": "queryId",
+ "isOptional": true
+ },
+ {
+ "name": "formatResults",
+ "isOptional": true
+ },
+ {
+ "name": "queryScope",
+ "value": {
+ "scope": 0,
+ "values": []
+ },
+ "isOptional": true
+ },
+ {
+ "name": "query",
+ "value": "resources\r\n | where type =~ 'microsoft.hybridcompute/machines/extensions'\r\n | where properties.type in ('WindowsAgent.SqlServer','LinuxAgent.SqlServer')\r\n | parse id with * '/providers/Microsoft.HybridCompute/machines/' machineName '/extensions/' *\r\n | parse properties with * 'uploadStatus : ' uploadStatus ';' *\r\n | project uploadStatus, subscriptionId, resourceGroup, machineName\r\n | where uploadStatus !in ('OK') //comment this out to see all upload stats\r\n | order by uploadStatus desc",
+ "isOptional": true
+ }
+ ],
+ "type": "Extension/HubsExtension/PartType/ArgQueryGridTile",
+ "settings": {
+ "content": {}
+ },
+ "partHeader": {
+ "title": "Servers with Errors communicating with Azure DPS Service",
+ "subtitle": "For more information see https://learn.microsoft.com/en-us/sql/sql-server/azure-arc/troubleshoot-telemetry-endpoint"
+ }
+ }
}
}
}
diff --git a/samples/features/reporting-services/ssrs-migration-rss/ssrs_migration.rss b/samples/features/reporting-services/ssrs-migration-rss/ssrs_migration.rss
index ac675037..49164e10 100644
--- a/samples/features/reporting-services/ssrs-migration-rss/ssrs_migration.rss
+++ b/samples/features/reporting-services/ssrs-migration-rss/ssrs_migration.rss
@@ -75,7 +75,7 @@ Private policies As Policy() = Nothing
Private srcSiteUrl As String = Nothing
Private snkSiteUrl As String = Nothing
-Private logFilePath As String = "MigrationLog.txt"
+Private logFilePath As String = "MigrationLog.csv"
''''''''''''''''''''''''''''''''''''''''''''''
Sub Main()
@@ -241,8 +241,8 @@ Sub Main()
RsSnk.CreateFolder(folderName, parentFolder, Nothing)
Catch er As Exception
If (er.Message.Contains("Microsoft.ReportingServices.Diagnostics.Utilities.ItemAlreadyExistsException"))
- Console.ForegroundColor = ConsoleColor.Yellow
- Console.WriteLine("Folder already exists.")
+ Console.ForegroundColor = ConsoleColor.Gray
+ Console.WriteLine("Folder already exists: " + folderName)
Console.ResetColor()
Else
Throw ' Unknown Exception
@@ -478,7 +478,7 @@ Function MigrateDataSource(srcItem As CatalogItem) As CatalogItem
Console.WriteLine(warningMsg)
Console.ResetColor()
- LogErrorToFile("CATALOGITEM", "Warning", warningMsg)
+ LogErrorToFile("CATALOGITEM", "Warning: " + result.Path, warningMsg)
End If
@@ -567,7 +567,7 @@ Function MigrateCatalogItem(srcItem As CatalogItem) As CatalogItem
Console.WriteLine(warningMsg)
Console.ResetColor()
- LogErrorToFile("CATALOGITEM", "Warning", warningMsg)
+ LogErrorToFile("CATALOGITEM", "Warning: " + result.TypeName, warningMsg)
End If
End If
Next
@@ -742,7 +742,7 @@ Sub MigrateReportSubscriptions(snkReport As CatalogItem, srcReport As CatalogIte
Console.Write(description)
If Not dataRetrievalPlan Is Nothing And TypeOf dataRetrievalPlan.Item Is DataSourceReference Then
Dim item As DataSourceReference = dataRetrievalPlan.Item
- Dim ref As String = GetSnkPath(item.Reference)
+ Dim ref As String = GetSnkPathRef(item.Reference)
item.Reference = ref
End If
RsSnk.CreateDataDrivenSubscription(snkReport.Path, extensionSettings, dataRetrievalPlan, description, eventType, GetMatchData(matchData, RsSnk), parameters)
@@ -756,7 +756,7 @@ Sub MigrateReportSubscriptions(snkReport As CatalogItem, srcReport As CatalogIte
Console.WriteLine(warningMsg)
Console.ResetColor()
- LogErrorToFile("SUBSCRIPTIONS", "Warning", warningMsg)
+ LogErrorToFile("SUBSCRIPTIONS", "Warning: " + snkReport.Path, warningMsg)
End If
End If
@@ -795,9 +795,9 @@ Sub MigrateReportSubscriptions(snkReport As CatalogItem, srcReport As CatalogIte
Console.WriteLine(warningMsg)
Console.ResetColor()
- LogErrorToFile("SUBSCRIPTIONS", "Warning", warningMsg)
+ LogErrorToFile("SUBSCRIPTIONS", "Warning: " + snkReport.Path, warningMsg)
- End If
+ End If
Next
Catch ex As Exception
@@ -990,10 +990,19 @@ End Sub
'Helper function to link snk reference with relative paths
Function GetSnkPathRef(srcPath As String) As String
- Dim snkPath = srcPath
- If srcSiteUrl isNot Nothing
- snkPath = srcPath.Remove(0, srcSiteUrl.LastIndexOf("/"))
- End If
+ Dim snkPath = srcPath
+
+ If Not SrcIsNative Then
+ 'SharePoint integrated mode, will assume /sites server relative URL delimeter
+ If srcSiteUrl isNot Nothing
+ Dim delimeter = "/sites/"
+ snkPath = srcPath.Remove(0, srcSiteUrl.IndexOf(delimeter) + delimeter.Length-1)
+ End If
+ Else
+ 'Treat path reference like other scenarios if not intergated mode
+ snkPath = GetSnkPath(srcPath)
+ End If
+
Return snkPath
End Function
@@ -1189,12 +1198,18 @@ Sub LogErrorToFile(source As String, errItem as String, message As String)
Dim writer as StreamWriter
Try
+ Dim fileExists As Boolean = Not File.Exists(logFilePath) OrElse New FileInfo(logFilePath).Length = 0
+
' Create a StreamWriter object
writer = New StreamWriter(logFilePath, True)
+ If fileExists Then
+ writer.WriteLine("DateTime, Source, ErrorItem, ErrorMessage")
+ End If
+
' Format log message with timestamp
Dim timeStamp As String = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
- Dim formattedMessage as String = String.Format("{0}, {1}, {2}, ""{3}""", timeStamp, source, errItem, message.Replace(Environment.NewLine, ""))
+ Dim formattedMessage as String = String.Format("{0}, {1}, {2}, ""{3}""", timeStamp, source, errItem, message.Replace(Environment.NewLine, " "))
' Write the log entry to file
writer.WriteLine(formattedMessage)
diff --git a/samples/features/security/always-encrypted-with-secure-enclaves/sample-application/AlwaysEncryptedConsole/AlwaysEncryptedConsole.csproj b/samples/features/security/always-encrypted-with-secure-enclaves/sample-application/AlwaysEncryptedConsole/AlwaysEncryptedConsole.csproj
index cc585632..8bd770b7 100644
--- a/samples/features/security/always-encrypted-with-secure-enclaves/sample-application/AlwaysEncryptedConsole/AlwaysEncryptedConsole.csproj
+++ b/samples/features/security/always-encrypted-with-secure-enclaves/sample-application/AlwaysEncryptedConsole/AlwaysEncryptedConsole.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/samples/features/security/always-encrypted-with-secure-enclaves/source/ContosoHR/ContosoHR.csproj b/samples/features/security/always-encrypted-with-secure-enclaves/source/ContosoHR/ContosoHR.csproj
index a078da12..cd12b121 100644
--- a/samples/features/security/always-encrypted-with-secure-enclaves/source/ContosoHR/ContosoHR.csproj
+++ b/samples/features/security/always-encrypted-with-secure-enclaves/source/ContosoHR/ContosoHR.csproj
@@ -15,8 +15,8 @@
-
-
+
+
diff --git a/samples/features/security/ledger/source/ContosoHR/ContosoHR.csproj b/samples/features/security/ledger/source/ContosoHR/ContosoHR.csproj
index 99d038b7..99e6ed65 100644
--- a/samples/features/security/ledger/source/ContosoHR/ContosoHR.csproj
+++ b/samples/features/security/ledger/source/ContosoHR/ContosoHR.csproj
@@ -43,7 +43,7 @@
-
+
diff --git a/samples/manage/azure-arc-enabled-sql-server/modify-license-type/README.md b/samples/manage/azure-arc-enabled-sql-server/modify-license-type/README.md
index ba1674ba..e0282d40 100644
--- a/samples/manage/azure-arc-enabled-sql-server/modify-license-type/README.md
+++ b/samples/manage/azure-arc-enabled-sql-server/modify-license-type/README.md
@@ -30,7 +30,7 @@ The script accepts the following command line parameters:
|-SubId|subscription_id *or* a file_name|Optional: Subscription id or a .csv file with the list of subscriptions1. If not specified all subscriptions will be scanned|
|-ResourceGroup |resource_group_name|Optional: Limits the scope to a specific resource group|
|-MachineName |machine_name|Optional: Limits the scope to a specific machine|
-|-LicenceType | "Paid", "PAYG" or "LicenseOnly"| Optional: Sets the license type to the specified value |
+|-LicenseType | "Paid", "PAYG" or "LicenseOnly"| Optional: Sets the license type to the specified value |
|-EnableESU | "Yes", "No" | Optional. Enables the ESU policy the value is "Yes" or disables it if the value is "No". To enable, the license type must be "Paid" or "PAYG"|
|-Force| |Optional. Forces the change of the license type to the specified value on all installed extensions. If -Force is not specified, the -LicenseType value is set only if undefined. Ignored if -LicenseType is not specified|
diff --git a/samples/manage/polybase/external-table/README.md b/samples/manage/polybase/external-table/README.md
index 412fb4ae..c8c49f51 100644
--- a/samples/manage/polybase/external-table/README.md
+++ b/samples/manage/polybase/external-table/README.md
@@ -1,15 +1,15 @@

-# Handling Update Statistics Error on External Tables in SQL Server
+# Handling UPDATE STATISTICS error on SQL Server PolyBase external tables
-This sample describes an option to update statistics on SQL Server PolyBase external tables!
+This sample describes an option to update statistics on SQL Server PolyBase external tables.
## Background
In the process of configuring a maintenance plan for a SQL Server database with external tables and external data sources for PolyBase queries, an error occurred during the update statistics task.
-## Problem Encountered
+## Problem encountered
While attempting to update statistics on an external table, the following error message was encountered:
@@ -37,7 +37,7 @@ The object Update Statistics isn't supported on External Table
## About this sample
- **Applies to:** SQL Server 2017 (or higher)
-- **Key features:** Update statistics
+- **Key features:** UPDATE STATISTICS
- **Workload:** No workload related to this sample
- **Programming Language:** T-SQL
- **Authors:** [Sergio Govoni](https://www.linkedin.com/in/sgovoni/) | [Microsoft MVP Profile](https://mvp.microsoft.com/mvp/profile/c7b770c0-3c9a-e411-93f2-9cb65495d3c4) | [Blog](https://segovoni.medium.com/) | [GitHub](https://github.com/segovoni) | [Twitter](https://twitter.com/segovoni)
@@ -60,19 +60,19 @@ Upon investigation, it became apparent that SQL Server does not support the dire
## Resolution steps
-1. Understanding the Limitation:
+### Understanding the limitation
Referring to the documentation page, it explicitly states, "Updating statistics is not supported on external tables. To update statistics on an external table, drop and re-create the statistics."
-2. Available Solutions:
+### Available solutions
-Option 1: Ignore External Tables:
-This option is not feasible for maintenance plans managed by SQL Server Management Studio, necessitating third-party solutions.
+* Option 1: Ignore External Tables:
+ * This option is not feasible for maintenance plans managed by SQL Server Management Studio, necessitating third-party solutions.
-Option 2: Drop and Recreate Statistics:
-Employ a stored procedure, `sp_drop_create_stats_external_table`, to generate T-SQL statements for dropping and creating statistics on external tables. This procedure supports statistics on multiple columns.
+* Option 2: Drop and Recreate Statistics:
+ * Employ a stored procedure, `sp_drop_create_stats_external_table`, to generate T-SQL statements for dropping and creating statistics on external tables. This procedure supports statistics on multiple columns.
-3. Implementation Guide:
+### Implementation guide
- Execute `sp_drop_create_stats_external_table` to generate T-SQL statements
- Execute DROP STATISTICS statements before the maintenance statistics task
@@ -103,7 +103,11 @@ This code sample is provided for demonstration and educational purposes only. It
-## Related Links
+## Related links
-For more information, see these articles...
\ No newline at end of file
+For more information, see these articles:
+
+- [Data virtualization with PolyBase in SQL Server](https://learn.microsoft.com/sql/relational-databases/polybase/polybase-guide?WT.mc_id=DP-MVP-4029181)
+- [UPDATE STATISTICS (Transact-SQL)](https://learn.microsoft.com/sql/t-sql/statements/update-statistics-transact-sql?WT.mc_id=DP-MVP-4029181)
+- [External tables: Why create statistics?](https://learn.microsoft.com/answers/questions/978155/external-tables-why-create-statistics?WT.mc_id=DP-MVP-4029181)
diff --git a/samples/manage/sql-vm-io-analysis.ps1 b/samples/manage/sql-vm-io-analysis.ps1
new file mode 100644
index 00000000..9f019525
--- /dev/null
+++ b/samples/manage/sql-vm-io-analysis.ps1
@@ -0,0 +1,186 @@
+# Enter parameters
+$subscriptionId = Read-Host ""
+$resourceGroup = Read-Host ""
+$vmName = Read-Host ""
+
+# Set resource details
+$resourceType = "Microsoft.Compute/virtualMachines"
+$resourceId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/$resourceType/$vmName"
+
+# Get Azure access token
+$accessToken = az account get-access-token --query accessToken -o tsv
+
+# Invoke Azure Monitor Metrics API
+function Get-Metrics {
+ [CmdletBinding()]
+ param (
+ [string]$accessToken,
+ [string]$resourceId,
+ [string]$metricNames,
+ [string]$apiVersion = "2023-10-01"
+ )
+ try {
+ $startTime = (Get-Date).AddHours(-24).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
+ $endTime = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')
+ $timespan = "$startTime/$endTime"
+ Write-Verbose "Evaluating timespan: $timespan"
+ $uri = "https://management.azure.com$resourceId/providers/Microsoft.Insights/metrics?api-version=$apiVersion&metricnames=$metricNames&aggregation=maximum&interval=PT1M×pan=$timespan"
+ $headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json" }
+
+ $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
+ if ($response) {
+ Write-Verbose "API response successfully retrieved."
+ return $response
+ } else {
+ Write-Error "No response from API."
+ }
+ } catch {
+ Write-Error "Error retrieving metrics: $_"
+ }
+}
+
+# Check if data disk latency violates thresholds
+function Check-Latency {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory = $true)]
+ [Object]$metrics,
+
+ [Parameter()]
+ [int]$latencyThreshold = 500,
+
+ [Parameter()]
+ [int]$consecutiveCount = 5
+ )
+ $violationTimes = @()
+ foreach ($metric in $metrics.value) {
+ if ($metric.name.value -eq "Data Disk Latency") {
+ $count = 0
+ foreach ($dataPoint in $metric.timeseries[0].data) {
+ if ($dataPoint.maximum -gt $latencyThreshold) {
+ $count++
+ if ($count -ge $consecutiveCount) {
+ $violationTimes += $dataPoint.timeStamp
+ $count = 0 # Reset count after recording a violation
+ }
+ } else {
+ $count = 0 # Reset count if the sequence is broken
+ }
+ }
+ }
+ }
+ if ($violationTimes.Count -gt 0) {
+ Write-Verbose "Latency violations detected."
+ return @{ "Flag" = $true; "Times" = $violationTimes }
+ } else {
+ Write-Verbose "No latency violations detected."
+ return @{ "Flag" = $false }
+ }
+}
+
+# Check metrics other than latency to evaluate for throttling
+function Check-OtherMetricsThrottled {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory = $true)]
+ [Object]$metrics,
+
+ [Parameter()]
+ [int]$PercentageThreshold = 90,
+
+ [Parameter()]
+ [int]$consecutiveCount = 5
+ )
+ $violatedMetrics = @()
+ foreach ($metric in $metrics.value) {
+ $count = 0
+ foreach ($dataPoint in $metric.timeseries[0].data) {
+ if ($dataPoint.maximum -gt $PercentageThreshold) {
+ $count++
+ if ($count -ge $consecutiveCount) {
+ $violatedMetrics += @{ "Metric" = $metric.name.localizedValue; "Time" = $dataPoint.timeStamp; "Value" = $dataPoint.maximum }
+ break
+ }
+ } else {
+ $count = 0
+ }
+ }
+ }
+ if ($violatedMetrics.Count -gt 0) {
+ Write-Verbose "Other metrics violations detected."
+ } else {
+ Write-Verbose "No other metrics violations detected."
+ }
+ return $violatedMetrics
+}
+
+# Compare times for latency & other throttled metrics. Logs the volations with values & timestamps
+function CompareTimes {
+ [CmdletBinding()]
+ param (
+ [Parameter(Mandatory = $true)]
+ [Hashtable]$latencyResult,
+
+ [Parameter(Mandatory = $true)]
+ [Array]$otherMetrics
+ )
+ foreach ($metric in $otherMetrics) {
+ $otherDateTime = [DateTime]$metric["Time"]
+ $isWithinFiveMinutes = $false
+ $closestLatencyTime = $null
+ $closestTimeDifference = [int]::MaxValue
+
+ foreach ($latencyTime in $latencyResult.Times) {
+ $latencyDateTime = [DateTime]$latencyTime
+ $timeDifference = [Math]::Abs(($otherDateTime - $latencyDateTime).TotalMinutes)
+
+ if ($timeDifference -le 5) {
+ $isWithinFiveMinutes = $true
+ if ($timeDifference -lt $closestTimeDifference) {
+ $closestTimeDifference = $timeDifference
+ $closestLatencyTime = $latencyTime
+ }
+ }
+ }
+
+ if ($isWithinFiveMinutes) {
+ if ($otherDateTime -lt $closestLatencyTime) {
+ Write-Host "`n $($metric["Metric"]) limit was hit before latency spiked at $closestLatencyTime with value $($metric["Value"]). `n"
+ } else {
+ Write-Host "`n $($metric["Metric"]) hit its limit with value $($metric["Value"]) at $($metric["Time"])."
+ Write-Host "Latency spiked at $closestLatencyTime before $($metric["Metric"]) hit its limit `n"
+ }
+ } else {
+ Write-Host "`n Metric: $($metric["Metric"]) exceeded its threshold with a value of $($metric["Value"]) at $($metric["Time"]), but this was not within 5 minutes of any latency spikes."
+ }
+ }
+}
+
+# Prompt user for latency threshold
+$latencyThreshold = Read-Host "Enter Latency Threshold (default is 500)"
+if (-not [int]::TryParse($latencyThreshold, [ref]0)) {
+ $latencyThreshold = 500 # Use default if invalid input
+ Write-Host "No valid input provided. Using Default 500ms for disk latency threshold"
+}
+
+# Execute main logic
+$latencyMetrics = Get-Metrics -accessToken $accessToken -resourceId $resourceId -metricNames "Data Disk Latency"
+$latencyResult = Check-Latency -metrics $latencyMetrics -latencyThreshold $latencyThreshold
+
+if ($latencyResult.Flag) {
+
+ # If latency is flagged, check for other metrics. If there is no disk latency, machine is likely not throttled but only at high consumption
+ Write-Verbose "Checking the following metrics: Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage"
+
+ $DiskVMMetrics = Get-Metrics -accessToken $accessToken -resourceId $resourceId -metricNames "Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage"
+
+ $additionalMetrics = Check-OtherMetricsThrottled -metrics $DiskVMMetrics
+
+ if ($additionalMetrics.Count -gt 0) {
+ CompareTimes $latencyResult $additionalMetrics
+ } else {
+ Write-Host "No metrics violations detected besides latency."
+ }
+} else {
+ Write-Host "No latency issues detected."
+}