問題描述
在Azure上建立虛擬機器(VM)後,在門戶上可以檢視監控指標(Metrics),如CPU Usage,Memory,Disk I/O等。那如何通過Java 程式碼獲取到這些指標呢?
關於VM 的記憶體使用率,虛擬機器本身並沒有提供這個指標,需要開啟診斷後去Azure Storage表中獲取,欄位為\Memory\% Committed Bytes In Use,是開啟了診斷日誌儲存到WADMetrics 表中
解決辦法
方式一:使用REST API
Azure中門戶上看見的內容都是通過REST API來獲取值,基於此原理,可以通過在門戶中Metrics頁面中,點看CPU的指標資料後,通過F12(開發者工具),檢視具體使用的是什麼API, 並參考同樣的方式在Java 程式碼中呼叫該類介面來完成。
通常情況,是可以在Azure Monitor官網中(https://docs.microsoft.com/zh-cn/rest/api/monitor/)找到需要的REST API介面。如:
Metrics - List
列出資源的指標值。
GET https://management.azure.com/{resourceUri}/providers/microsoft.insights/metrics?api-version=2018-01-01
GET https://management.azure.com/{resourceUri}/providers/microsoft.insights/metrics?timespan={timespan}&interval={interval}&metricnames={metricnames}&aggregation={aggregation}&top={top}&orderby={orderby}&$filter={$filter}&resultType={resultType}&api-version=2018-01-01&metricnamespace={metricnamespace}
上文截圖中呼叫通過API獲取到的Metrics的URL引數值為:"/subscriptions/<subscriptionid>/resourceGroups/<resource group>/providers/Microsoft.Compute/virtualMachines/<vm name>/providers/microsoft.Insights/metrics?
timespan=2020-11-24T22:03:01.141Z/2020-11-27T04:55:40.325Z
&interval=PT30M
&metricnames=Percentage CPU
&aggregation=average
&metricNamespace=microsoft.compute%2Fvirtualmachines
&autoadjusttimegrain=true
&validatedimensions=false
&api-version=2019-07-01"引數的詳細說明:
Name In Required Type Description resourceUripath True
- string
資源的識別符號。
api-versionquery True
- string
客戶端 Api 版本。
$filterquery
- string
$filter用於減少返回的指標資料集。
示例:
指標包含後設資料 A、B 和 C。
- 返回所有時間序列 C,其中 A = a1 和 B = b1 或 b2
$filter_eq 'a1' 和 B eq 'b1' 或 B eq 'b2' 和 C eq '#'
- 無效變體:
$filter=eq 'a1'和 B eq 'b1' 和 C eq '*' 或 B = 'b2'
這是無效的,因為邏輯或運算子不能分隔兩個不同的後設資料名稱。
- 返回所有時間序列,其中 A = a1,B = b1 和 C = c1:
$filter=eq 'a1'和 B eq 'b1' 和 C eq 'c1'
- 返回所有時間序列,其中 A = a1
$filter_aq 'a1' 和 B eq '和 C eq''. aggregationquery
- string
要檢索的聚合型別(逗號分隔)的列表。
intervalquery duration
- string
查詢的間隔(即時粒)。
metricnamesquery
- string
要檢索的指標(逗號分隔)的名稱。
metricnamespacequery
- string
用於查詢指標定義的指標名稱空間。
orderbyquery
- string
用於對結果進行排序的聚合和排序方向。 只能指定一個訂單。 示例:總和 asc。
resultTypequery 減少收集的資料集。 允許的語法取決於操作。 有關詳細資訊,請參閱操作說明。
timespanquery
- string
查詢的時間跨度。 它是具有以下格式"startDateTime_ISO/endDateTime_ISO"的字串。
topquery int32
- integer
要檢索的最大記錄數。 僅在指定$filter時有效。 預設值為 10。
全文內容:https://docs.microsoft.com/zh-cn/rest/api/monitor/metrics/list
方式二:使用Azure VM診斷日誌 ——> Storage Table——> Java Code (Storage SDK)
開啟虛擬機器的診斷日誌,讓Azure VM把監控資料傳送到Storage Table中,通過Storage SDK直接獲取Table中的資料。
開啟診斷日誌
獲取Storage Table中資料的Java程式碼
若要對錶查詢分割槽中的實體,可以使用
TableQuery
。 呼叫TableQuery.from
可建立針對特定表的查詢,該查詢將返回指定的結果型別。 以下程式碼指定了一個篩選器,用於篩選其中的分割槽鍵是“Smith”的實體。TableQuery.generateFilterCondition
是用於建立查詢篩選器的幫助程式方法。 對TableQuery.from
方法返回的引用呼叫where
,以對查詢應用篩選器。 當通過呼叫CloudTable
物件上的execute
來執行查詢時,該查詢將返回指定了CustomerEntity
結果型別的Iterator
。 然後,可以利用在“ForEach”迴圈中返回的Iterator
來使用結果。 此程式碼會將查詢結果中每個實體的欄位列印到控制檯。try { // Define constants for filters. final String PARTITION_KEY = "PartitionKey"; final String ROW_KEY = "RowKey"; final String TIMESTAMP = "Timestamp"; // Retrieve storage account from connection-string. CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectionString); // Create the table client. CloudTableClient tableClient = storageAccount.createCloudTableClient(); // Create a cloud table object for the table. CloudTable cloudTable = tableClient.getTableReference("people"); // Create a filter condition where the partition key is "Smith". String partitionFilter = TableQuery.generateFilterCondition( PARTITION_KEY, QueryComparisons.EQUAL, "Smith"); // Specify a partition query, using "Smith" as the partition key filter. TableQuery<CustomerEntity> partitionQuery = TableQuery.from(CustomerEntity.class) .where(partitionFilter); // Loop through the results, displaying information about the entity. for (CustomerEntity entity : cloudTable.execute(partitionQuery)) { System.out.println(entity.getPartitionKey() + " " + entity.getRowKey() + "\t" + entity.getEmail() + "\t" + entity.getPhoneNumber()); } } catch (Exception e) { // Output the stack trace. e.printStackTrace(); }
參考資料
REST API 引用 Azure Monitor: https://docs.microsoft.com/zh-cn/rest/api/monitor/
如何通過 Java 使用 Azure 表儲存或 Azure Cosmos DB 表 API: https://docs.azure.cn/zh-cn/cosmos-db/table-storage-how-to-use-java?toc=https%3A%2F%2Fdocs.azure.cn%2Fzh-cn%2Fstorage%2Ftables%2Ftoc.json&bc=https%3A%2F%2Fdocs.azure.cn%2Fzh-cn%2Fbread%2Ftoc.json
附錄一:檢視Azure REST API的方法:
附錄二:使用Java SDK直接獲取VM物件和VM物件中Mertics的程式碼:https://github.com/Azure/azure-libraries-for-java/blob/master/azure-mgmt-monitor/src/test/java/com/microsoft/azure/management/monitor/MonitorActivityAndMetricsTests.java
/** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for * license information. */ package com.microsoft.azure.management.monitor; import com.microsoft.azure.PagedList; import com.microsoft.azure.management.compute.VirtualMachine; import com.microsoft.azure.management.resources.fluentcore.utils.SdkContext; import org.joda.time.DateTime; import org.junit.Assert; import org.junit.Test; import java.util.List; public class MonitorActivityAndMetricsTests extends MonitorManagementTest { @Test public void canListEventsAndMetrics() throws Exception { DateTime recordDateTime = SdkContext.dateTimeNow().minusDays(40); VirtualMachine vm = computeManager.virtualMachines().list().get(0); // Metric Definition List<MetricDefinition> mt = monitorManager.metricDefinitions().listByResource(vm.id()); Assert.assertNotNull(mt); MetricDefinition mDef = mt.get(0); Assert.assertNotNull(mDef.metricAvailabilities()); Assert.assertNotNull(mDef.namespace()); Assert.assertNotNull(mDef.supportedAggregationTypes()); // Metric MetricCollection metrics = mDef.defineQuery() .startingFrom(recordDateTime.minusDays(30)) .endsBefore(recordDateTime) .withResultType(ResultType.DATA) .execute(); Assert.assertNotNull(metrics); Assert.assertNotNull(metrics.namespace()); Assert.assertNotNull(metrics.resourceRegion()); Assert.assertEquals("Microsoft.Compute/virtualMachines", metrics.namespace());