Klientská knihovna dotazů Azure Monitoru pro JavaScript – verze 1.0.3

Klientská knihovna dotazů služby Azure Monitor se používá ke spouštění dotazů jen pro čtení na dvou datových platformách služby Azure Monitor:

  • Protokoly – shromažďuje a uspořádá data protokolů a výkonu z monitorovaných prostředků. Data z různých zdrojů, jako jsou protokoly platformy ze služeb Azure, data protokolů a výkonu od agentů virtuálních počítačů a data o využití a výkonu z aplikací, je možné konsolidovat do jednoho pracovního prostoru služby Azure Log Analytics. Různé datové typy je možné analyzovat společně pomocí dotazovací jazyk Kusto.
  • Metriky – shromažďuje číselná data z monitorovaných prostředků do databáze časových řad. Metriky jsou číselné hodnoty, které se shromažďují v pravidelných intervalech a popisují určité aspekty systému v určitém čase. Metriky jsou jednoduché a jsou schopné podporovat scénáře téměř v reálném čase, takže jsou užitečné zejména pro upozorňování a rychlé zjišťování problémů.

Zdroje a prostředky:

Začínáme

Podporovaná prostředí

  • LtS verze Node.js
  • Nejnovější verze prohlížečů Safari, Chrome, Edge a Firefox

Další podrobnosti najdete v našich zásadách podpory.

Požadavky

Instalace balíčku

Nainstalujte klientskou knihovnu dotazů Azure Monitoru pro JavaScript pomocí npm:

npm install @azure/monitor-query

Vytvoření klienta

K dotazování protokolů nebo metrik se vyžaduje ověřený klient. K ověření použije následující příklad DefaultAzureCredential z balíčku @azure/identity .

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

const credential = new DefaultAzureCredential();

const logsQueryClient = new LogsQueryClient(credential);
// or
const metricsQueryClient = new MetricsQueryClient(credential);

Spusťte dotaz.

Příklady dotazů na protokoly a metriky najdete v části Příklady .

Klíčové koncepty

Protokoluje omezení rychlosti dotazů a omezování.

Služba Log Analytics použije omezování v případě, že je frekvence požadavků příliš vysoká. Omezení, jako je například maximální počet vrácených řádků, se použijí také u dotazů Kusto. Další informace najdete v tématu Rozhraní API pro dotazy.

Struktura dat metrik

Každá sada hodnot metrik je časová řada s následujícími charakteristikami:

  • Čas shromáždění hodnoty
  • Prostředek přidružený k hodnotě
  • Obor názvů, který funguje jako kategorie metriky
  • Název metriky
  • Samotná hodnota
  • Některé metriky můžou mít více dimenzí, jak je popsáno v tématu multidimenzionální metriky. Vlastní metriky můžou mít až 10 dimenzí.

Příklady

Dotaz na protokoly

Můžete LogsQueryClient použít k dotazování pracovního prostoru služby Log Analytics pomocí dotazovací jazyk Kusto. Je timespan.duration možné zadat jako řetězec ve formátu doby trvání ISO 8601. Můžete použít Durations konstanty poskytované pro některé běžně používané doby trvání ISO 8601.

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));

Zpracování odpovědi na dotaz na protokoly

Funkce queryWorkspace vrátí LogsQueryClientLogsQueryResult objekt . Typ objektu může být LogsQuerySuccessfulResult nebo LogsQueryPartialResult. Tady je hierarchie odpovědi:

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

Pokud chcete například zpracovat odpověď s tabulkami:

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);
    }
  }
}

Úplnou ukázku najdete tady.

Dotaz na dávkové protokoly

Následující příklad ukazuje odesílání více dotazů najednou pomocí rozhraní API dávkových dotazů. Dotazy mohou být reprezentovány jako seznam BatchQuery objektů.

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);
    }
  }
}

Zpracování odpovědi na dávkové dotazy na protokoly

Funkce queryBatch vrátí LogsQueryClientLogsQueryBatchResult objekt . LogsQueryBatchResult obsahuje seznam objektů s následujícími možnými typy:

  • LogsQueryPartialResult
  • LogsQuerySuccessfulResult
  • LogsQueryError

Tady je hierarchie odpovědi:


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")

Například následující kód zpracovává odpověď dotazu na dávkové protokoly:

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);
    }
  }
}

Úplnou ukázku najdete tady.

Informace o omezování požadavků na úrovni služby Log Analytics najdete v tématu Omezení přenosové rychlosti.

Pokročilé scénáře dotazů na protokoly

Nastavení časového limitu dotazu na protokoly

Provedení některých dotazů na protokoly trvá déle než 3 minuty. Výchozí časový limit serveru je 3 minuty. Časový limit serveru můžete prodloužit až na 10 minut. V následujícím příkladu se vlastnost objektu LogsQueryOptionsserverTimeoutInSeconds používá ke zvýšení časového limitu serveru na 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;

Dotazování na více pracovních prostorů

