azure-sdk-for-js/sdk/metricsadvisor/ai-metrics-advisor/samples-dev/quickstart.ts

300 строки
9.2 KiB
TypeScript

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @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.
* @azsdk-weight 100
*/
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
import {
MetricsAdvisorKeyCredential,
MetricsAdvisorAdministrationClient,
AnomalyAlert,
MetricsAdvisorDataFeed,
MetricsAdvisorClient,
WebNotificationHook,
DataFeedDescriptor,
AnomalyAlertConfiguration,
AnomalyDetectionConfiguration,
} from "@azure/ai-metrics-advisor";
export 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_SUBSCRIPTION_KEY"] || "<subscription key>";
const apiKey = process.env["METRICS_ADVISOR_API_KEY"] || "<api key>";
const sqlServerConnectionString =
process.env["METRICS_ADVISOR_SQL_SERVER_CONNECTION_STRING"] ||
"<connection string to SQL Server>";
const sqlServerQuery =
process.env["METRICS_ADVISOR_AZURE_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: MetricsAdvisorAdministrationClient,
sqlServerConnectionString: string,
sqlServerQuery: string,
): Promise<MetricsAdvisorDataFeed> {
console.log("Creating Datafeed...");
const dataFeed: DataFeedDescriptor = {
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: MetricsAdvisorAdministrationClient,
datafeedId: string,
startTime: Date,
endTime: Date,
) {
// 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: MetricsAdvisorAdministrationClient,
metricId: string,
) {
console.log(`Creating an anomaly detection configuration on metric '${metricId}'...`);
const anomalyConfig: Omit<AnomalyDetectionConfiguration, "id"> = {
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: MetricsAdvisorAdministrationClient) {
console.log("Creating a webhook hook");
const hook: WebNotificationHook = {
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: MetricsAdvisorAdministrationClient,
detectionConfigId: string,
hookIds: string[],
) {
console.log("Creating a new alerting configuration...");
const anomalyAlert: Omit<AnomalyAlertConfiguration, "id"> = {
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: MetricsAdvisorClient,
alertConfigId: string,
startTime: Date,
endTime: Date,
) {
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: AnomalyAlert[] = [];
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: MetricsAdvisorClient, alert: AnomalyAlert) {
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: number) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
main()
.then((_) => {
console.log("Succeeded");
})
.catch((err) => {
console.log("Error occurred:");
console.log(err);
});