你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 JavaScript 的 Azure Monitor 查询日志客户端库 - 版本 1.0.0

Azure Monitor 查询日志客户端库用于针对 Azure Monitor 的日志数据平台执行只读查询:

  • 日志 - 从受监控的资源中收集和组织日志和性能数据。 来自不同来源的数据(例如 Azure 服务中的平台日志、虚拟机代理中的日志和性能数据以及应用中的使用情况和性能数据)可以合并到单个 Azure Log Analytics 工作区中。 可以使用 Kusto 查询语言一起分析各种数据类型。

从咨询⚠迁移 @azure/monitor-query ️

查看 迁移指南 ,了解如何将应用程序代码从原始 @azure/monitor-query 包更新到库的 @azure/monitor-query-logs 详细说明。

资源:

入门指南

支持的环境

有关详细信息,请参阅我们的 支持政策

先决条件

安装软件包

使用 npm 安装适用于 JavaScript 的 Azure Monitor 查询客户端库:

npm install --save @azure/monitor-query-logs

创建客户端

需要经过身份验证的客户端才能查询日志。 为了进行身份验证,以下示例使用 @azure/identity 包中的 DefaultAzureCredential

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

const credential = new DefaultAzureCredential();

// Create a LogsQueryClient
const logsQueryClient = new LogsQueryClient(credential);

为 Azure 主权云配置客户端

默认情况下,库的客户端配置为使用 Azure 公有云。 若要改用主权云,在实例化客户端时提供正确的终结点和受众值。 例如:

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

const credential = new DefaultAzureCredential();

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

执行查询

有关日志查询的示例,请参阅 示例部分

重要概念

记录查询速率限制和限制

当请求速率过高时,Log Analytics 服务将应用限制。 Kusto 查询也会应用限制,例如返回的最大行数。 有关更多信息,请参阅 查询 API

例子

日志查询

可用于 LogsQueryClient 使用 Kusto 查询语言查询 Log Analytics 工作区。 可以 timespan.duration 指定为 ISO 8601 持续时间格式的字符串。 您可以使用 Durations 为一些常用的 ISO 8601 持续时间提供的常量。

可以通过 Log Analytics 工作区 ID 或 Azure 资源 ID 查询日志。 结果以包含行集合的表的形式返回。

以工作区为中心的日志查询

要按工作区 ID 查询,请使用以下 LogsQueryClient.queryWorkspace 方法:

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

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

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

if (result.status === LogsQueryResultStatus.Success) {
  const tablesFromResult = 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);
  }
}

以资源为中心的日志查询

以下示例演示如何直接从 Azure 资源查询日志。 此处使用 queryResource 该方法并传入 Azure 资源 ID。 例如,/subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/{resource-provider}/{resource-type}/{resource-name}

若要查找资源 ID,请执行以下操作:

  1. 导航到 Azure 门户中的资源页。
  2. 在“ 概述 ”边栏选项卡中,选择“ JSON 视图 ”链接。
  3. 在生成的 JSON 中,复制属性的值 id
import { DefaultAzureCredential } from "@azure/identity";
import { LogsQueryClient, Durations, LogsQueryResultStatus } from "@azure/monitor-query-logs";

const logsResourceId = "<the Resource Id for your logs resource>";

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

const kustoQuery = `MyTable_CL | summarize count()`;

console.log(`Running '${kustoQuery}' over the last One Hour`);
const queryLogsOptions = {
  // 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,
);

console.log(`Results for query '${kustoQuery}'`);

if (result.status === LogsQueryResultStatus.Success) {
  const tablesFromResult = 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);
  }
}

处理日志查询响应

函数 queryWorkspace of LogsQueryClient 返回一个 LogsQueryResult 对象。 对象类型可以是 LogsQuerySuccessfulResultLogsQueryPartialResult。 下面是响应的层次结构:

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

例如,若要处理包含表的响应:

function processTables(tablesFromResult) {
  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);
    }
  }
}

可以 在此处找到完整的示例。

批处理日志查询

以下示例演示如何使用批处理查询 API 同时发送多个查询。 查询可以表示为对象列表 BatchQuery

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

const monitorWorkspaceId = "<workspace_id>";

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

处理日志批处理查询响应

