使用 Application Insights 监视 Node.js 服务和应用
Application Insights 会在部署后对组件进行监视,以便发现性能问题和其他问题。 可以将 Application Insights 用于 Node.js 服务,不管这些服务是托管在数据中心、Azure VM 和 Web 应用中,还是在其他公有云中。
若要接收、存储和探索监视数据,请将 SDK 包括到代码中。 然后在 Azure 中设置相应的 Application Insights 资源。 SDK 会将数据发送到该资源进行进一步的分析和探索。
Node.js 客户端库可以自动监视传入和传出的 HTTP 请求、异常和某些系统指标。 从 0.20 版开始,客户端库也可监视某些常用的第三方程序包,例如 MongoDB、MySQL、Redis。
所有与传入 HTTP 请求相关的事件都会进行关联,以加快故障排除速度。
可以使用 TelemetryClient API 手动检测和监视应用和系统的其他方面。 本文后面会更详细地介绍 TelemetryClient API。
注意
以下文档依赖于 Application Insights 经典 API。 Application Insights 的长期计划是使用 OpenTelemetry 收集数据。 有关详细信息,请参阅为 .NET、Node.js、Python 和 Java 应用程序启用 Azure Monitor OpenTelemetry 和我们的 OpenTelemetry 路线图。 迁移指导适用于 .NET、Node.js 和 Python。
开始使用
请完成以下任务,为应用或服务设置监视。
先决条件
开始之前,请确保拥有 Azure 订阅,否则请获取一个新的试用版。 如果组织已经拥有 Azure 订阅,管理员可以按照这些说明将你添加到该订阅。
设置 Application Insights 资源
- 登录到 Azure 门户。
- 创建 Application Insights 资源。
设置 Node.js 客户端库
将 SDK 包括到应用中,使之能够收集数据。
从新资源复制资源的连接字符串。 Application Insights 使用连接字符串将数据映射到 Azure 资源。 必须在环境变量或代码中指定连接字符串,然后 SDK 才能使用该连接字符串。
通过
package.json
将 Node.js 客户端库添加到应用的依赖项。 从应用的根文件夹,运行:npm install applicationinsights --save
注意
如果使用 TypeScript,请勿安装单独的“typings”包。 此 NPM 包包含内置的 typings。
将该库显式加载到代码中。 由于 SDK 将检测注入到许多其他库中,请尽早加载该库,甚至应赶在其他
require
语句之前加载。let appInsights = require('applicationinsights');
也可通过环境变量
APPLICATIONINSIGHTS_CONNECTION_STRING
来提供连接字符串,不必手动将其传递给setup()
或new appInsights.TelemetryClient()
。 这种做法允许将连接字符串脱离已提交的源代码,因此可以为不同的环境指定不同的连接字符串。 若要手动进行配置,请调用appInsights.setup('[your connection string]');
。有关其他配置选项,请参阅以下各节。
可以设置
appInsights.defaultClient.config.disableAppInsights = true
,尝试在不发送遥测的情况下使用 SDK。开始通过调用
appInsights.start();
自动收集和发送数据。
注意
在使用 Application Insights 检测的过程中,我们会收集诊断数据并将其发送给 Microsoft。 这些数据可帮助我们运行和改进 Application Insights。 可以选择禁用非基本数据的收集。 了解详细信息。
监视应用
SDK 会自动收集有关 Node.js 运行时和一些常见第三方模块的遥测。 请使用应用程序生成部分此类数据。
然后,在 Azure 门户中转到此前创建的 Application Insights 资源。 在“概览时间线”中,查找前面的几个数据点。 若要查看更多详细数据,请在图表中选择不同的组件。
若要查看应用的已发现拓扑,可以使用应用程序映射。
无数据
由于 SDK 对要提交的数据进行批处理,项目在门户中显示之前可能会有一段延迟。 如果在资源中看不到数据,可尝试下面的部分修复手段:
- 继续使用应用程序。 通过更多操作生成更多遥测。
- 在门户资源视图中选择“刷新”。 图表会定期自行刷新,但手动刷新会强制图表立刻刷新。
- 验证所需传出端口是否已打开。
- 使用搜索查找特定事件。
- 查看常见问题。
基本用法
对于开箱即用的 HTTP 请求集合、受欢迎的第三方库事件、未经处理的异常和系统指标:
let appInsights = require("applicationinsights");
appInsights.setup("[your connection string]").start();
注意
如果在环境变量 APPLICATIONINSIGHTS_CONNECTION_STRING
中设置连接字符串,则无需使用参数即可调用 .setup()
。 这样就可以轻松地针对不同环境使用不同的连接字符串。
加载其他包之前,请尽早在脚本中加载 Application Insights 库 require("applicationinsights")
。 此步骤是必需的,这样 Application Insights 库才能为跟踪准备更高版本的包。 如果与执行类似准备的其他库发生冲突,请尝试稍后加载 Application Insights 库。
由于 JavaScript 处理回调的方式,需要执行额外的工作,以跟踪跨外部依赖项和更高版本回调的请求。 默认情况下,此额外跟踪处于启用状态。 通过调用 setAutoDependencyCorrelation(false)
将其禁用,如 SDK 配置 部分所述。
从版本 0.22 之前的版本进行迁移
这些是版本 0.22 及更高版本之前的版本之间的重大更改。 这些更改旨在与其他 Application Insights SDK 保持一致并允许将来进行扩展。
通常,可以通过以下操作进行迁移:
- 用
appInsights.defaultClient
替换对appInsights.client
的引用。 - 用
new appInsights.TelemetryClient()
替换对appInsights.getClient()
的引用。 - 将所有参数替换为 client.track* 方法,其中有一个包含命名属性的对象用作参数。 有关每种类型的遥测的例外对象,请参阅 IDE 的内置类型提示或 TelemetryTypes。
如果在不将 SDK 配置函数链接到 appInsights.setup()
的情况下访问这些函数,现在可以在 appInsights.Configurations
中找到这些函数。 例如 appInsights.Configuration.setAutoCollectDependencies(true)
。 查看下一节中对默认配置所做的更改。
SDK 配置
appInsights
对象提供了许多配置方法。 以下代码片段中列出了这些方法及其默认值。
let appInsights = require("applicationinsights");
appInsights.setup("<connection_string>")
.setAutoDependencyCorrelation(true)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(true, true)
.setAutoCollectExceptions(true)
.setAutoCollectDependencies(true)
.setAutoCollectConsole(true)
.setUseDiskRetryCaching(true)
.setSendLiveMetrics(false)
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI)
.start();
若要让服务中的事件完全相关联,请确保设置 .setAutoDependencyCorrelation(true)
。 设置此选项以后,SDK 即可在 Node.js 中跨异步回调跟踪上下文。
请在 IDE 的内置类型提示或 applicationinsights.ts 中查看其说明,了解详细信息和可选的辅助参数。
注意
默认情况下,setAutoCollectConsole
配置为排除对 console.log
(以及其他控制台方法)的调用。 将只收集对受支持的第三方记录器(例如 winston 和 bunyan)的调用。 你可以通过使用 setAutoCollectConsole(true, true)
将此行为更改为包括对 console
方法的调用。
采样
默认情况下,SDK 会将收集的所有数据发送到 Application Insights 服务。 如果要启用采样以减少数据量,请在客户端的 config
对象上设置 samplingPercentage
字段。 将 samplingPercentage
设置为 100(默认值)表示将发送所有数据,设置为 0 则表示不会发送任何内容。
如果使用自动关联,则会将与单个请求关联的所有数据作为一个单元包括或排除。
若要启用采样,请添加以下代码:
const appInsights = require("applicationinsights");
appInsights.setup("<connection_string>");
appInsights.defaultClient.config.samplingPercentage = 33; // 33% of all telemetry will be sent to Application Insights
appInsights.start();
多组件应用程序的多个角色
在某些情况下,应用程序可能包含多个组件,你希望使用相同的连接字符串对所有这些组件进行检测。 你希望仍将这些组件视为门户中的单独单元,就像它们使用的是单独的连接字符串一样。 例如,应用程序映射上的单独节点。 需要手动配置 RoleName
字段,以便将一个组件的遥测与发送到 Application Insights 资源的其他组件区分开来。
使用以下代码设置 RoleName
字段:
const appInsights = require("applicationinsights");
appInsights.setup("<connection_string>");
appInsights.defaultClient.context.tags[appInsights.defaultClient.context.keys.cloudRole] = "MyRoleName";
appInsights.start();
浏览器 SDK 加载程序
注意
以公共预览版的形式提供。 Azure 预览版补充使用条款
可以在配置中通过 JavaScript (Web) SDK 加载程序脚本注入为节点服务器启用自动 Web 检测。
let appInsights = require("applicationinsights");
appInsights.setup("<connection_string>")
.enableWebInstrumentation(true)
.start();
或设置环境变量 APPLICATIONINSIGHTS_WEB_INSTRUMENTATION_ENABLED = true
为节点服务器启用自动 Web 检测。
满足以下所有要求时,将对节点服务器响应启用 Web 检测:
- 响应的状态代码为
200
。 - 响应方法为
GET
。 - 服务器响应具有
Content-Type
html。 - 服务器响应同时包含
<head>
和</head>
标记。 - 如果响应已压缩,则它必须只有一种
Content-Encoding
类型,并且编码类型必须是gzip
、br
或deflate
中的一种。 - 响应不包含当前的 /backup Web 检测 CDN 终结点。 (此处为当前和备份 Web 检测 CDN 终结点)
可以通过设置环境变量 APPLICATIONINSIGHTS_WEB_INSTRUMENTATION_SOURCE = "web Instrumentation CDN endpoints"
来更改 Web 检测 CDN 终结点。
可以通过设置环境变量 APPLICATIONINSIGHTS_WEB_INSTRUMENTATION_CONNECTION_STRING = "web Instrumentation connection string"
来更改 Web 检测连接字符串
注意
Web 检测可能会减慢服务器响应时间,尤其是在响应大小较大或响应已压缩时。 对于应用某些中间层的情况,可能会导致 Web 检测不起作用,并且将返回原始响应。
自动第三方检测
为了跨异步调用跟踪上下文,某些第三方库(如 MongoDB 和 Redis)需要进行一些更改。 默认情况下,Application Insights 将使用 diagnostic-channel-publishers
以对其中部分库进行猴式修补。 可通过设置 APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL
环境变量禁用此功能。
注意
设置该环境变量后,事件可能不会与正确的操作正确关联。
可以通过将 APPLICATION_INSIGHTS_NO_PATCH_MODULES
环境变量设置为要禁用的包的逗号分隔列表来禁用单个猴子补丁。 例如,使用 APPLICATION_INSIGHTS_NO_PATCH_MODULES=console,redis
以避免修补 console
和 redis
包。
目前已检测到 9 个包:bunyan
、console
、mongodb
、mongodb-core
、mysql
、redis
、winston
、pg
和 pg-pool
。 有关修补这些包的哪个确切版本的信息,请访问 diagnostic-channel-publishers 自述文件。
bunyan
、winston
和 console
补丁会根据是否启用 setAutoCollectConsole
生成 Application Insights 跟踪事件。 其余补丁会根据是否启用 setAutoCollectDependencies
生成 Application Insights 依赖项事件。
实时指标
若要允许将实时指标从应用发送到 Azure,请使用 setSendLiveMetrics(true)
。 目前,不支持在门户中筛选实时指标。
扩展指标
注意
1.4.0 版本中添加了发送扩展本机指标的功能。
若要允许将扩展本机指标从应用发送到 Azure,请安装单独的本机指标包。 SDK 会在安装后自动加载,并开始收集 Node.js 原生指标。
npm install applicationinsights-native-metrics
目前,本机指标包会自动收集垃圾回收 CPU 时间、事件循环计时和堆使用情况:
- 垃圾回收:每种类型的垃圾回收所用的 CPU 时间,以及每种类型出现的次数。
- 事件循环:发生了多少个计时周期,以及总共花费了多少 CPU 时间。
- 堆与非堆:应用的内存使用量有多少位于堆或非堆中。
分布式跟踪模式
默认情况下,SDK 会发送被其他应用程序或服务理解的标头,可通过 Application Insights SDK 检测到此类应用程序或服务。 除了现有的 AI 标头,还可以启用 W3C 跟踪上下文标头的发送和接收。 这样就不会中断与任何现有旧服务的关联。 通过启用 W3C 标头,可将应用与未通过 Application Insights 检测的其他服务关联,但会采用这一 W3C 标准。
const appInsights = require("applicationinsights");
appInsights
.setup("<your connection string>")
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)
.start()
TelemetryClient API
有关 TelemetryClient API 的完整说明,请参阅用于处理自定义事件和指标的 Application Insights API。
可以使用 Node.js 的 Application Insights 客户端库跟踪任何请求、事件、指标或异常。 以下代码示例演示了部分可用 API:
let appInsights = require("applicationinsights");
appInsights.setup().start(); // assuming connection string in env var. start() can be omitted to disable any non-custom data
let client = appInsights.defaultClient;
client.trackEvent({name: "my custom event", properties: {customProperty: "custom property value"}});
client.trackException({exception: new Error("handled exceptions can be logged with this method")});
client.trackMetric({name: "custom metric", value: 3});
client.trackTrace({message: "trace message"});
client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:231, resultCode:0, success: true, dependencyTypeName: "ZSQL"});
client.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true});
let http = require("http");
http.createServer( (req, res) => {
client.trackNodeHttpRequest({request: req, response: res}); // Place at the beginning of your request handler
});
跟踪依赖项
使用以下代码跟踪依赖项:
let appInsights = require("applicationinsights");
let client = new appInsights.TelemetryClient();
var success = false;
let startTime = Date.now();
// execute dependency call here....
let duration = Date.now() - startTime;
success = true;
client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:duration, resultCode:0, success: true, dependencyTypeName: "ZSQL"});;
使用 trackMetric
度量事件循环计划所花费的时间的示例实用工具:
function startMeasuringEventLoop() {
var startTime = process.hrtime();
var sampleSum = 0;
var sampleCount = 0;
// Measure event loop scheduling delay
setInterval(() => {
var elapsed = process.hrtime(startTime);
startTime = process.hrtime();
sampleSum += elapsed[0] * 1e9 + elapsed[1];
sampleCount++;
}, 0);
// Report custom metric every second
setInterval(() => {
var samples = sampleSum;
var count = sampleCount;
sampleSum = 0;
sampleCount = 0;
if (count > 0) {
var avgNs = samples / count;
var avgMs = Math.round(avgNs / 1e6);
client.trackMetric({name: "Event Loop Delay", value: avgMs});
}
}, 1000);
}
将自定义属性添加到所有事件
使用以下代码向所有事件添加自定义属性:
appInsights.defaultClient.commonProperties = {
environment: process.env.SOME_ENV_VARIABLE
};
跟踪 HTTP GET 请求
使用以下代码手动跟踪 HTTP GET 请求:
注意
- 默认情况下跟踪所有请求。 若要禁用自动收集,请在调用
start()
之前调用.setAutoCollectRequests(false)
。 - 经典 Application Insights 不会自动跟踪本机提取 API 请求;需要手动依赖项跟踪。
appInsights.defaultClient.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true});
也可使用 trackNodeHttpRequest
方法跟踪请求:
var server = http.createServer((req, res) => {
if ( req.method === "GET" ) {
appInsights.defaultClient.trackNodeHttpRequest({request:req, response:res});
}
// other work here....
res.end();
});
跟踪服务器启动时间
使用以下代码跟踪服务器启动时间:
let start = Date.now();
server.on("listening", () => {
let duration = Date.now() - start;
appInsights.defaultClient.trackMetric({name: "server startup time", value: duration});
});
刷新
默认情况下,遥测数据在发送到引入服务器之前会缓冲 15 秒。 如果应用程序的生存期较短(例如 CLI 工具就是如此),则可能需要在应用程序终止时使用 appInsights.defaultClient.flush()
手动刷新缓冲的遥测。
如果 SDK 检测到应用程序正在崩溃,它会使用 appInsights.defaultClient.flush({ isAppCrashing: true })
为你调用刷新。 如果使用刷新选项 isAppCrashing
,应用程序会被认为处于异常状态,不适合发送遥测。 改为由 SDK 把所有缓冲的遥测数据保存到持久存储,并让应用程序终止。 当应用程序重新启动时,它会尝试发送已保存到持久存储中的遥测数据。
使用遥测处理器预处理数据
在发送收集的数据进行保留之前,可以使用遥测处理器来处理和筛选这些数据。 遥测处理器在遥测项发送到云之前按其添加顺序依次调用。
public addTelemetryProcessor(telemetryProcessor: (envelope: Contracts.Envelope, context: { http.RequestOptions, http.ClientRequest, http.ClientResponse, correlationContext }) => boolean)
如果遥测处理器返回 false
,则不会发送该遥测项。
所有遥测处理器都接收遥测数据及其信封来检查和修改。 它们还会接收上下文对象。 在为手动跟踪的遥测调用跟踪方法时,此对象的内容由 contextObjects
参数定义。 对于自动收集的遥测,此对象使用 appInsights.getCorrelationContext()
提供的可用请求信息和持久性请求内容(如果启用了自动相关性关联)进行填充。
遥测处理器的 TypeScript 类型为:
telemetryProcessor: (envelope: ContractsModule.Contracts.Envelope, context: { http.RequestOptions, http.ClientRequest, http.ClientResponse, correlationContext }) => boolean;
例如,可以按如下所示编写并添加从异常中删除堆栈跟踪数据的处理器:
function removeStackTraces ( envelope, context ) {
if (envelope.data.baseType === "Microsoft.ApplicationInsights.ExceptionData") {
var data = envelope.data.baseData;
if (data.exceptions && data.exceptions.length > 0) {
for (var i = 0; i < data.exceptions.length; i++) {
var exception = data.exceptions[i];
exception.parsedStack = null;
exception.hasFullStack = false;
}
}
}
return true;
}
appInsights.defaultClient.addTelemetryProcessor(removeStackTraces);
使用多个连接字符串
可以创建多个 Application Insights 资源,并使用各自的连接字符串将不同数据发送到每个资源。
例如:
let appInsights = require("applicationinsights");
// configure auto-collection under one connection string
appInsights.setup("Connection String A").start();
// track some events manually under another connection string
let otherClient = new appInsights.TelemetryClient("Connection String B");
otherClient.trackEvent({name: "my custom event"});
高级配置选项
客户端对象包含一个 config
属性,该属性具有多个适用于高级方案的可选设置。 若要设置它们,请使用:
client.config.PROPERTYNAME = VALUE;
这些属性是特定于客户端的,因此你可以从使用 new appInsights.TelemetryClient()
创建的客户端单独配置 appInsights.defaultClient
。
Property | 说明 |
---|---|
connectionString | Application Insights 资源的标识符。 |
endpointUrl | 接收遥测有效负载的引入终结点。 |
quickPulseHost | 接收实时指标遥测的实时指标流主机。 |
proxyHttpUrl | SDK HTTP 流量的代理服务器。 (可选。默认值是从 http_proxy 环境变量拉取的。) |
proxyHttpsUrl | SDK HTTPS 流量的代理服务器。 (可选。默认值是从 https_proxy 环境变量拉取的。) |
httpAgent | 用于 SDK HTTP 流量的 http.Agent。 (可选。默认为未定义。) |
httpsAgent | 用于 SDK HTTPS 流量的 https.Agent。 (可选。默认为未定义。) |
maxBatchSize | 要包括在引入终结点的有效负载中的最大遥测项数。 (默认为 250 。) |
maxBatchIntervalMs | 有效负载达到 maxBatchSize 之前要等待的最长时间。 (默认为 15000 。) |
disableAppInsights | 一个标志,用于指示是否禁用遥测传输。 (默认为 false 。) |
samplingPercentage | 应传输的已跟踪遥测项的百分比。 (默认为 100 。) |
correlationIdRetryIntervalMs | 重试检索交叉组件相关的 ID 之前要等待的时间。 (默认为 30000 。) |
correlationHeaderExcludedDomains | 要从交叉组件相关标头注入中排除的域列表。 (默认值,请参阅 Config.ts。) |
常见问题解答
如何禁用遥测关联?
若要禁用遥测关联,请在配置中使用 correlationHeaderExcludedDomains
属性。 有关详细信息,请参阅 ApplicationInsights-node.js。
故障排除
有关故障排除信息(包括“无数据”方案和自定义日志),请参阅对 Node.js 应用和服务的 Application Insights 监视进行故障排除。