Biblioteka klienta zapytań usługi Azure Monitor dla języka JavaScript — wersja 1.2.0

Biblioteka klienta zapytań usługi Azure Monitor służy do wykonywania zapytań tylko do odczytu na dwóch platformach danych usługi Azure Monitor:

  • Dzienniki — zbiera i organizuje dane dzienników i wydajności z monitorowanych zasobów. Dane z różnych źródeł, takich jak dzienniki platformy z usług platformy Azure, dane dzienników i wydajności agentów maszyn wirtualnych, a dane użycia i wydajności z aplikacji można skonsolidować w jednym obszarze roboczym usługi Azure Log Analytics. Różne typy danych można analizować razem przy użyciu język zapytań Kusto.
  • Metryki — zbiera dane liczbowe z monitorowanych zasobów do bazy danych szeregów czasowych. Metryki to wartości liczbowe, które są zbierane w regularnych odstępach czasu i opisują jakiś aspekt systemu w określonym czasie. Metryki są lekkie i mogą obsługiwać scenariusze niemal w czasie rzeczywistym, co ułatwia alerty i szybkie wykrywanie problemów.

Zasoby:

Wprowadzenie

Obsługiwane środowiska

  • Wersje LTS Node.js
  • Najnowsze wersje przeglądarek Safari, Chrome, Microsoft Edge i Firefox

Aby uzyskać więcej informacji, zobacz nasze zasady pomocy technicznej.

Wymagania wstępne

Instalowanie pakietu

Zainstaluj bibliotekę klienta zapytań usługi Azure Monitor dla języka JavaScript przy użyciu narzędzia npm:

npm install @azure/monitor-query

Tworzenie klienta

Uwierzytelniony klient jest wymagany do wykonywania zapytań dotyczących dzienników lub metryk. Aby przeprowadzić uwierzytelnianie, w poniższym przykładzie użyto wartości DefaultAzureCredential z pakietu @azure/tożsamości .

import { DefaultAzureCredential } from "@azure/identity";
import { LogsQueryClient, MetricsQueryClient, MetricsBatchQueryClient } from "@azure/monitor-query";

const credential = new DefaultAzureCredential();

const logsQueryClient: LogsQueryClient = new LogsQueryClient(credential);
// or
const metricsQueryClient: MetricsQueryClient = new MetricsQueryClient(credential);
// or
const endPoint: string = "<YOUR_METRICS_ENDPOINT>"; //for example, https://eastus.metrics.monitor.azure.com/

const metricsQueryClient: MetricsQueryClient = new MetricsQueryClient(
  endPoint,
  credential
);

Konfigurowanie klienta dla suwerennej chmury platformy Azure

Domyślnie LogsQueryClient i MetricsQueryClient są skonfigurowane do korzystania z chmury publicznej Platformy Azure. Aby zamiast tego użyć suwerennej chmury, podaj poprawny endpoint argument. Na przykład:

import { DefaultAzureCredential } from "@azure/identity";
import { LogsQueryClient, MetricsQueryClient } from "@azure/monitor-query";

const credential = new DefaultAzureCredential();

const logsQueryClient = new LogsQueryClient(credential, {
  endpoint: "https://api.loganalytics.azure.cn/v1",
});

// or
const metricsQueryClient = new MetricsQueryClient(credential{
  endpoint: "https://management.chinacloudapi.cn",
});

Uwaga: obecnie MetricsQueryClient do wykonywania zapytań dotyczących metryk jest używany punkt końcowy usługi Azure Resource Manager (ARM). Potrzebny jest odpowiedni punkt końcowy zarządzania dla chmury podczas korzystania z tego klienta. Te szczegóły mogą ulec zmianie w przyszłości.

Wykonaj zapytanie

Przykłady zapytań dzienników i metryk można znaleźć w sekcji Przykłady .

Kluczowe pojęcia

Rejestruje limity szybkości zapytań i ograniczanie przepustowości