Stejný dotaz na protokoly je možné spustit napříč několika pracovními prostory služby Log Analytics. Kromě dotazu Kusto se vyžadují následující parametry:

  • workspaceId – ID prvního (primárního) pracovního prostoru.
  • additionalWorkspaces – Seznam pracovních prostorů s výjimkou pracovního prostoru zadaného v parametru workspaceId . Položky seznamu parametru se mohou skládat z následujících formátů identifikátorů:
    • Kvalifikované názvy pracovních prostorů
    • ID pracovního prostoru
    • ID prostředků Azure

Například následující dotaz se spustí ve třech pracovních prostorech:

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

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

Pokud chcete zobrazit výsledky pro každý pracovní prostor, použijte TenantId sloupec k seřazení výsledků nebo k jejich filtrování v dotazu Kusto.

Seřazení výsledků podle Id tenanta

AppEvents | order by TenantId

Filtrovat výsledky podle Id tenanta

AppEvents | filter TenantId == "<workspace2>"

Úplnou ukázku najdete tady.

Zahrnout statistiky

Pokud chcete získat statistiky provádění dotazů na protokoly, jako je využití procesoru a paměti:

  1. LogsQueryOptions.includeQueryStatistics Nastavte vlastnost na true.
  2. Přístup k statistics poli uvnitř objektu LogsQueryResult

Následující příklad vytiskne čas provádění dotazu:

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
    }`
  );

Vzhledem k tomu, že struktura statistics datové části se liší podle dotazu, použije se návratový Record<string, unknown> typ. Obsahuje nezpracovanou odpověď JSON. Statistiky se nacházejí ve query vlastnosti JSON. Příklad:

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

Zahrnout vizualizaci

Získání vizualizačních dat pro dotazy na protokoly pomocí operátoru vykreslování:

  1. LogsQueryOptions.includeVisualization Nastavte vlastnost na true.
  2. Přístup k visualization poli uvnitř objektu LogsQueryResult

Příklad:

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);

Vzhledem k tomu, že struktura visualization datové části se liší podle dotazu, použije se návratový Record<string, unknown> typ. Obsahuje nezpracovanou odpověď JSON. Příklad:

{
  "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
}

Dotaz na metriky

Následující příklad získá metriky pro předplatné Azure Metrics Advisor . Identifikátor URI prostředku musí být identifikátor URI prostředku, pro který se metriky dotazují. Obvykle je ve formátu /subscriptions/<id>/resourceGroups/<rg-name>/providers/<source>/topics/<resource-name>.

Identifikátor URI prostředku najdete následovně:

  1. V Azure Portal přejděte na stránku prostředku.
  2. V okně Přehled vyberte odkaz Zobrazení JSON .
  3. Ve výsledném formátu JSON zkopírujte hodnotu id vlastnosti.
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);
});

V předchozím příkladu jsou výsledky metriky seřazeny metricsResponse podle pořadí, ve kterém uživatel určuje názvy metrik v argumentu metricNames matice pro queryResource funkci. Pokud uživatel zadá [firstMetricName, secondMetricName], zobrazí se výsledek pro firstMetricName před výsledkem pro secondMetricName v .metricResponse

Zpracování odpovědi na dotazy na metriky

Funkce metrics queryResource vrátí QueryMetricsResult objekt. Objekt QueryMetricsResult obsahuje vlastnosti, jako je seznam Metricobjektů intervalnamespacetypu , a timespan. Seznam Metric objektů je přístupný pomocí metrics vlastnosti . Každý Metric objekt v tomto seznamu obsahuje seznam TimeSeriesElement objektů. Každý TimeSeriesElement obsahuje data vlastnosti a metadataValues . Ve vizuální podobě se hierarchie objektů odpovědi podobá následující struktuře:

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)

Příklad zpracování odpovědi

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);
});

Úplnou ukázku najdete tady.

Řešení potíží

protokolování

Povolení protokolování může pomoct odhalit užitečné informace o selháních. Pokud chcete zobrazit protokol požadavků a odpovědí HTTP, nastavte proměnnou AZURE_LOG_LEVEL prostředí na info. Případně je možné protokolování povolit za běhu voláním setLogLevel v :@azure/logger

import { setLogLevel } from "@azure/logger";

setLogLevel("info");

Podrobné pokyny k povolení protokolů najdete v dokumentaci k @azure/protokolovacímu balíčku.

Další kroky

Další informace o službě Azure Monitor najdete v dokumentaci ke službě Azure Monitor.

Přispívání

Pokud chcete přispívat do této knihovny, přečtěte si prosím průvodce přispívání , kde se dozvíte více o tom, jak sestavit a otestovat kód.

Testy tohoto modulu jsou kombinací živých testů a testů jednotek, které vyžadují, abyste měli instanci Služby Azure Monitor. Pokud chcete testy spustit, musíte spustit:

  1. rush update
  2. rush build -t @azure/monitor-query
  3. cd into sdk/monitor/monitor-query
  4. Zkopírujte soubor do sample.env.env
  5. .env Otevřete soubor v editoru a vyplňte hodnoty.
  6. npm run test.

Další podrobnosti najdete v naší složce testů .

Imprese