빠른 시작: 클라이언트 라이브러리 또는 REST API를 사용하여 솔루션 사용자 지정
Important
2023년 9월 20일부터 새로운 Metrics Advisor 리소스를 만들 수 없습니다. Metrics Advisor 서비스는 2026년 10월 1일에 사용 중지됩니다.
Metrics Advisor REST API 또는 클라이언트 라이브러리를 시작합니다. 이러한 단계에 따라 패키지를 설치하고 기본 작업을 위한 예제 코드를 사용해 봅니다.
Metrics Advisor를 사용하여 다음을 수행합니다.
- 데이터 원본에서 데이터 피드 추가
- 수집 상태 확인
- 탐지 및 경고 구성
- 변칙 검색 결과 쿼리
- 변칙 진단
참조 설명서 | 라이브러리 소스 코드 | 패키지(NuGet) | 샘플
Important
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 이 문서에 설명된 인증 흐름 중 일부는 애플리케이션에 대해 매우 높은 수준의 신뢰를 요구하며 보다 안전한 다른 흐름에는 없는 위험을 수반합니다. 이 흐름은 관리 ID와 같은 보다 안전한 다른 흐름을 실행할 수 없는 경우에만 사용되어야 합니다.
필수 조건
- Azure 구독 - 체험 구독 만들기
- 최신 버전의 .NET Core
- Azure 구독이 있으면 Azure Portal에서 Metrics Advisor 리소스 만들기를 수행하여 Metrics Advisor 인스턴스를 배포합니다.
- 시계열 데이터가 포함된 사용자 고유의 SQL 데이터베이스.
팁
- GitHub에서 .NET Metrics Advisor 샘플을 찾을 수 있습니다.
- Metrics Advisor 리소스에서 사용할 서비스 인스턴스를 배포하는 데 10~30분 정도 걸릴 수 있습니다. 성공적으로 배포되면 리소스로 이동을 선택합니다. 배포 후에는 웹 포털과 REST API 모두를 사용하여 Metrics Advisor 인스턴스 사용을 시작할 수 있습니다.
- 리소스의 개요 섹션에서 Azure Portal의 REST API에 대한 URL을 찾을 수 있습니다. 다음과 같이 표시됩니다.
https://<instance-name>.cognitiveservices.azure.com/
설정
클라이언트 라이브러리 설치
새 프로젝트가 만들어지면 솔루션 탐색기에서 마우스 오른쪽 단추로 프로젝트 솔루션을 클릭하고, NuGet 패키지 관리를 선택하여 클라이언트 라이브러리를 설치합니다. 열리는 패키지 관리자에서 찾아보기를 선택하고, 시험판 포함을 선택하고, Azure.AI.MetricsAdvisor
를 검색합니다. 1.0.0
버전, 설치를 차례로 선택합니다.
콘솔 창(예: cmd, PowerShell 또는 Bash)에서 dotnet new
명령을 사용하여 metrics-advisor-quickstart
라는 새 콘솔 앱을 만듭니다. 이 명령은 program.cs라는 단일 소스 파일을 사용하여 간단한 "Hello World" C# 프로젝트를 만듭니다.
dotnet new console -n metrics-advisor-quickstart
새로 만든 앱 폴더로 디렉터리를 변경합니다. 다음을 통해 애플리케이션을 빌드할 수 있습니다.
dotnet build
빌드 출력에 경고나 오류가 포함되지 않아야 합니다.
...
Build succeeded.
0 Warning(s)
0 Error(s)
...
Visual Studio 이외의 IDE를 사용하는 경우 다음 명령을 사용하여 .NET용 Metrics Advisor 클라이언트 라이브러리를 설치할 수 있습니다.
dotnet add package Azure.AI.MetricsAdvisor --version 1.1.0
환경 변수
Anomaly Detector 서비스를 성공적으로 호출하려면 다음 값이 필요합니다.
변수 이름 | 값 |
---|---|
METRICS_ADVISOR_ENDPOINT |
이 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. 엔드포인트 예: https://YOUR_RESOURCE_NAME.cognitiveservices.azure.com/ |
METRICS_ADVISOR_KEY |
키 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
METRICS_ADVISOR_API_KEY |
키 값은 Metrics Advisor 포털에서 리소스를 검사할 때 설정>API 키에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
SQL_CONNECTION_STRING |
이 빠른 시작에서는 고유한 SQL Database + 연결 문자열이 있어야 합니다. 연결 문자열 예제는 다음 예제와 유사합니다. Data Source=<Server>;Initial Catalog=<db-name>;User ID=<user-name>;Password=<password> SQL 연결 문자열을 생성하는 방법에 대한 자세한 내용은 SQL 설명서를 참조하세요. |
SQL_QUERY |
데이터 세트와 관련된 고유 쿼리입니다. |
환경 변수 만들기
키 및 엔드포인트에 대한 영구 환경 변수를 만들고 할당합니다.
Important
API 키를 사용하는 경우 Azure Key Vault와 같은 다른 위치에 안전하게 저장합니다. API 키를 코드에 직접 포함하지 말고, 공개적으로 게시하지 마세요.
AI 서비스 보안에 대한 자세한 내용은 Azure AI 서비스에 대한 요청 인증을 참조하세요.
setx METRICS_ADVISOR_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"
setx METRICS_ADVISOR_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx METRICS_ADVISOR_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx SQL_CONNECTION_STRING "REPLACE_WITH_YOUR_UNIQUE_SQL_CONNECTION_STRING"
setx SQL_QUERY "REPLACE_WITH_YOUR_UNIQUE_SQL_QUERY_BASED_ON_THE_UNDERLYING_STRUCTURE_OF_YOUR_DATA"
애플리케이션 만들기
program.cs 파일을 편집하고 를 다음으로 바꿉니다.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Threading.Tasks;
using Azure.AI.MetricsAdvisor.Administration;
using Azure.AI.MetricsAdvisor.Models;
using Azure.AI.MetricsAdvisor.Tests;
using Azure.Core.TestFramework;
using NUnit.Framework;
using static System.Environment;
namespace Azure.AI.MetricsAdvisor.Samples
{
[LiveOnly]
public partial class MetricsAdvisorSamples : MetricsAdvisorTestEnvironment
{
[Test]
public async Task CreateAndDeleteDataFeedAsync()
{
string endpoint = GetEnvironmentVariable("METRICS_ADVISOR_ENDPOINT");
string subscriptionKey = GetEnvironmentVariable("METRICS_ADVISOR_KEY");
string apiKey = GetEnvironmentVariable("METRICS_ADVISOR_API_KEY");
var credential = new MetricsAdvisorKeyCredential(subscriptionKey, apiKey);
var adminClient = new MetricsAdvisorAdministrationClient(new Uri(endpoint), credential);
#region Snippet:CreateDataFeedAsync
#if SNIPPET
string sqlServerConnectionString = GetEnvironmentVariable("SQL_CONNECTION_STRING");
string sqlServerQuery = GetEnvironmentVariable("SQL_QUERY");
#else
string sqlServerConnectionString = SqlServerConnectionString;
string sqlServerQuery = SqlServerQuery;
#endif
var dataFeed = new DataFeed();
#if SNIPPET
dataFeed.Name = "<dataFeedName>";
#else
dataFeed.Name = GetUniqueName();
#endif
dataFeed.DataSource = new SqlServerDataFeedSource(sqlServerConnectionString, sqlServerQuery);
dataFeed.Granularity = new DataFeedGranularity(DataFeedGranularityType.Daily);
dataFeed.Schema = new DataFeedSchema();
dataFeed.Schema.MetricColumns.Add(new DataFeedMetric("cost"));
dataFeed.Schema.MetricColumns.Add(new DataFeedMetric("revenue"));
dataFeed.Schema.DimensionColumns.Add(new DataFeedDimension("category"));
dataFeed.Schema.DimensionColumns.Add(new DataFeedDimension("region"));
dataFeed.IngestionSettings = new DataFeedIngestionSettings(DateTimeOffset.Parse("2020-01-01T00:00:00Z"));
Response<DataFeed> response = await adminClient.CreateDataFeedAsync(dataFeed);
DataFeed createdDataFeed = response.Value;
Console.WriteLine($"Data feed ID: {createdDataFeed.Id}");
Console.WriteLine($"Data feed status: {createdDataFeed.Status.Value}");
Console.WriteLine($"Data feed created time: {createdDataFeed.CreatedOn.Value}");
Console.WriteLine($"Data feed administrators:");
foreach (string admin in createdDataFeed.Administrators)
{
Console.WriteLine($" - {admin}");
}
Console.WriteLine($"Metric IDs:");
foreach (DataFeedMetric metric in createdDataFeed.Schema.MetricColumns)
{
Console.WriteLine($" - {metric.Name}: {metric.Id}");
}
Console.WriteLine($"Dimensions:");
foreach (DataFeedDimension dimension in createdDataFeed.Schema.DimensionColumns)
{
Console.WriteLine($" - {dimension.Name}");
}
#endregion
// Delete the created data feed to clean up the Metrics Advisor resource. Do not perform this
// step if you intend to keep using the data feed.
await adminClient.DeleteDataFeedAsync(createdDataFeed.Id);
}
[Test]
public async Task GetDataFeedAsync()
{
string endpoint = GetEnvironmentVariable("METRICS_ADVISOR_ENDPOINT");
string subscriptionKey = GetEnvironmentVariable("METRICS_ADVISOR_KEY");
string apiKey = GetEnvironmentVariable("METRICS_ADVISOR_API_KEY");
var credential = new MetricsAdvisorKeyCredential(subscriptionKey, apiKey);
var adminClient = new MetricsAdvisorAdministrationClient(new Uri(endpoint), credential);
string dataFeedId = DataFeedId;
Response<DataFeed> response = await adminClient.GetDataFeedAsync(dataFeedId);
DataFeed dataFeed = response.Value;
Console.WriteLine($"Data feed status: {dataFeed.Status.Value}");
Console.WriteLine($"Data feed created time: {dataFeed.CreatedOn.Value}");
Console.WriteLine($"Data feed administrators:");
foreach (string admin in dataFeed.Administrators)
{
Console.WriteLine($" - {admin}");
}
Console.WriteLine($"Metric IDs:");
foreach (DataFeedMetric metric in dataFeed.Schema.MetricColumns)
{
Console.WriteLine($" - {metric.Name}: {metric.Id}");
}
Console.WriteLine($"Dimensions:");
foreach (DataFeedDimension dimension in dataFeed.Schema.DimensionColumns)
{
Console.WriteLine($" - {dimension.Name}");
}
}
[Test]
public async Task UpdateDataFeedAsync()
{
string endpoint = GetEnvironmentVariable("METRICS_ADVISOR_ENDPOINT");
string subscriptionKey = GetEnvironmentVariable("METRICS_ADVISOR_KEY");
string apiKey = GetEnvironmentVariable("METRICS_ADVISOR_API_KEY");
var credential = new MetricsAdvisorKeyCredential(subscriptionKey, apiKey);
var adminClient = new MetricsAdvisorAdministrationClient(new Uri(endpoint), credential);
string dataFeedId = DataFeedId;
Response<DataFeed> response = await adminClient.GetDataFeedAsync(dataFeedId);
DataFeed dataFeed = response.Value;
string originalDescription = dataFeed.Description;
dataFeed.Description = "This description was generated by a sample.";
// Some properties, such as IngestionStartOffset, can be reset to their default value
// when set to null during an Update operation. Check the API documentation to verify
// when a property supports this feature.
TimeSpan? originalStartOffset = dataFeed.IngestionSettings.IngestionStartOffset;
dataFeed.IngestionSettings.IngestionStartOffset = null;
response = await adminClient.UpdateDataFeedAsync(dataFeed);
DataFeed updatedDataFeed = response.Value;
Console.WriteLine($"Updated description: {updatedDataFeed.Description}");
Console.WriteLine($"Updated ingestion start offset: {updatedDataFeed.IngestionSettings.IngestionStartOffset}");
// Undo the changes to leave the data feed unaltered. Skip this step if you intend to keep
// the changes.
dataFeed.Description = originalDescription;
dataFeed.IngestionSettings.IngestionStartOffset = originalStartOffset;
await adminClient.UpdateDataFeedAsync(dataFeed);
}
[Test]
public async Task GetDataFeedsAsync()
{
string endpoint = GetEnvironmentVariable("METRICS_ADVISOR_ENDPOINT");
string subscriptionKey = GetEnvironmentVariable("METRICS_ADVISOR_KEY");
string apiKey = GetEnvironmentVariable("METRICS_ADVISOR_API_KEY");
var credential = new MetricsAdvisorKeyCredential(subscriptionKey, apiKey);
var adminClient = new MetricsAdvisorAdministrationClient(new Uri(endpoint), credential);
var filter = new DataFeedFilter()
{
Status = DataFeedStatus.Active,
GranularityType = DataFeedGranularityType.Daily
};
var options = new GetDataFeedsOptions()
{
Filter = filter,
MaxPageSize = 5
};
int dataFeedCount = 0;
await foreach (DataFeed dataFeed in adminClient.GetDataFeedsAsync(options))
{
Console.WriteLine($"Data feed ID: {dataFeed.Id}");
Console.WriteLine($"Name: {dataFeed.Name}");
Console.WriteLine($"Description: {dataFeed.Description}");
Console.WriteLine();
// Print at most 5 data feeds.
if (++dataFeedCount >= 5)
{
break;
}
}
}
}
}
애플리케이션 실행
dotnet run
명령을 사용하여 애플리케이션 디렉터리에서 애플리케이션을 실행합니다.
dotnet run
참조 설명서 | 라이브러리 소스 코드 | 아티팩트(Maven) | 샘플
Important
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 이 문서에 설명된 인증 흐름 중 일부는 애플리케이션에 대해 매우 높은 수준의 신뢰를 요구하며 보다 안전한 다른 흐름에는 없는 위험을 수반합니다. 이 흐름은 관리 ID와 같은 보다 안전한 다른 흐름을 실행할 수 없는 경우에만 사용되어야 합니다.
필수 조건
- Azure 구독 - 체험 구독 만들기
- JDK(Java Development Kit)의 현재 버전
- Gradle 빌드 도구 또는 다른 종속성 관리자
- Azure 구독이 있으면 Azure Portal에서 Metrics Advisor 리소스 만들기를 수행하여 Metrics Advisor 인스턴스를 배포합니다.
- 시계열 데이터가 포함된 사용자 고유의 SQL 데이터베이스.
팁
- GitHub에서 Java Metrics Advisor 샘플을 찾을 수 있습니다.
- Metrics Advisor 리소스에서 사용할 서비스 인스턴스를 배포하는 데 10~30분 정도 걸릴 수 있습니다. 성공적으로 배포되면 리소스로 이동을 선택합니다. 배포 후에는 웹 포털과 REST API 모두를 사용하여 Metrics Advisor 인스턴스 사용을 시작할 수 있습니다.
- 리소스의 개요 섹션에서 Azure Portal의 REST API에 대한 URL을 찾을 수 있습니다. 다음과 같이 표시됩니다.
https://<instance-name>.cognitiveservices.azure.com/
설정
새 Gradle 프로젝트 만들기
이 빠른 시작에서는 Gradle 종속성 관리자를 사용합니다. Maven Central Repository에서 추가 클라이언트 라이브러리 정보를 찾을 수 있습니다.
콘솔 창(예: cmd, PowerShell 또는 Bash)에서 앱에 대한 새 디렉터리를 만들고 이 디렉터리로 이동합니다.
mkdir myapp && cd myapp
작업 디렉터리에서 gradle init
명령을 실행합니다. 이 명령은 build.gradle.kts를 포함하여 런타임에 애플리케이션을 만들고 구성하는 데 사용되는 Gradle용 필수 빌드 파일을 만듭니다.
gradle init --type basic
DSL을 선택하라는 메시지가 표시되면 Kotlin을 선택합니다.
클라이언트 라이브러리 설치
build.gradle.kts를 찾고, 원하는 IDE 또는 텍스트 편집기에서 엽니다. 그런 다음, 이 빌드 구성에서 복사합니다. 프로젝트 종속성을 포함해야 합니다.
dependencies {
compile("com.azure:azure-ai-metricsadvisor:1.1.8")
}
Java 파일 만들기
샘플 앱에 대한 폴더를 만듭니다. 작업 디렉터리에서 다음 명령을 실행합니다.
mkdir -p src/main/java
새 폴더로 이동하여 MetricsAdvisorQuickstarts.java라는 파일을 만듭니다. 원하는 편집기 또는 IDE에서 이 파일을 열고, 다음 import
문을 추가합니다.
팁
한 번에 전체 빠른 시작 코드 파일을 보시겠습니까? GitHub에서 찾을 수 있으며 이 빠른 시작의 코드 예제를 포함합니다.
환경 변수
Anomaly Detector 서비스를 성공적으로 호출하려면 다음 값이 필요합니다.
변수 이름 | 값 |
---|---|
METRICS_ADVISOR_ENDPOINT |
이 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. 엔드포인트 예: https://YOUR_RESOURCE_NAME.cognitiveservices.azure.com/ |
METRICS_ADVISOR_KEY |
키 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
METRICS_ADVISOR_API_KEY |
키 값은 Metrics Advisor 포털에서 리소스를 검사할 때 설정>API 키에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
SQL_CONNECTION_STRING |
이 빠른 시작에서는 고유한 SQL Database + 연결 문자열이 있어야 합니다. 연결 문자열 예제는 다음 예제와 유사합니다. Data Source=<Server>;Initial Catalog=<db-name>;User ID=<user-name>;Password=<password> SQL 연결 문자열을 생성하는 방법에 대한 자세한 내용은 SQL 설명서를 참조하세요. |
SQL_QUERY |
데이터 세트와 관련된 고유 쿼리입니다. |
환경 변수 만들기
키 및 엔드포인트에 대한 영구 환경 변수를 만들고 할당합니다.
Important
API 키를 사용하는 경우 Azure Key Vault와 같은 다른 위치에 안전하게 저장합니다. API 키를 코드에 직접 포함하지 말고, 공개적으로 게시하지 마세요.
AI 서비스 보안에 대한 자세한 내용은 Azure AI 서비스에 대한 요청 인증을 참조하세요.
setx METRICS_ADVISOR_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"
setx METRICS_ADVISOR_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx METRICS_ADVISOR_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx SQL_CONNECTION_STRING "REPLACE_WITH_YOUR_UNIQUE_SQL_CONNECTION_STRING"
setx SQL_QUERY "REPLACE_WITH_YOUR_UNIQUE_SQL_QUERY_BASED_ON_THE_UNDERLYING_STRUCTURE_OF_YOUR_DATA"
애플리케이션 만들기
.java 파일의 내용을 다음으로 바꿉니다.
package com.azure.ai.metricsadvisor.administration;
import com.azure.ai.metricsadvisor.administration.models.AzureAppInsightsDataFeedSource;
import com.azure.ai.metricsadvisor.administration.models.DataFeed;
import com.azure.ai.metricsadvisor.administration.models.DataFeedDimension;
import com.azure.ai.metricsadvisor.administration.models.DataFeedGranularity;
import com.azure.ai.metricsadvisor.administration.models.DataFeedGranularityType;
import com.azure.ai.metricsadvisor.administration.models.DataFeedIngestionSettings;
import com.azure.ai.metricsadvisor.administration.models.DataFeedMetric;
import com.azure.ai.metricsadvisor.administration.models.DataFeedOptions;
import com.azure.ai.metricsadvisor.administration.models.DataFeedSchema;
import com.azure.ai.metricsadvisor.administration.models.DataFeedSourceType;
import com.azure.ai.metricsadvisor.models.MetricsAdvisorKeyCredential;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.Collections;
/**
* Sample demonstrates how to create, get, update, delete and list datafeed.
*/
public class DatafeedSample {
private static String subscription_key = System.getenv("METRICS_ADVISOR_KEY");
private static String api_key = System.getenv("METRICS_ADVISOR_API_KEY");
private static String endpoint = System.getenv("METRICS_ADVISOR_ENDPOINT");
private static String connection_string = System.getenv("SQL_CONNECTION_STRING");
private static String sql_query = System.getenv("SQL_QUERY");
public static void main(String[] args) {
final MetricsAdvisorAdministrationClient advisorAdministrationClient =
new MetricsAdvisorAdministrationClientBuilder()
.endpoint("https://{endpoint}.cognitiveservices.azure.com/")
.credential(new MetricsAdvisorKeyCredential("subscription_key", "api_key"))
.buildClient();
// Create Data feed
DataFeed dataFeed = new DataFeed()
.setName("dataFeedName")
.setSource(new MySqlDataFeedSource(connection_string, sql_query))
.setGranularity(new DataFeedGranularity().setGranularityType(DataFeedGranularityType.DAILY))
.setSchema(new DataFeedSchema(
Arrays.asList(
new DataFeedMetric("cost"),
new DataFeedMetric("revenue")
)).setDimensions(
Arrays.asList(
new DataFeedDimension("city"),
new DataFeedDimension("category")
))
)
.setIngestionSettings(new DataFeedIngestionSettings(OffsetDateTime.parse("2020-01-01T00:00:00Z")))
.setOptions(new DataFeedOptions()
.setDescription("data feed description")
.setRollupSettings(new DataFeedRollupSettings()
.setRollupType(DataFeedRollupType.AUTO_ROLLUP)));
final DataFeed createdSqlDataFeed = metricsAdvisorAdminClient.createDataFeed(dataFeed);
System.out.printf("Data feed Id : %s%n", createdSqlDataFeed.getId());
System.out.printf("Data feed name : %s%n", createdSqlDataFeed.getName());
System.out.printf("Is the query user is one of data feed administrator : %s%n", createdSqlDataFeed.isAdmin());
System.out.printf("Data feed created time : %s%n", createdSqlDataFeed.getCreatedTime());
System.out.printf("Data feed granularity type : %s%n",
createdSqlDataFeed.getGranularity().getGranularityType());
System.out.printf("Data feed granularity value : %d%n",
createdSqlDataFeed.getGranularity().getCustomGranularityValue());
System.out.println("Data feed related metric Ids:");
dataFeed.getMetricIds().forEach((metricId, metricName)
-> System.out.printf("Metric Id : %s, Metric Name: %s%n", metricId, metricName));
System.out.printf("Data feed source type: %s%n", createdSqlDataFeed.getSourceType());
if (SQL_SERVER_DB == createdSqlDataFeed.getSourceType()) {
System.out.printf("Data feed sql server query: %s%n",
((SqlServerDataFeedSource) createdSqlDataFeed.getSource()).getQuery());
}
// Update the data feed.
System.out.printf("Updating data feed: %s%n", dataFeed.getId());
dataFeed = advisorAdministrationClient.updateDataFeed(dataFeed.setOptions(new DataFeedOptions()
.setAdmins(Collections.singletonList("admin1@admin.com"))
));
System.out.printf("Updated data feed admin list: %s%n",
String.join(",", dataFeed.getOptions().getAdmins()));
// Delete the data feed.
System.out.printf("Deleting data feed: %s%n", dataFeed.getId());
advisorAdministrationClient.deleteDataFeed(dataFeed.getId());
System.out.printf("Deleted data feed%n");
// List data feeds.
System.out.printf("Listing data feeds%n");
advisorAdministrationClient.listDataFeeds().forEach(dataFeedItem -> {
System.out.printf("Data feed Id : %s%n", dataFeedItem.getId());
System.out.printf("Data feed name : %s%n", dataFeedItem.getName());
System.out.printf("Is the query user is one of data feed administrator : %s%n", dataFeedItem.isAdmin());
System.out.printf("Data feed created time : %s%n", dataFeedItem.getCreatedTime());
System.out.printf("Data feed granularity type : %s%n", dataFeedItem.getGranularity().getGranularityType());
System.out.printf("Data feed granularity value : %d%n",
dataFeedItem.getGranularity().getCustomGranularityValue());
System.out.println("Data feed related metric Id's:");
dataFeedItem.getMetricIds().forEach((metricId, metricName)
-> System.out.printf("Metric Id : %s, Metric Name: %s%n", metricId, metricName));
System.out.printf("Data feed source type: %s%n", dataFeedItem.getSourceType());
});
}
}
다음을 사용하여 앱을 빌드할 수 있습니다.
gradle build
애플리케이션 실행
run
목표를 사용하여 애플리케이션을 실행합니다.
gradle run
참조 설명서 | 라이브러리 소스 코드 | 패키지(npm) | 샘플
Important
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 이 문서에 설명된 인증 흐름 중 일부는 애플리케이션에 대해 매우 높은 수준의 신뢰를 요구하며 보다 안전한 다른 흐름에는 없는 위험을 수반합니다. 이 흐름은 관리 ID와 같은 보다 안전한 다른 흐름을 실행할 수 없는 경우에만 사용되어야 합니다.
필수 조건
- Azure 구독 - 체험 구독 만들기
- 현재 버전의 Node.js
- Azure 구독이 있으면 Azure Portal에서 Metrics Advisor 리소스 만들기를 수행하여 Metrics Advisor 인스턴스를 배포합니다.
- 시계열 데이터가 포함된 사용자 고유의 SQL 데이터베이스.
팁
- GitHub에서 JavaScript Metrics Advisor 샘플을 찾을 수 있습니다.
- Metrics Advisor 리소스에서 사용할 서비스 인스턴스를 배포하는 데 10~30분 정도 걸릴 수 있습니다. 성공적으로 배포되면 리소스로 이동을 선택합니다. 배포 후에는 웹 포털과 REST API 모두를 사용하여 Metrics Advisor 인스턴스 사용을 시작할 수 있습니다.
- 리소스의 개요 섹션에서 Azure Portal의 REST API에 대한 URL을 찾을 수 있습니다. 다음과 같이 표시됩니다.
https://<instance-name>.cognitiveservices.azure.com/
설정
새 Node.js 애플리케이션 만들기
콘솔 창(예: cmd, PowerShell 또는 Bash)에서 앱에 대한 새 디렉터리를 만들고 이 디렉터리로 이동합니다.
mkdir myapp && cd myapp
package.json
파일을 사용하여 노드 애플리케이션을 만들려면 npm init
명령을 실행합니다.
npm init
클라이언트 라이브러리 설치
@azure/ai-metrics-advisor
npm 패키지를 설치합니다.
npm install @azure/ai-metrics-advisor
종속성이 있는 앱의 package.json
파일이 업데이트됩니다.
환경 변수
Anomaly Detector 서비스를 성공적으로 호출하려면 다음 값이 필요합니다.
변수 이름 | 값 |
---|---|
METRICS_ADVISOR_ENDPOINT |
이 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. 엔드포인트 예: https://YOUR_RESOURCE_NAME.cognitiveservices.azure.com/ |
METRICS_ADVISOR_KEY |
키 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
METRICS_ADVISOR_API_KEY |
키 값은 Metrics Advisor 포털에서 리소스를 검사할 때 설정>API 키에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
SQL_CONNECTION_STRING |
이 빠른 시작에서는 고유한 SQL Database + 연결 문자열이 있어야 합니다. 연결 문자열 예제는 다음 예제와 유사합니다. Data Source=<Server>;Initial Catalog=<db-name>;User ID=<user-name>;Password=<password> SQL 연결 문자열을 생성하는 방법에 대한 자세한 내용은 SQL 설명서를 참조하세요. |
SQL_QUERY |
데이터 세트와 관련된 고유 쿼리입니다. |
환경 변수 만들기
키 및 엔드포인트에 대한 영구 환경 변수를 만들고 할당합니다.
Important
API 키를 사용하는 경우 Azure Key Vault와 같은 다른 위치에 안전하게 저장합니다. API 키를 코드에 직접 포함하지 말고, 공개적으로 게시하지 마세요.
AI 서비스 보안에 대한 자세한 내용은 Azure AI 서비스에 대한 요청 인증을 참조하세요.
setx METRICS_ADVISOR_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"
setx METRICS_ADVISOR_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx METRICS_ADVISOR_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx SQL_CONNECTION_STRING "REPLACE_WITH_YOUR_UNIQUE_SQL_CONNECTION_STRING"
setx SQL_QUERY "REPLACE_WITH_YOUR_UNIQUE_SQL_QUERY_BASED_ON_THE_UNDERLYING_STRUCTURE_OF_YOUR_DATA"
애플리케이션 만들기
index.js
라는 파일을 만들고 다음 코드를 복사합니다.
/**
* @summary This sample demonstrates how to get started by creating a data feed, checking ingestion status,
* creating detection and alerting configurations, and querying for alerts and anomalies.
*/
// Load the .env file if it exists
const dotenv = require("dotenv");
dotenv.config();
const {
MetricsAdvisorKeyCredential,
MetricsAdvisorAdministrationClient,
MetricsAdvisorClient
} = require("@azure/ai-metrics-advisor");
async function main() {
// You will need to set these environment variables or edit the following values
const endpoint = process.env["METRICS_ADVISOR_ENDPOINT"] || "<service endpoint>";
const subscriptionKey = process.env["METRICS_ADVISOR_KEY"] || "<subscription key>";
const apiKey = process.env["METRICS_ADVISOR_API_KEY"] || "<api key>";
const sqlServerConnectionString =
process.env["SQL_SERVER_CONNECTION_STRING"] ||
"<connection string to SQL Server>";
const sqlServerQuery =
process.env["SQL_SERVER_QUERY"] || "<SQL Server query to retrive data>";
const credential = new MetricsAdvisorKeyCredential(subscriptionKey, apiKey);
const client = new MetricsAdvisorClient(endpoint, credential);
const adminClient = new MetricsAdvisorAdministrationClient(endpoint, credential);
const created = await createDataFeed(adminClient, sqlServerConnectionString, sqlServerQuery);
console.log(`Data feed created: ${created.id}`);
console.log(" metrics: ");
console.log(created.schema.metrics);
console.log("Waiting for a minute before checking ingestion status...");
await delay(60 * 1000);
try {
await checkIngestionStatus(
adminClient,
created.id,
new Date(Date.UTC(2020, 8, 1)),
new Date(Date.UTC(2020, 8, 12))
);
const metricId = created.schema.metrics[0].id;
const detectionConfig = await configureAnomalyDetectionConfiguration(adminClient, metricId);
console.log(`Detection configuration created: ${detectionConfig.id}`);
const hook = await createWebhookHook(adminClient);
console.log(`Webhook hook created: ${hook.id}`);
const alertConfig = await configureAlertConfiguration(adminClient, detectionConfig.id, [
hook.id
]);
console.log(`Alert configuration created: ${alertConfig.id}`);
// you can use alert configuration created in above step to query the alert.
const alerts = await queryAlerts(
client,
alertConfig.id,
new Date(Date.UTC(2020, 8, 1)),
new Date(Date.UTC(2020, 8, 12))
);
if (alerts.length > 1) {
// query anomalies using an alert id.
await queryAnomaliesByAlert(client, alerts[0]);
} else {
console.log("No alerts during the time period");
}
} finally {
console.log(`Deleting the data feed '${created.id}`);
await adminClient.deleteDataFeed(created.id);
}
}
async function createDataFeed(adminClient, sqlServerConnectionString, sqlServerQuery) {
console.log("Creating Datafeed...");
const dataFeed = {
name: "test_datafeed_" + new Date().getTime().toString(),
source: {
dataSourceType: "SqlServer",
connectionString: sqlServerConnectionString,
query: sqlServerQuery,
authenticationType: "Basic"
},
granularity: {
granularityType: "Daily"
},
schema: {
metrics: [
{
name: "revenue",
displayName: "revenue",
description: "Metric1 description"
},
{
name: "cost",
displayName: "cost",
description: "Metric2 description"
}
],
dimensions: [
{ name: "city", displayName: "city display" },
{ name: "category", displayName: "category display" }
],
timestampColumn: undefined
},
ingestionSettings: {
ingestionStartTime: new Date(Date.UTC(2020, 5, 1)),
ingestionStartOffsetInSeconds: 0,
dataSourceRequestConcurrency: -1,
ingestionRetryDelayInSeconds: -1,
stopRetryAfterInSeconds: -1
},
rollupSettings: {
rollupType: "AutoRollup",
rollupMethod: "Sum",
rollupIdentificationValue: "__SUM__"
},
missingDataPointFillSettings: {
fillType: "SmartFilling"
},
accessMode: "Private",
admins: ["xyz@microsoft.com"]
};
const result = await adminClient.createDataFeed(dataFeed);
return result;
}
async function checkIngestionStatus(adminClient, datafeedId, startTime, endTime) {
// This shows how to use for-await-of syntax to list status
console.log("Checking ingestion status...");
const listIterator = adminClient.listDataFeedIngestionStatus(datafeedId, startTime, endTime);
for await (const status of listIterator) {
console.log(` [${status.timestamp}] ${status.status} - ${status.message}`);
}
}
async function configureAnomalyDetectionConfiguration(adminClient, metricId) {
console.log(`Creating an anomaly detection configuration on metric '${metricId}'...`);
const anomalyConfig = {
name: "test_detection_configuration" + new Date().getTime().toString(),
metricId,
wholeSeriesDetectionCondition: {
smartDetectionCondition: {
sensitivity: 100,
anomalyDetectorDirection: "Both",
suppressCondition: {
minNumber: 1,
minRatio: 1
}
}
},
description: "Detection configuration description"
};
return await adminClient.createDetectionConfig(anomalyConfig);
}
async function createWebhookHook(adminClient) {
console.log("Creating a webhook hook");
const hook = {
hookType: "Webhook",
name: "web hook " + new Date().getTime().toString(),
description: "description",
hookParameter: {
endpoint: "https://httpbin.org/post",
username: "user",
password: "pass"
// certificateKey: "k",
// certificatePassword: "kp"
}
};
return await adminClient.createHook(hook);
}
async function configureAlertConfiguration(adminClient, detectionConfigId, hookIds) {
console.log("Creating a new alerting configuration...");
const anomalyAlert = {
name: "test_alert_config_" + new Date().getTime().toString(),
crossMetricsOperator: "AND",
metricAlertConfigurations: [
{
detectionConfigurationId: detectionConfigId,
alertScope: {
scopeType: "All"
},
alertConditions: {
severityCondition: {
minAlertSeverity: "Medium",
maxAlertSeverity: "High"
}
},
snoozeCondition: {
autoSnooze: 0,
snoozeScope: "Metric",
onlyForSuccessive: true
}
}
],
hookIds,
description: "Alerting config description"
};
return await adminClient.createAlertConfig(anomalyAlert);
}
async function queryAlerts(client, alertConfigId, startTime, endTime) {
console.log(`Listing alerts for alert configuration '${alertConfigId}'`);
// This shows how to use `for-await-of` syntax to list alerts
console.log(" using for-await-of syntax");
let alerts = [];
const listIterator = client.listAlerts(alertConfigId, startTime, endTime, "AnomalyTime");
for await (const alert of listIterator) {
alerts.push(alert);
console.log(" Alert");
console.log(` id: ${alert.id}`);
console.log(` timestamp: ${alert.timestamp}`);
console.log(` created on: ${alert.createdOn}`);
}
// alternatively we could list results by pages
console.log(` by pages`);
const iterator = client
.listAlerts(alertConfigId, startTime, endTime, "AnomalyTime")
.byPage({ maxPageSize: 2 });
let result = await iterator.next();
while (!result.done) {
console.log(" -- Page -- ");
for (const item of result.value) {
console.log(` id: ${item.id}`);
console.log(` timestamp: ${item.timestamp}`);
console.log(` created on: ${item.createdOn}`);
}
result = await iterator.next();
}
return alerts;
}
async function queryAnomaliesByAlert(client, alert) {
console.log(
`Listing anomalies for alert configuration '${alert.alertConfigId}' and alert '${alert.id}'`
);
const listIterator = client.listAnomaliesForAlert(alert);
for await (const anomaly of listIterator) {
console.log(
` Anomaly ${anomaly.severity} ${anomaly.status} ${anomaly.seriesKey.dimension} ${anomaly.timestamp}`
);
}
}
async function delay(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
main()
.then((_) => {
console.log("Succeeded");
})
.catch((err) => {
console.log("Error occurred:");
console.log(err);
});
애플리케이션 실행
quickstart 파일의 node
명령을 사용하여 애플리케이션을 실행합니다.
node index.js
참조 설명서 | 라이브러리 소스 코드 | 패키지(PiPy) | 샘플
Important
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 이 문서에 설명된 인증 흐름 중 일부는 애플리케이션에 대해 매우 높은 수준의 신뢰를 요구하며 보다 안전한 다른 흐름에는 없는 위험을 수반합니다. 이 흐름은 관리 ID와 같은 보다 안전한 다른 흐름을 실행할 수 없는 경우에만 사용되어야 합니다.
필수 조건
- Azure 구독 - 체험 구독 만들기
- Python 3.x
- Azure 구독이 있으면 Azure Portal에서 Metrics Advisor 리소스 만들기를 수행하여 Metrics Advisor 인스턴스를 배포합니다.
- 시계열 데이터가 포함된 사용자 고유의 SQL 데이터베이스.
팁
- GitHub에서 Python Metrics Advisor 샘플을 찾을 수 있습니다.
- Metrics Advisor 리소스에서 사용할 서비스 인스턴스를 배포하는 데 10~30분 정도 걸릴 수 있습니다. 성공적으로 배포되면 리소스로 이동을 선택합니다. 배포 후에는 웹 포털과 REST API 모두를 사용하여 Metrics Advisor 인스턴스 사용을 시작할 수 있습니다.
- 리소스의 개요 섹션에서 Azure Portal의 REST API에 대한 URL을 찾을 수 있습니다. 다음과 같이 표시됩니다.
https://<instance-name>.cognitiveservices.azure.com/
설정
클라이언트 라이브러리 설치
클라이언트 라이브러리를 설치합니다. 다음을 사용하여 클라이언트 라이브러리를 설치할 수 있습니다.
pip install azure-ai-metricsadvisor --pre
환경 변수
Anomaly Detector 서비스를 성공적으로 호출하려면 다음 값이 필요합니다.
변수 이름 | 값 |
---|---|
METRICS_ADVISOR_ENDPOINT |
이 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. 엔드포인트 예: https://YOUR_RESOURCE_NAME.cognitiveservices.azure.com/ |
METRICS_ADVISOR_KEY |
키 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
METRICS_ADVISOR_API_KEY |
키 값은 Metrics Advisor 포털에서 리소스를 검사할 때 설정>API 키에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
SQL_CONNECTION_STRING |
이 빠른 시작에서는 고유한 SQL Database + 연결 문자열이 있어야 합니다. 연결 문자열 예제는 다음 예제와 유사합니다. Data Source=<Server>;Initial Catalog=<db-name>;User ID=<user-name>;Password=<password> SQL 연결 문자열을 생성하는 방법에 대한 자세한 내용은 SQL 설명서를 참조하세요. |
SQL_QUERY |
데이터 세트와 관련된 고유 쿼리입니다. |
환경 변수 만들기
키 및 엔드포인트에 대한 영구 환경 변수를 만들고 할당합니다.
Important
API 키를 사용하는 경우 Azure Key Vault와 같은 다른 위치에 안전하게 저장합니다. API 키를 코드에 직접 포함하지 말고, 공개적으로 게시하지 마세요.
AI 서비스 보안에 대한 자세한 내용은 Azure AI 서비스에 대한 요청 인증을 참조하세요.
setx METRICS_ADVISOR_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"
setx METRICS_ADVISOR_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx METRICS_ADVISOR_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx SQL_CONNECTION_STRING "REPLACE_WITH_YOUR_UNIQUE_SQL_CONNECTION_STRING"
setx SQL_QUERY "REPLACE_WITH_YOUR_UNIQUE_SQL_QUERY_BASED_ON_THE_UNDERLYING_STRUCTURE_OF_YOUR_DATA"
애플리케이션 만들기
다음 코드와 관계없는 Python 애플리케이션을 만듭니다.
"""
FILE: sample_data_feeds.py
DESCRIPTION:
This sample demonstrates how to create, get, list, update, and delete datafeeds under your Metrics Advisor account.
USAGE:
python sample_data_feeds.py
Set the environment variables with your own values before running the sample:
1) METRICS_ADVISOR_ENDPOINT - the endpoint of your Azure AI Metrics Advisor service
2) METRICS_ADVISOR_KEY - Metrics Advisor service subscription key
3) METRICS_ADVISOR_API_KEY - Metrics Advisor service API key
4) SQL_CONNECTION_STRING - Used in this sample for demonstration, but you should
add your own credentials specific to the data source type you're using
5) SQL_QUERY - Used in this sample for demonstration, but you should
add your own query specific to the structure of the data in your datasource.
"""
import os
import datetime
def sample_create_data_feed():
from azure.ai.metricsadvisor import MetricsAdvisorKeyCredential, MetricsAdvisorAdministrationClient
from azure.ai.metricsadvisor.models import (
SqlServerDataFeedSource,
DataFeedSchema,
DataFeedMetric,
DataFeedDimension,
DataFeedRollupSettings,
DataFeedMissingDataPointFillSettings,
)
service_endpoint = os.getenv("METRICS_ADVISOR_ENDPOINT")
subscription_key = os.getenv("METRICS_ADVISOR_KEY")
api_key = os.getenv("METRICS_ADVISOR_API_KEY")
sql_server_connection_string = os.getenv("SQL_CONNECTION_STRING")
query = os.getenv("SQL_QUERY")
client = MetricsAdvisorAdministrationClient(service_endpoint,
MetricsAdvisorKeyCredential(subscription_key, api_key))
data_feed = client.create_data_feed(
name="My data feed",
source=SqlServerDataFeedSource(
connection_string=sql_server_connection_string,
query=query,
),
granularity="Daily",
schema=DataFeedSchema(
metrics=[
DataFeedMetric(name="cost", display_name="Cost"),
DataFeedMetric(name="revenue", display_name="Revenue")
],
dimensions=[
DataFeedDimension(name="category", display_name="Category"),
DataFeedDimension(name="region", display_name="region")
],
timestamp_column="Timestamp"
),
ingestion_settings=datetime.datetime(2019, 10, 1),
data_feed_description="cost/revenue data feed",
rollup_settings=DataFeedRollupSettings(
rollup_type="AutoRollup",
rollup_method="Sum",
rollup_identification_value="__CUSTOM_SUM__"
),
missing_data_point_fill_settings=DataFeedMissingDataPointFillSettings(
fill_type="SmartFilling"
),
access_mode="Private"
)
return data_feed
def sample_get_data_feed(data_feed_id):
from azure.ai.metricsadvisor import MetricsAdvisorKeyCredential, MetricsAdvisorAdministrationClient
service_endpoint = os.getenv("METRICS_ADVISOR_ENDPOINT")
subscription_key = os.getenv("METRICS_ADVISOR_KEY")
api_key = os.getenv("METRICS_ADVISOR_API_KEY")
client = MetricsAdvisorAdministrationClient(service_endpoint,
MetricsAdvisorKeyCredential(subscription_key, api_key))
data_feed = client.get_data_feed(data_feed_id)
print("ID: {}".format(data_feed.id))
print("Data feed name: {}".format(data_feed.name))
print("Created time: {}".format(data_feed.created_time))
print("Status: {}".format(data_feed.status))
print("Source type: {}".format(data_feed.source.data_source_type))
print("Granularity type: {}".format(data_feed.granularity.granularity_type))
print("Data feed metrics: {}".format([metric.name for metric in data_feed.schema.metrics]))
print("Data feed dimensions: {}".format([dimension.name for dimension in data_feed.schema.dimensions]))
print("Data feed timestamp column: {}".format(data_feed.schema.timestamp_column))
print("Ingestion data starting on: {}".format(data_feed.ingestion_settings.ingestion_begin_time))
print("Data feed description: {}".format(data_feed.data_feed_description))
print("Data feed rollup type: {}".format(data_feed.rollup_settings.rollup_type))
print("Data feed rollup method: {}".format(data_feed.rollup_settings.rollup_method))
print("Data feed fill setting: {}".format(data_feed.missing_data_point_fill_settings.fill_type))
print("Data feed access mode: {}".format(data_feed.access_mode))
def sample_list_data_feeds():
from azure.ai.metricsadvisor import MetricsAdvisorKeyCredential, MetricsAdvisorAdministrationClient
service_endpoint = os.getenv("METRICS_ADVISOR_ENDPOINT")
subscription_key = os.getenv("METRICS_ADVISOR_SUBSCRIPTION_KEY")
api_key = os.getenv("METRICS_ADVISOR_API_KEY")
client = MetricsAdvisorAdministrationClient(service_endpoint,
MetricsAdvisorKeyCredential(subscription_key, api_key))
data_feeds = client.list_data_feeds()
for feed in data_feeds:
print("Data feed name: {}".format(feed.name))
print("ID: {}".format(feed.id))
print("Created time: {}".format(feed.created_time))
print("Status: {}".format(feed.status))
print("Source type: {}".format(feed.source.data_source_type))
print("Granularity type: {}".format(feed.granularity.granularity_type))
print("\nFeed metrics:")
for metric in feed.schema.metrics:
print(metric.name)
print("\nFeed dimensions:")
for dimension in feed.schema.dimensions:
print(dimension.name)
def sample_update_data_feed(data_feed):
from azure.ai.metricsadvisor import MetricsAdvisorKeyCredential, MetricsAdvisorAdministrationClient
service_endpoint = os.getenv("METRICS_ADVISOR_ENDPOINT")
subscription_key = os.getenv("METRICS_ADVISOR_KEY")
api_key = os.getenv("METRICS_ADVISOR_API_KEY")
client = MetricsAdvisorAdministrationClient(service_endpoint,
MetricsAdvisorKeyCredential(subscription_key, api_key))
# update data feed on the data feed itself or by using available keyword arguments
data_feed.name = "updated name"
data_feed.data_feed_description = "updated description for data feed"
updated = client.update_data_feed(
data_feed,
access_mode="Public",
fill_type="CustomValue",
custom_fill_value=1
)
print("Updated name: {}".format(updated.name))
print("Updated description: {}".format(updated.data_feed_description))
print("Updated access mode: {}".format(updated.access_mode))
print("Updated fill setting, value: {}, {}".format(
updated.missing_data_point_fill_settings.fill_type,
updated.missing_data_point_fill_settings.custom_fill_value,
))
def sample_delete_data_feed(data_feed_id):
from azure.core.exceptions import ResourceNotFoundError
from azure.ai.metricsadvisor import MetricsAdvisorKeyCredential, MetricsAdvisorAdministrationClient
service_endpoint = os.getenv("METRICS_ADVISOR_ENDPOINT")
subscription_key = os.getenv("METRICS_ADVISOR_KEY")
api_key = os.getenv("METRICS_ADVISOR_API_KEY")
client = MetricsAdvisorAdministrationClient(service_endpoint,
MetricsAdvisorKeyCredential(subscription_key, api_key))
client.delete_data_feed(data_feed_id)
try:
client.get_data_feed(data_feed_id)
except ResourceNotFoundError:
print("Data feed successfully deleted.")
if __name__ == '__main__':
print("---Creating data feed...")
data_feed = sample_create_data_feed()
print("Data feed successfully created...")
print("\n---Get a data feed...")
sample_get_data_feed(data_feed.id)
print("\n---List data feeds...")
sample_list_data_feeds()
print("\n---Update a data feed...")
sample_update_data_feed(data_feed)
print("\n---Delete a data feed...")
sample_delete_data_feed(data_feed.id)
애플리케이션 실행
quickstart 파일의 python
명령을 사용하여 애플리케이션을 실행합니다.
python quickstart-file.py
필수 조건
- Azure 구독 - 체험 구독 만들기
- Azure 구독이 있으면 Azure Portal에서 Metrics Advisor 리소스 만들기를 수행하여 Metrics Advisor 인스턴스를 배포합니다.
- Python 3.x
- 시계열 데이터가 포함된 사용자 고유의 SQL 데이터베이스.
Important
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 이 문서에 설명된 인증 흐름 중 일부는 애플리케이션에 대해 매우 높은 수준의 신뢰를 요구하며 보다 안전한 다른 흐름에는 없는 위험을 수반합니다. 이 흐름은 관리 ID와 같은 보다 안전한 다른 흐름을 실행할 수 없는 경우에만 사용되어야 합니다.
설정
이 빠른 시작의 예제 코드에서는 Python을 사용하여 REST API를 호출하는 방법을 보여 줍니다. 특정 REST API 호출은 GitHub 샘플을 참조하세요.
팁
- Metrics Advisor 리소스에서 사용할 서비스 인스턴스를 배포하는 데 10~30분 정도 걸릴 수 있습니다. 성공적으로 배포되면 리소스로 이동을 선택합니다. 배포 후에는 웹 포털과 REST API 모두를 사용하여 Metrics Advisor 인스턴스 사용을 시작할 수 있습니다.
- 리소스의 개요 섹션에서 Azure Portal의 REST API에 대한 URL을 찾을 수 있습니다. 다음과 같이 표시됩니다.
https://<instance-name>.cognitiveservices.azure.com/
환경 변수
Anomaly Detector 서비스를 성공적으로 호출하려면 다음 값이 필요합니다.
변수 이름 | 값 |
---|---|
METRICS_ADVISOR_ENDPOINT |
이 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. 엔드포인트 예: https://YOUR_RESOURCE_NAME.cognitiveservices.azure.com/ |
METRICS_ADVISOR_KEY |
키 값은 Azure Portal에서 리소스를 검사할 때 키 및 엔드포인트 섹션에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
METRICS_ADVISOR_API_KEY |
키 값은 Metrics Advisor 포털에서 리소스를 검사할 때 설정>API 키에서 찾을 수 있습니다. KEY1 또는 KEY2 를 사용할 수 있습니다. |
SQL_CONNECTION_STRING |
이 빠른 시작에서는 고유한 SQL Database + 연결 문자열이 있어야 합니다. 연결 문자열 예제는 다음 예제와 유사합니다. Data Source=<Server>;Initial Catalog=<db-name>;User ID=<user-name>;Password=<password> SQL 연결 문자열을 생성하는 방법에 대한 자세한 내용은 SQL 설명서를 참조하세요. |
SQL_QUERY |
데이터 세트와 관련된 고유 쿼리입니다. |
환경 변수 만들기
키 및 엔드포인트에 대한 영구 환경 변수를 만들고 할당합니다.
Important
API 키를 사용하는 경우 Azure Key Vault와 같은 다른 위치에 안전하게 저장합니다. API 키를 코드에 직접 포함하지 말고, 공개적으로 게시하지 마세요.
AI 서비스 보안에 대한 자세한 내용은 Azure AI 서비스에 대한 요청 인증을 참조하세요.
setx METRICS_ADVISOR_ENDPOINT "REPLACE_WITH_YOUR_ENDPOINT_HERE"
setx METRICS_ADVISOR_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx METRICS_ADVISOR_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
setx SQL_CONNECTION_STRING "REPLACE_WITH_YOUR_UNIQUE_SQL_CONNECTION_STRING"
setx SQL_QUERY "REPLACE_WITH_YOUR_UNIQUE_SQL_QUERY_BASED_ON_THE_UNDERLYING_STRUCTURE_OF_YOUR_DATA"
애플리케이션 만들기
import requests
import json
import time
def add_data_feed(endpoint, subscription_key, api_key):
url = endpoint + '/dataFeeds'
data_feed_body = {
"dataSourceType": "SqlServer",
"dataFeedName": "test_data_feed_00000001",
"dataFeedDescription": "",
"dataSourceParameter": {
"connectionString": os.environ['SQL_CONNECTION_STRING'],
"query": os.environ['SQL_QUERY']
},
"granularityName": "Daily",
"granularityAmount": 0,
"metrics": [
{
"metricName": "revenue",
"metricDisplayName": "revenue",
"metricDescription": ""
},
{
"metricName": "cost",
"metricDisplayName": "cost",
"metricDescription": ""
}
],
"dimension": [
{
"dimensionName": "city",
"dimensionDisplayName": "city"
},
{
"dimensionName": "category",
"dimensionDisplayName": "category"
}
],
"timestampColumn": "timestamp",
"dataStartFrom": "2020-06-01T00:00:00.000Z",
"startOffsetInSeconds": 0,
"maxConcurrency": -1,
"minRetryIntervalInSeconds": -1,
"stopRetryAfterInSeconds": -1,
"allUpIdentification": "__SUM__",
"needRollup": "AlreadyRollup",
"fillMissingPointType": "SmartFilling",
"fillMissingPointValue": 0,
"viewMode": "Private",
"admins": [
"admin@contoso.com"
],
"viewers": [
],
"actionLinkTemplate": ""
}
res = requests.post(url, data=json.dumps(data_feed_body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 201:
raise RuntimeError("add_data_feed failed " + res.text)
else:
print("add_data_feed success " + res.text)
return res.headers['Location']
def check_ingestion_latest_status(endpoint, subscription_key, api_key, datafeed_id):
url = endpoint + '/dataFeeds/{}/ingestionProgress'.format(datafeed_id)
res = requests.get(url, headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("check_ingestion_latest_status failed " + res.text)
else:
print("check_ingestion_latest_status success " + res.text)
def check_ingestion_detail_status(endpoint, subscription_key, api_key, datafeed_id, start_time, end_time):
url = endpoint + '/dataFeeds/{}/ingestionStatus/query'.format(datafeed_id)
ingestion_detail_status_body = {
"startTime": start_time,
"endTime": end_time
}
res = requests.post(url, data=json.dumps(ingestion_detail_status_body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("check_ingestion_detail_status failed " + res.text)
else:
print("check_ingestion_detail_status success " + res.text)
def create_detection_config(endpoint, subscription_key, api_key, metric_id):
url = endpoint + '/enrichment/anomalyDetection/configurations'
detection_config_body = {
"name": "test_detection_config0000000001",
"description": "string",
"metricId": metric_id,
"wholeMetricConfiguration": {
"smartDetectionCondition": {
"sensitivity": 100,
"anomalyDetectorDirection": "Both",
"suppressCondition": {
"minNumber": 1,
"minRatio": 1
}
}
},
"dimensionGroupOverrideConfigurations": [
],
"seriesOverrideConfigurations": [
]
}
res = requests.post(url, data=json.dumps(detection_config_body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 201:
raise RuntimeError("create_detection_config failed " + res.text)
else:
print("create_detection_config success " + res.text)
return res.headers['Location']
def create_web_hook(endpoint, subscription_key, api_key):
url = endpoint + '/hooks'
web_hook_body = {
"hookType": "Webhook",
"hookName": "test_web_hook000001",
"description": "",
"externalLink": "",
"hookParameter": {
"endpoint": "https://www.contoso.com",
"username": "",
"password": ""
}
}
res = requests.post(url, data=json.dumps(web_hook_body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 201:
raise RuntimeError("create_web_hook failed " + res.text)
else:
print("create_web_hook success " + res.text)
return res.headers['Location']
def create_alert_config(endpoint, subscription_key, api_key, anomaly_detection_configuration_id, hook_id):
url = endpoint + '/alert/anomaly/configurations'
web_hook_body = {
"name": "test_alert_config00000001",
"description": "",
"crossMetricsOperator": "AND",
"hookIds": [
hook_id
],
"metricAlertingConfigurations": [
{
"anomalyDetectionConfigurationId": anomaly_detection_configuration_id,
"anomalyScopeType": "All",
"severityFilter": {
"minAlertSeverity": "Low",
"maxAlertSeverity": "High"
},
"snoozeFilter": {
"autoSnooze": 0,
"snoozeScope": "Metric",
"onlyForSuccessive": True
},
}
]
}
res = requests.post(url, data=json.dumps(web_hook_body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 201:
raise RuntimeError("create_alert_config failed " + res.text)
else:
print("create_alert_config success " + res.text)
return res.headers['Location']
def query_alert_by_alert_config(endpoint, subscription_key, api_key, alert_config_id, start_time, end_time):
url = endpoint + '/alert/anomaly/configurations/{}/alerts/query'.format(alert_config_id)
alerts_body = {
"startTime": start_time,
"endTime": end_time,
"timeMode": "AnomalyTime"
}
res = requests.post(url, data=json.dumps(alerts_body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("query_alert_by_alert_config failed " + res.text)
else:
print("query_alert_by_alert_config success " + res.text)
return [item['alertId'] for item in json.loads(res.content)['value']]
def query_anomaly_by_alert(endpoint, subscription_key, api_key, alert_config_id, alert_id):
url = endpoint + '/alert/anomaly/configurations/{}/alerts/{}/anomalies'.format(alert_config_id, alert_id)
res = requests.get(url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("query_anomaly_by_alert failed " + res.text)
else:
print("query_anomaly_by_alert success " + res.text)
return json.loads(res.content)
def query_incident_by_alert(endpoint, subscription_key, api_key, alert_config_id, alert_id):
url = endpoint + '/alert/anomaly/configurations/{}/alerts/{}/incidents'.format(alert_config_id, alert_id)
res = requests.get(url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("query_incident_by_alert failed " + res.text)
else:
print("query_incident_by_alert success " + res.text)
return json.loads(res.content)
def query_root_cause_by_incident(endpoint, subscription_key, api_key, detection_config_id, incident_id):
url = endpoint + '/enrichment/anomalyDetection/configurations/{}/incidents/{}/rootCause'.format(detection_config_id, incident_id)
res = requests.get(url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("query_root_cause_by_incident failed " + res.text)
else:
print("query_root_cause_by_incident success " + res.text)
return json.loads(res.content)
def query_anomaly_by_detection_config(endpoint, subscription_key, api_key, detection_config_id, start_time, end_time):
url = endpoint + '/enrichment/anomalyDetection/configurations/{}/anomalies/query'.format(detection_config_id)
body = {
"startTime": start_time,
"endTime": end_time,
"filter": {
"dimensionFilter": [
],
"severityFilter": {
"min": "Low",
"max": "High"
}
}
}
res = requests.post(url, data=json.dumps(body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("query_anomaly_by_detection_config failed " + res.text)
else:
print("query_anomaly_by_detection_config success " + res.text)
return json.loads(res.content)
def query_incident_by_detection_config(endpoint, subscription_key, api_key, detection_config_id, start_time, end_time):
url = endpoint + '/enrichment/anomalyDetection/configurations/{}/incidents/query'.format(detection_config_id)
body = {
"startTime": start_time,
"endTime": end_time,
"filter": {
"dimensionFilter": [
],
}
}
res = requests.post(url, data=json.dumps(body),
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key})
if res.status_code != 200:
raise RuntimeError("query_incident_by_detection_config failed " + res.text)
else:
print("query_incident_by_detection_config success " + res.text)
return json.loads(res.content)
if __name__ == '__main__':
# Example endpoint: https://[placeholder].cognitiveservices.azure.com/metricsadvisor/v1.0
endpoint = os.environ['METRICS_ADVISOR_ENDPOINT'] + "metricsadvisor/v1.0"
subscription_key = os.environ['METRICS_ADVISOR_KEY']
api_key = os.environ['METRICS_ADVISOR_API_KEY']
'''
First part
1.onboard datafeed
2.check datafeed latest status
3.check datafeed status details
4.create detection config
5.create webhook
6.create alert config
'''
datafeed_resource_url = add_data_feed(endpoint, subscription_key, api_key)
print(datafeed_resource_url)
# datafeed_id and metrics_id can get from datafeed_resource_url
datafeed_info = json.loads(requests.get(url=datafeed_resource_url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key}).content)
print(datafeed_info)
datafeed_id = datafeed_info['dataFeedId']
metrics_id = []
for metrics in datafeed_info['metrics']:
metrics_id.append(metrics['metricId'])
time.sleep(60)
check_ingestion_latest_status(endpoint, subscription_key, api_key, datafeed_id)
check_ingestion_detail_status(endpoint, subscription_key, api_key, datafeed_id,
"2020-06-01T00:00:00Z", "2020-07-01T00:00:00Z")
detection_config_resource_url = create_detection_config(endpoint, subscription_key, api_key, metrics_id[0])
print(detection_config_resource_url)
# anomaly_detection_configuration_id can get from detection_config_resource_url
detection_config = json.loads(requests.get(url=detection_config_resource_url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key}).content)
print(detection_config)
anomaly_detection_configuration_id = detection_config['anomalyDetectionConfigurationId']
webhook_resource_url = create_web_hook(endpoint, subscription_key, api_key)
print(webhook_resource_url)
# hook_id can get from webhook_resource_url
webhook = json.loads(requests.get(url=webhook_resource_url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key}).content)
print(webhook)
hook_id = webhook['hookId']
alert_config_resource_url = create_alert_config(endpoint, subscription_key, api_key,
anomaly_detection_configuration_id, hook_id)
# anomaly_alerting_configuration_id can get from alert_config_resource_url
alert_config = json.loads(requests.get(url=alert_config_resource_url,
headers={'Ocp-Apim-Subscription-Key': subscription_key,
'x-api-key': api_key}).content)
print(alert_config)
anomaly_alerting_configuration_id = alert_config['anomalyAlertingConfigurationId']
리소스 정리
Azure AI 서비스 구독을 정리하고 제거하려면 리소스 또는 리소스 그룹을 삭제할 수 있습니다. 리소스 그룹을 삭제하면 해당 리소스 그룹에 연결된 다른 모든 리소스가 함께 삭제됩니다.