Usługa Log Analytics stosuje ograniczanie przepustowości, gdy szybkość żądania jest zbyt wysoka. Limity, takie jak maksymalna liczba zwracanych wierszy, są również stosowane do zapytań Kusto. Aby uzyskać więcej informacji, zobacz Interfejs API zapytań.

Struktura danych metryk

Każdy zestaw wartości metryk jest szeregiem czasowym o następujących cechach:

  • Czas zbierania wartości
  • Zasób skojarzony z wartością
  • Przestrzeń nazw, która działa jak kategoria metryki
  • Nazwa metryki
  • Sama wartość
  • Niektóre metryki mają wiele wymiarów zgodnie z opisem w metrykach wielowymiarowych. Metryki niestandardowe mogą mieć maksymalnie 10 wymiarów.

Przykłady

Zapytanie dotyczące dzienników

Element LogsQueryClient może służyć do wykonywania zapytań względem obszaru roboczego usługi Log Analytics przy użyciu język zapytań Kusto. Można timespan.duration go określić jako ciąg w formacie czasu trwania ISO 8601. Możesz użyć Durations stałych podanych dla niektórych często używanych czasów trwania ISO 8601.

Możesz wykonywać zapytania dotyczące dzienników według identyfikatora obszaru roboczego lub identyfikatora zasobu. Wynik jest zwracany jako tabela z kolekcją wierszy.

Zapytanie dotyczące dzienników skoncentrowanych na obszarze roboczym

Aby wykonywać zapytania według identyfikatora LogsQueryClient.queryWorkspace obszaru roboczego, użyj metody :

import { DefaultAzureCredential } from "@azure/identity";
import { Durations, LogsQueryClient, LogsQueryResultStatus, LogsTable } from "@azure/monitor-query";

const azureLogAnalyticsWorkspaceId = "<the Workspace Id for your Azure Log Analytics resource>";
const logsQueryClient = new LogsQueryClient(new DefaultAzureCredential());

async function run() {
  const kustoQuery = "AppEvents | limit 1";
  const result = await logsQueryClient.queryWorkspace(azureLogAnalyticsWorkspaceId, kustoQuery, {
    duration: Durations.twentyFourHours,
  });

  if (result.status === LogsQueryResultStatus.Success) {
    const tablesFromResult: LogsTable[] = result.tables;

    if (tablesFromResult.length === 0) {
      console.log(`No results for query '${kustoQuery}'`);
      return;
    }
    console.log(`This query has returned table(s) - `);
    processTables(tablesFromResult);
  } else {
    console.log(`Error processing the query '${kustoQuery}' - ${result.partialError}`);
    if (result.partialTables.length > 0) {
      console.log(`This query has also returned partial data in the following table(s) - `);
      processTables(result.partialTables);
    }
  }
}

async function processTables(tablesFromResult: LogsTable[]) {
  for (const table of tablesFromResult) {
    const columnHeaderString = table.columnDescriptors
      .map((column) => `${column.name}(${column.type}) `)
      .join("| ");
    console.log("| " + columnHeaderString);

    for (const row of table.rows) {
      const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| ");
      console.log("| " + columnValuesString);
    }
  }
}

run().catch((err) => console.log("ERROR:", err));

Zapytanie dotyczące dzienników skoncentrowanych na zasobach

W poniższym przykładzie pokazano, jak wykonywać zapytania dotyczące dzienników bezpośrednio z zasobu platformy Azure. queryResource W tym miejscu jest używana metoda, a identyfikator zasobu platformy Azure jest przekazywany. Na przykład /subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/{resource-provider}/{resource-type}/{resource-name}.

Aby znaleźć identyfikator zasobu:

  1. Przejdź do strony zasobu w Azure Portal.
  2. W bloku Przegląd wybierz link Widok JSON .
  3. W wynikowym formacie JSON skopiuj wartość id właściwości .
/**
 * @summary Demonstrates how to run a query against a Log Analytics workspace, using an Azure resource ID.
 */