函数 queryBatch of LogsQueryClient 返回一个 LogsQueryBatchResult 对象。 LogsQueryBatchResult 包含具有以下可能类型的对象列表:

  • LogsQueryPartialResult
  • LogsQuerySuccessfulResult
  • LogsQueryError

下面是响应的层次结构:

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

例如,以下代码处理批处理日志查询响应:

import { LogsQueryResultStatus } from "@azure/monitor-query-logs";

async function processBatchResult(result, queriesBatch) {
  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++;
  }
}
function processTables(tablesFromResult) {
  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);
    }
  }
}

可以 在此处找到完整的示例。

高级日志查询方案

设置日志查询超时

某些日志查询的执行时间超过 3 分钟。 默认服务器超时为 3 分钟。 可以将服务器超时增加到最多 10 分钟。 在以下示例中, LogsQueryOptions 对象的属性 serverTimeoutInSeconds 用于将服务器超时增加到 10 分钟:

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

const azureLogAnalyticsWorkspaceId = "<workspace_id>";

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

const kqlQuery = "AppEvents | project TimeGenerated, Name, AppRoleInstance | limit 1";

// setting optional parameters
const queryLogsOptions = {
  // 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,
  kqlQuery,
  { duration: Durations.twentyFourHours },
  queryLogsOptions,
);

const status = result.status;

查询多个工作区

可以在多个 Log Analytics 工作区中执行相同的日志查询。 除了 Kusto 查询之外,还需要以下参数:

  • workspaceId - 第一个(主要)工作区 ID。
  • additionalWorkspaces - 工作区列表,不包括参数中提供的 workspaceId 工作区。 参数的列表项可以包含以下标识符格式:
    • 限定的工作区名称
    • 工作区 ID
    • Azure 资源 ID

例如,以下查询在三个工作区中执行:

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

const azureLogAnalyticsWorkspaceId = "<workspace_id>";

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

const kqlQuery = "AppEvents | project TimeGenerated, Name, AppRoleInstance | limit 1";

// setting optional parameters
const queryLogsOptions = {
  additionalWorkspaces: ["<workspace2>", "<workspace3>"],
};

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

const status = result.status;

若要查看每个工作区的结果,请使用该 TenantId 列对结果进行排序或在 Kusto 查询中筛选结果。

按 TenantId 对结果进行排序

AppEvents | order by TenantId

按 TenantId 筛选结果

AppEvents | filter TenantId == "<workspace2>"

可以 在此处找到完整的示例。

包括统计信息

若要获取日志查询执行统计信息,例如 CPU 和内存消耗:

  1. LogsQueryOptions.includeQueryStatistics 属性设置为 true
  2. statistics访问对象内的LogsQueryResult字段。

以下示例打印查询执行时间:

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

const monitorWorkspaceId = "<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,
  },
);

console.log(`Results for query '${kustoQuery}'`);

由于有效负载的结构 statistics 因查询而异,因此 Record<string, unknown> 使用返回类型。 它包含原始 JSON 响应。 统计信息位于 JSON 的属性中 query 。 例如:

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

包括可视化效果

要使用 render 运算符获取日志查询的可视化数据,请执行以下作:

  1. LogsQueryOptions.includeVisualization 属性设置为 true
  2. visualization访问对象内的LogsQueryResult字段。

例如:

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

const monitorWorkspaceId = "<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);

由于有效负载的结构 visualization 因查询而异,因此 Record<string, unknown> 使用返回类型。 它包含原始 JSON 响应。 例如:

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

故障排除

要诊断各种故障场景,请参阅 故障排除指南

后续步骤

若要了解有关 Azure Monitor 的详细信息,请参阅 Azure Monitor 服务文档

贡献

若要参与此库,请阅读 贡献指南 了解有关如何生成和测试代码的详细信息。

本模块的测试是实时测试和单元测试的混合体,需要拥有 Azure Monitor 实例。 若要执行测试,需要运行:

  1. rush update
  2. rush build -t @azure/monitor-query-logs
  3. cd into sdk/monitor/monitor-query
  4. sample.env 文件复制到 .env
  5. .env在编辑器中打开文件并填写值。
  6. npm run test

有关更多详细信息,请查看我们的 tests 文件夹。