import { DefaultAzureCredential } from "@azure/identity";
import {
  Durations,
  LogsQueryClient,
  LogsTable,
  LogsQueryOptions,
  LogsQueryResultStatus,
} from "@azure/monitor-query";
import * as dotenv from "dotenv";
dotenv.config();

const logsResourceId = process.env.LOGS_RESOURCE_ID;

export async function main() {
  const tokenCredential = new DefaultAzureCredential();
  const logsQueryClient = new LogsQueryClient(tokenCredential);

  if (!logsResourceId) {
    throw new Error("LOGS_RESOURCE_ID must be set in the environment for this sample");
  }

  const kustoQuery = `MyTable_CL | summarize count()`

  console.log(`Running '${kustoQuery}' over the last One Hour`);
  const queryLogsOptions: LogsQueryOptions = {
    // explicitly control the amount of time the server can spend processing the query.
    serverTimeoutInSeconds: 600, // sets the timeout to 10 minutes
    // optionally enable returning additional statistics about the query's execution.
    // (by default, this is off)
    includeQueryStatistics: true,
  };

  const result = await logsQueryClient.queryResource(
    logsResourceId, 
    kustoQuery,
    { duration: Durations.sevenDays },
    queryLogsOptions);

  const executionTime =
    result.statistics && result.statistics.query && (result.statistics.query as any).executionTime;

  console.log(
    `Results for query '${kustoQuery}', execution time: ${
      executionTime == null ? "unknown" : executionTime
    }`
  );

  if (result.status === LogsQueryResultStatus.Success) {
    const tablesFromResult: LogsTable[] = result.tables;

    if (tablesFromResult.length === 0) {
      console.log(`No results for query '${kustoQuery}'`);
      return;
    }
    console.log(`This query has returned table(s) - `);
    processTables(tablesFromResult);
  } else {
    console.log(`Error processing the query '${kustoQuery}' - ${result.partialError}`);
    if (result.partialTables.length > 0) {
      console.log(`This query has also returned partial data in the following table(s) - `);
      processTables(result.partialTables);
    }
  }
}

async function processTables(tablesFromResult: LogsTable[]) {
  for (const table of tablesFromResult) {
    const columnHeaderString = table.columnDescriptors
      .map((column) => `${column.name}(${column.type}) `)
      .join("| ");
    console.log("| " + columnHeaderString);

    for (const row of table.rows) {
      const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| ");
      console.log("| " + columnValuesString);
    }
  }
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
  process.exit(1);
});

Obsługa odpowiedzi zapytania dotyczącego dzienników

Funkcja queryWorkspace funkcji LogsQueryClient zwraca LogsQueryResult obiekt. Typ obiektu może mieć wartość LogsQuerySuccessfulResult lub LogsQueryPartialResult. Oto hierarchia odpowiedzi:

LogsQuerySuccessfulResult
|---statistics
|---visualization
|---status ("Success")
|---tables (list of `LogsTable` objects)
    |---name
    |---rows
    |---columnDescriptors (list of `LogsColumn` objects)
        |---name
        |---type

LogsQueryPartialResult
|---statistics
|---visualization
|---status ("PartialFailure")
|---partialError
    |--name
    |--code
    |--message
    |--stack
|---partialTables (list of `LogsTable` objects)
    |---name
    |---rows
    |---columnDescriptors (list of `LogsColumn` objects)
        |---name
        |---type

Aby na przykład obsłużyć odpowiedź z tabelami:

async function processTables(tablesFromResult: LogsTable[]) {
  for (const table of tablesFromResult) {
    const columnHeaderString = table.columnDescriptors
      .map((column) => `${column.name}(${column.type}) `)
      .join("| ");
    console.log("| " + columnHeaderString);

    for (const row of table.rows) {
      const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| ");
      console.log("| " + columnValuesString);
    }
  }
}

Pełny przykład można znaleźć tutaj.

Zapytanie dotyczące dzienników usługi Batch

W poniższym przykładzie pokazano wysyłanie wielu zapytań jednocześnie przy użyciu interfejsu API zapytań wsadowych. Zapytania mogą być reprezentowane jako lista BatchQuery obiektów.

export async function main() {
  if (!monitorWorkspaceId) {
    throw new Error("MONITOR_WORKSPACE_ID must be set in the environment for this sample");
  }

  const tokenCredential = new DefaultAzureCredential();
  const logsQueryClient = new LogsQueryClient(tokenCredential);

  const kqlQuery = "AppEvents | project TimeGenerated, Name, AppRoleInstance | limit 1";
  const queriesBatch = [
    {
      workspaceId: monitorWorkspaceId,
      query: kqlQuery,
      timespan: { duration: "P1D" },
    },
    {
      workspaceId: monitorWorkspaceId,
      query: "AzureActivity | summarize count()",
      timespan: { duration: "PT1H" },
    },
    {
      workspaceId: monitorWorkspaceId,
      query:
        "AppRequests | take 10 | summarize avgRequestDuration=avg(DurationMs) by bin(TimeGenerated, 10m), _ResourceId",
      timespan: { duration: "PT1H" },
    },
    {
      workspaceId: monitorWorkspaceId,
      query: "AppRequests | take 2",
      timespan: { duration: "PT1H" },
      includeQueryStatistics: true,
    },
  ];

  const result = await logsQueryClient.queryBatch(queriesBatch);

  if (result == null) {
    throw new Error("No response for query");
  }

  let i = 0;
  for (const response of result) {
    console.log(`Results for query with query: ${queriesBatch[i]}`);
    if (response.status === LogsQueryResultStatus.Success) {
      console.log(
        `Printing results from query '${queriesBatch[i].query}' for '${queriesBatch[i].timespan}'`
      );
      processTables(response.tables);
    } else if (response.status === LogsQueryResultStatus.PartialFailure) {
      console.log(
        `Printing partial results from query '${queriesBatch[i].query}' for '${queriesBatch[i].timespan}'`
      );
      processTables(response.partialTables);
      console.log(
        ` Query had errors:${response.partialError.message} with code ${response.partialError.code}`
      );
    } else {
      console.log(`Printing errors from query '${queriesBatch[i].query}'`);
      console.log(` Query had errors:${response.message} with code ${response.code}`);
    }
    // next query
    i++;
  }
}

async function processTables(tablesFromResult: LogsTable[]) {
  for (const table of tablesFromResult) {
    const columnHeaderString = table.columnDescriptors
      .map((column) => `${column.name}(${column.type}) `)
      .join("| ");
    console.log("| " + columnHeaderString);

    for (const row of table.rows) {
      const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| ");
      console.log("| " + columnValuesString);
    }
  }
}

Obsługa odpowiedzi zapytania wsadowego dzienników

Funkcja queryBatch funkcji LogsQueryClient zwraca LogsQueryBatchResult obiekt. LogsQueryBatchResult zawiera listę obiektów z następującymi możliwymi typami:

  • LogsQueryPartialResult
  • LogsQuerySuccessfulResult
  • LogsQueryError

Oto hierarchia odpowiedzi:

LogsQuerySuccessfulResult
|---statistics
|---visualization
|---status ("Success")
|---tables (list of `LogsTable` objects)
    |---name
    |---rows
    |---columnDescriptors (list of `LogsColumn` objects)
        |---name
        |---type

LogsQueryPartialResult
|---statistics
|---visualization
|---status ("PartialFailure")
|---partialError
    |--name
    |--code
    |--message
    |--stack
|---partialTables (list of `LogsTable` objects)
    |---name
    |---rows
    |---columnDescriptors (list of `LogsColumn` objects)
        |---name
        |---type

LogsQueryError
|--name
|--code
|--message
|--stack
|--status ("Failure")

Na przykład poniższy kod obsługuje odpowiedź zapytania dzienników wsadowych:

async function processBatchResult(result: LogsQueryBatchResult) {
  let i = 0;
  for (const response of result) {
    console.log(`Results for query with query: ${queriesBatch[i]}`);
    if (response.status === LogsQueryResultStatus.Success) {
      console.log(
        `Printing results from query '${queriesBatch[i].query}' for '${queriesBatch[i].timespan}'`
      );
      processTables(response.tables);
    } else if (response.status === LogsQueryResultStatus.PartialFailure) {
      console.log(
        `Printing partial results from query '${queriesBatch[i].query}' for '${queriesBatch[i].timespan}'`
      );
      processTables(response.partialTables);
      console.log(
        ` Query had errors:${response.partialError.message} with code ${response.partialError.code}`
      );
    } else {
      console.log(`Printing errors from query '${queriesBatch[i].query}'`);
      console.log(` Query had errors:${response.message} with code ${response.code}`);
    }
    // next query
    i++;
  }
}

async function processTables(tablesFromResult: LogsTable[]) {
  for (const table of tablesFromResult) {
    const columnHeaderString = table.columnDescriptors
      .map((column) => `${column.name}(${column.type}) `)
      .join("| ");
    console.log("| " + columnHeaderString);

    for (const row of table.rows) {
      const columnValuesString = row.map((columnValue) => `'${columnValue}' `).join("| ");
      console.log("| " + columnValuesString);
    }
  }
}

Pełny przykład można znaleźć tutaj.

Zaawansowane scenariusze zapytań dzienników

Ustawianie limitu czasu zapytania dzienników

Wykonywanie niektórych zapytań dotyczących dzienników trwa dłużej niż 3 minuty. Domyślny limit czasu serwera wynosi 3 minuty. Limit czasu serwera można zwiększyć do maksymalnie 10 minut. W poniższym przykładzie LogsQueryOptions właściwość obiektu serverTimeoutInSeconds służy do zwiększenia limitu czasu serwera do 10 minut:

// setting optional parameters
const queryLogsOptions: LogsQueryOptions = {
  // explicitly control the amount of time the server can spend processing the query.
  serverTimeoutInSeconds: 600, // 600 seconds = 10 minutes
};

const result = await logsQueryClient.queryWorkspace(
  azureLogAnalyticsWorkspaceId,
  kustoQuery,
  { duration: Durations.twentyFourHours },
  queryLogsOptions
);

const tablesFromResult = result.tables;

Wykonywanie zapytań dotyczących wielu obszarów roboczych

To samo zapytanie dzienników można wykonać w wielu obszarach roboczych usługi Log Analytics. Oprócz zapytania Kusto wymagane są następujące parametry:

  • workspaceId — pierwszy (podstawowy) identyfikator obszaru roboczego.
  • additionalWorkspaces — Lista obszarów roboczych z wyłączeniem obszaru roboczego podanego w parametrze workspaceId . Elementy listy parametru mogą składać się z następujących formatów identyfikatorów:
    • Kwalifikowane nazwy obszarów roboczych
    • Identyfikatory obszarów roboczych
    • Identyfikatory zasobów platformy Azure

Na przykład następujące zapytanie jest wykonywane w trzech obszarach roboczych:

const queryLogsOptions: LogsQueryOptions = {
  additionalWorkspaces: ["<workspace2>", "<workspace3>"],
};

const kustoQuery = "AppEvents | limit 10";
const result = await logsQueryClient.queryWorkspace(
  azureLogAnalyticsWorkspaceId,
  kustoQuery,
  { duration: Durations.twentyFourHours },
  queryLogsOptions
);

Aby wyświetlić wyniki dla każdego obszaru roboczego, użyj TenantId kolumny , aby uporządkować wyniki lub filtrować je w zapytaniu Kusto.

Order results by TenantId

AppEvents | order by TenantId

Filtrowanie wyników według identyfikatora dzierżawy

AppEvents | filter TenantId == "<workspace2>"

Pełny przykład można znaleźć tutaj.

Uwzględnij statystyki

Aby uzyskać statystyki wykonywania zapytań dzienników, takie jak użycie procesora CPU i pamięci:

  1. LogsQueryOptions.includeQueryStatistics Ustaw właściwość na truewartość .
  2. statistics Uzyskaj dostęp do pola wewnątrz LogsQueryResult obiektu.

Poniższy przykład wyświetla czas wykonywania zapytania:

const workspaceId = "<workspace_id>";
const logsQueryClient = new LogsQueryClient(new DefaultAzureCredential());
const kustoQuery = "AzureActivity | top 10 by TimeGenerated";

const result = await logsQueryClient.queryWorkspace(
  monitorWorkspaceId,
  kustoQuery,
  { duration: Durations.oneDay },
  {
    includeQueryStatistics: true,
  }
);

const executionTime =
  result.statistics && result.statistics.query && result.statistics.query.executionTime;

console.log(
  `Results for query '${kustoQuery}', execution time: ${
    executionTime == null ? "unknown" : executionTime
  }`
);

Ponieważ struktura ładunku statistics różni się w zależności od zapytania, używany jest typ zwracany Record<string, unknown> . Zawiera on nieprzetworzoną odpowiedź JSON. Statystyki znajdują się we query właściwości JSON. Na przykład:

{
  "query": {
    "executionTime": 0.0156478,
    "resourceUsage": {...},
    "inputDatasetStatistics": {...},
    "datasetStatistics": [{...}]
  }
}

Dołączanie wizualizacji

Aby uzyskać dane wizualizacji dla zapytań dotyczących dzienników przy użyciu operatora renderowania:

  1. LogsQueryOptions.includeVisualization Ustaw właściwość na truewartość .
  2. visualization Uzyskaj dostęp do pola wewnątrz LogsQueryResult obiektu.

Na przykład:

const workspaceId = "<workspace_id>";
const logsQueryClient = new LogsQueryClient(new DefaultAzureCredential());

const result = await logsQueryClient.queryWorkspace(
    monitorWorkspaceId,
    @"StormEvents
        | summarize event_count = count() by State
        | where event_count > 10
        | project State, event_count
        | render columnchart",
    { duration: Durations.oneDay },
    {
      includeVisualization: true
    }
  );
console.log("visualization result:", result.visualization);

Ponieważ struktura ładunku visualization różni się w zależności od zapytania, używany jest typ zwracany Record<string, unknown> . Zawiera on nieprzetworzoną odpowiedź JSON. Na przykład:

{
  "visualization": "columnchart",
  "title": "the chart title",
  "accumulate": false,
  "isQuerySorted": false,
  "kind": null,
  "legend": null,
  "series": null,
  "yMin": "NaN",
  "yMax": "NaN",
  "xAxis": null,
  "xColumn": null,
  "xTitle": "x axis title",
  "yAxis": null,
  "yColumns": null,
  "ySplit": null,
  "yTitle": null,
  "anomalyColumns": null
}

Zapytanie metryk

Poniższy przykład pobiera metryki dla subskrypcji usługi Azure Metrics Advisor . Identyfikator URI zasobu musi być identyfikatorem URI zasobu, dla którego są wykonywane zapytania dotyczące metryk. Zwykle jest to format /subscriptions/<id>/resourceGroups/<rg-name>/providers/<source>/topics/<resource-name>.

Aby znaleźć identyfikator URI zasobu:

  1. Przejdź do strony zasobu w Azure Portal.
  2. W bloku Przegląd wybierz link Widok JSON .
  3. W wynikowym formacie JSON skopiuj wartość id właściwości .
import { DefaultAzureCredential } from "@azure/identity";
import { Durations, Metric, MetricsQueryClient } from "@azure/monitor-query";
import * as dotenv from "dotenv";

dotenv.config();

const metricsResourceId = process.env.METRICS_RESOURCE_ID;

export async function main() {
  const tokenCredential = new DefaultAzureCredential();
  const metricsQueryClient = new MetricsQueryClient(tokenCredential);

  if (!metricsResourceId) {
    throw new Error("METRICS_RESOURCE_ID must be set in the environment for this sample");
  }

  const iterator = metricsQueryClient.listMetricDefinitions(metricsResourceId);
  let result = await iterator.next();
  let metricNames: string[] = [];
  for await (const result of iterator) {
    console.log(` metricDefinitions - ${result.id}, ${result.name}`);
    if (result.name) {
      metricNames.push(result.name);
    }
  }
  const firstMetricName = metricNames[0];
  const secondMetricName = metricNames[1];
  if (firstMetricName && secondMetricName) {
    console.log(`Picking an example metric to query: ${firstMetricName} and ${secondMetricName}`);
    const metricsResponse = await metricsQueryClient.queryResource(
      metricsResourceId,
      [firstMetricName, secondMetricName],
      {
        granularity: "PT1M",
        timespan: { duration: Durations.fiveMinutes },
      }
    );

    console.log(
      `Query cost: ${metricsResponse.cost}, interval: ${metricsResponse.granularity}, time span: ${metricsResponse.timespan}`
    );

    const metrics: Metric[] = metricsResponse.metrics;
    console.log(`Metrics:`, JSON.stringify(metrics, undefined, 2));
    const metric = metricsResponse.getMetricByName(firstMetricName);
    console.log(`Selected Metric: ${firstMetricName}`, JSON.stringify(metric, undefined, 2));
  } else {
    console.error(`Metric names are not defined - ${firstMetricName} and ${secondMetricName}`);
  }
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
  process.exit(1);
});

W poprzednim przykładzie wyniki metricsResponse metryk są uporządkowane zgodnie z kolejnością, w której użytkownik określa nazwy metryk w metricNames argumencie tablicy queryResource dla funkcji. Jeśli użytkownik określi [firstMetricName, secondMetricName]wartość , wynik polecenia firstMetricName pojawi się przed wynikiem w secondMetricName elemecie metricResponse.

Obsługa odpowiedzi na zapytanie metryk

Funkcja metrics queryResource zwraca QueryMetricsResult obiekt. Obiekt QueryMetricsResult zawiera właściwości, takie jak lista Metricobiektów typizowane, interval, namespacei timespan. Dostęp Metric do listy obiektów można uzyskać za pomocą metrics właściwości . Każdy Metric obiekt na tej liście zawiera listę TimeSeriesElement obiektów. Każdy TimeSeriesElement zawiera data właściwości i metadataValues . W formie wizualizacji hierarchia obiektów odpowiedzi przypomina następującą strukturę:

QueryMetricsResult
|---cost
|---timespan (of type `QueryTimeInterval`)
|---granularity
|---namespace
|---resourceRegion
|---metrics (list of `Metric` objects)
    |---id
    |---type
    |---name
    |---unit
    |---displayDescription
    |---errorCode
    |---timeseries (list of `TimeSeriesElement` objects)
        |---metadataValues
        |---data (list of data points represented by `MetricValue` objects)
            |---timeStamp
            |---average
            |---minimum
            |---maximum
            |---total
            |---count
|---getMetricByName(metricName): Metric | undefined (convenience method)

Przykład obsługi odpowiedzi

import { DefaultAzureCredential } from "@azure/identity";
import { Durations, Metric, MetricsQueryClient } from "@azure/monitor-query";
import * as dotenv from "dotenv";
dotenv.config();

const metricsResourceId = process.env.METRICS_RESOURCE_ID;
export async function main() {
  const tokenCredential = new DefaultAzureCredential();
  const metricsQueryClient = new MetricsQueryClient(tokenCredential);

  if (!metricsResourceId) {
    throw new Error(
      "METRICS_RESOURCE_ID for an Azure Metrics Advisor subscription must be set in the environment for this sample"
    );
  }

  console.log(`Picking an example metric to query: MatchedEventCount`);

  const metricsResponse = await metricsQueryClient.queryResource(
    metricsResourceId,
    ["MatchedEventCount"],
    {
      timespan: {
        duration: Durations.fiveMinutes,
      },
      granularity: "PT1M",
      aggregations: ["Count"],
    }
  );

  console.log(
    `Query cost: ${metricsResponse.cost}, granularity: ${metricsResponse.granularity}, time span: ${metricsResponse.timespan}`
  );

  const metrics: Metric[] = metricsResponse.metrics;
  for (const metric of metrics) {
    console.log(metric.name);
    for (const timeseriesElement of metric.timeseries) {
      for (const metricValue of timeseriesElement.data!) {
        if (metricValue.count !== 0) {
          console.log(`There are ${metricValue.count} matched events at ${metricValue.timeStamp}`);
        }
      }
    }
  }
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
  process.exit(1);
});

Pełny przykład można znaleźć tutaj.

Wykonywanie zapytań dotyczących metryk dla wielu zasobów

Aby wysłać zapytanie o metryki dla wielu zasobów platformy Azure w jednym żądaniu, użyj MetricsQueryClient.queryResources metody . Ta metoda:

  • Wywołuje inny interfejs API niż MetricsQueryClient metody.
  • Wymaga regionalnego punktu końcowego podczas tworzenia klienta. Na przykład "https://westus3.metrics.monitor.azure.com".

Każdy zasób platformy Azure musi znajdować się w:

  • Ten sam region co punkt końcowy określony podczas tworzenia klienta.
  • Ta sama subskrypcja platformy Azure.

Ponadto należy podać przestrzeń nazw metryki zawierającej metryki do odpytowania. Aby uzyskać listę przestrzeni nazw metryk, zobacz Obsługiwane metryki i kategorie dzienników według typu zasobu.

let resourceIds: string[] = [
  "/subscriptions/0000000-0000-000-0000-000000/resourceGroups/test/providers/Microsoft.OperationalInsights/workspaces/test-logs",
  "/subscriptions/0000000-0000-000-0000-000000/resourceGroups/test/providers/Microsoft.OperationalInsights/workspaces/test-logs2",
];
let metricsNamespace: string = "<YOUR_METRICS_NAMESPACE>";
let metricNames: string[] = ["requests", "count"];
const batchEndPoint: string = "<YOUR_METRICS_ENDPOINT>"; //for example, https://eastus.metrics.monitor.azure.com/

const credential = new DefaultAzureCredential();
const metricsQueryClient: MetricsQueryClient = new MetricsQueryClient(
  batchEndPoint,
  credential
);

const result: : MetricsQueryResult[] = await metricsQueryClient.queryResources(
  resourceIds,
  metricsNamespace,
  metricNames
);

Aby uzyskać spis metryk i wymiarów dostępnych dla każdego typu zasobu platformy Azure, zobacz Obsługiwane metryki w usłudze Azure Monitor.

Rozwiązywanie problemów

Aby zdiagnozować różne scenariusze awarii, zobacz przewodnik rozwiązywania problemów.

Następne kroki

Aby dowiedzieć się więcej na temat usługi Azure Monitor, zobacz dokumentację usługi Azure Monitor.

Współtworzenie

Jeśli chcesz współtworzyć tę bibliotekę, przeczytaj przewodnik współtworzenia , aby dowiedzieć się więcej na temat tworzenia i testowania kodu.

Testy tego modułu są kombinacją testów na żywo i testów jednostkowych, które wymagają posiadania wystąpienia usługi Azure Monitor. Aby wykonać testy, należy uruchomić następujące polecenie:

  1. rush update
  2. rush build -t @azure/monitor-query
  3. cd into sdk/monitor/monitor-query
  4. sample.env Kopiowanie pliku do.env
  5. .env Otwórz plik w edytorze i wypełnij wartości.
  6. npm run test.

Aby uzyskać więcej informacji, zobacz nasz folder testów .

Wrażenia