1 | # Application Insights for Node.js
|
2 |
|
3 | [![npm version](https://badge.fury.io/js/applicationinsights.svg)](http://badge.fury.io/js/applicationinsights)
|
4 | [![Build Status](https://travis-ci.org/Microsoft/ApplicationInsights-node.js.svg?branch=master)](https://travis-ci.org/Microsoft/ApplicationInsights-node.js)
|
5 |
|
6 | [Azure Application Insights][] monitors your backend services and components after
|
7 | you deploy them to help you [discover and rapidly diagnose performance and other
|
8 | issues][]. Add this SDK to your Node.js services to include deep info about Node.js
|
9 | processes and their external dependencies such as database and cache services.
|
10 | You can use this SDK for your Node.js services hosted anywhere: your datacenter,
|
11 | Azure VMs and Web Apps, and even other public clouds.
|
12 |
|
13 | [Azure Application Insights]: https://azure.microsoft.com/documentation/articles/app-insights-overview/
|
14 | [discover and rapidly diagnose performance and other issues]: https://docs.microsoft.com/azure/application-insights/app-insights-detect-triage-diagnose
|
15 |
|
16 | This library tracks the following out-of-the-box:
|
17 | - Incoming and outgoing HTTP requests
|
18 | - Important system metrics such as CPU usage
|
19 | - Unhandled exceptions
|
20 | - Events from many popular third-party libraries ([see Automatic third-party instrumentation](#automatic-third-party-instrumentation))
|
21 |
|
22 | You can manually track more aspects of your app and system using the API described in the
|
23 | [Track custom telemetry](#track-custom-telemetry) section.
|
24 |
|
25 | ## Getting Started
|
26 |
|
27 | 1. Create an Application Insights resource in Azure by following [these instructions][].
|
28 | 2. Grab the _Instrumentation Key_ (aka "ikey") from the resource you created in
|
29 | step 1. Later, you'll either add it to your app's environment variables or
|
30 | use it directly in your scripts.
|
31 | 3. Add the Application Insights Node.js SDK to your app's dependencies and
|
32 | package.json:
|
33 | ```bash
|
34 | npm install --save applicationinsights
|
35 | ```
|
36 | > *Note:* If you're using TypeScript, do not install a separate "typings" package.
|
37 | > This NPM package contains built-in typings.
|
38 | 4. As early as possible in your app's code, load the Application Insights
|
39 | package:
|
40 | ```javascript
|
41 | let appInsights = require('applicationinsights');
|
42 | ```
|
43 | 5. Configure the local SDK by calling `appInsights.setup('_your_ikey_');`, using
|
44 | the ikey you grabbed in step 2. Or put this ikey in the
|
45 | `APPINSIGHTS_INSTRUMENTATIONKEY` environment variable and call
|
46 | `appInsights.setup()` without parameters.
|
47 | > For more configuration options see below.
|
48 | 6. Finally, start automatically collecting and sending data by calling
|
49 | `appInsights.start();`.
|
50 |
|
51 | [these instructions]: https://docs.microsoft.com/azure/application-insights/app-insights-nodejs
|
52 |
|
53 |
|
54 | ## Basic Usage
|
55 |
|
56 | For out-of-the-box collection of HTTP requests, popular third-party library events,
|
57 | unhandled exceptions, and system metrics:
|
58 |
|
59 | ```javascript
|
60 | let appInsights = require("applicationinsights");
|
61 | appInsights.setup("_your_ikey_").start();
|
62 | ```
|
63 |
|
64 | * If the instrumentation key is set in the environment variable
|
65 | APPINSIGHTS\_INSTRUMENTATIONKEY, `.setup()` can be called with no
|
66 | arguments. This makes it easy to use different ikeys for different
|
67 | environments.
|
68 |
|
69 | Load the Application Insights library (i.e. `require("applicationinsights")`) as
|
70 | early as possible in your scripts, before loading other packages. This is needed
|
71 | so that the Application Insights libary can prepare later packages for tracking.
|
72 | If you encounter conflicts with other libraries doing similar preparation, try
|
73 | loading the Application Insights library after those.
|
74 |
|
75 | Because of the way JavaScript handles callbacks, additional work is necessary to
|
76 | track a request across external dependencies and later callbacks. By default
|
77 | this additional tracking is enabled; disable it by calling
|
78 | `setAutoDependencyCorrelation(false)` as described in the
|
79 | Configuration section below.
|
80 |
|
81 | ## Migrating from versions prior to 0.22
|
82 |
|
83 | There are breaking changes between releases prior to version 0.22 and after. These
|
84 | changes are designed to bring consistency with other Application Insights SDKs and
|
85 | allow future extensibility. Please review this README for new method and property names.
|
86 |
|
87 | In general, you can migrate with the following:
|
88 | - Replace references to `appInsights.client` with `appInsights.defaultClient`
|
89 | - Replace references to `appInsights.getClient()` with `new appInsights.TelemetryClient()`
|
90 | - Replace all arguments to client.track* methods with a single object containing named
|
91 | properties as arguments. See your IDE's built-in type hinting, or [TelemetryTypes](https://github.com/Microsoft/ApplicationInsights-node.js/tree/develop/Declarations/Contracts/TelemetryTypes), for
|
92 | the expected object for each type of telemetry.
|
93 |
|
94 | If you access SDK configuration functions without chaining them to `appInsights.setup()`,
|
95 | you can now find these functions at appInsights.Configuration
|
96 | (eg. `appInsights.Configuration.setAutoCollectDependencies(true)`).
|
97 | Take care to review the changes to the default configuration in the next section.
|
98 |
|
99 | ## Configuration
|
100 |
|
101 | The appInsights object provides a number of configuration methods. They are
|
102 | listed in the following snippet with their default values.
|
103 |
|
104 | ```javascript
|
105 | let appInsights = require("applicationinsights");
|
106 | appInsights.setup("<instrumentation_key>")
|
107 | .setAutoDependencyCorrelation(true)
|
108 | .setAutoCollectRequests(true)
|
109 | .setAutoCollectPerformance(true)
|
110 | .setAutoCollectExceptions(true)
|
111 | .setAutoCollectDependencies(true)
|
112 | .setAutoCollectConsole(true)
|
113 | .setUseDiskRetryCaching(true)
|
114 | .start();
|
115 | ```
|
116 |
|
117 | Please review their descriptions in your IDE's built-in type hinting, or [applicationinsights.ts](https://github.com/Microsoft/ApplicationInsights-node.js/tree/develop/applicationinsights.ts) for
|
118 | detailed information on what these control, and optional secondary arguments.
|
119 |
|
120 | Note that by default `setAutoCollectConsole` is configured to *exclude* calls to `console.log`
|
121 | (and other `console` methods). By default, only calls to supported third-party loggers
|
122 | (e.g. `winston`, `bunyan`) will be collected. You can change this behavior to *include* calls
|
123 | to `console` methods by using `setAutoCollectConsole(true, true)`.
|
124 |
|
125 | ### Sampling
|
126 |
|
127 | By default, the SDK will send all collected data to the Application Insights service. If you collect a lot of data, you might want to enable sampling to reduce the amount of data sent. Set the `samplingPercentage` field on the Config object of a Client to accomplish this. Setting `samplingPercentage` to 100 (the default) means all data will be sent, and 0 means nothing will be sent.
|
128 |
|
129 | If you are using automatic correlation, all data associated with a single request will be included or excluded as a unit.
|
130 |
|
131 | Add code such as the following to enable sampling:
|
132 |
|
133 | ```javascript
|
134 | const appInsights = require("applicationinsights");
|
135 | appInsights.setup("<instrumentation_key>");
|
136 | appInsights.defaultClient.config.samplingPercentage = 33; // 33% of all telemetry will be sent to Application Insights
|
137 | appInsights.start();
|
138 | ```
|
139 |
|
140 | ### Multiple roles for multi-component applications
|
141 |
|
142 | If your application consists of multiple components that you wish to instrument all with the same Instrumentation Key and still see these components as separate units in the Portal as if they were using separate Instrumentation Keys (for example, as separate nodes on the Application Map) you may need to manually configure the RoleName field to distinguish one component's telemetry from other components sending data to your Application Insights resource. (See [Monitor multi-component applications with Application Insights (preview)](https://docs.microsoft.com/azure/application-insights/app-insights-monitor-multi-role-apps))
|
143 |
|
144 | Use the following to set the RoleName field:
|
145 |
|
146 | ```javascript
|
147 | const appInsights = require("applicationinsights");
|
148 | appInsights.setup("<instrumentation_key>");
|
149 | appInsights.defaultClient.context.tags[appInsights.defaultClient.context.keys.cloudRole] = "MyRoleName";
|
150 | appInsights.start();
|
151 | ```
|
152 |
|
153 | ### Automatic third-party instrumentation
|
154 |
|
155 | In order to track context across asynchronous calls, some changes are required in third party libraries such as mongodb and redis.
|
156 | By default ApplicationInsights will use [`diagnostic-channel-publishers`](https://github.com/Microsoft/node-diagnostic-channel/tree/master/src/diagnostic-channel-publishers)
|
157 | to monkey-patch some of these libraries.
|
158 | This can be disabled by setting the `APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL` environment variable. Note that by setting that
|
159 | environment variable, events may no longer be correctly associated with the right operation. Individual monkey-patches can be
|
160 | disabled by setting the `APPLICATION_INSIGHTS_NO_PATCH_MODULES` environment variable to a comma separated list of packages to
|
161 | disable, e.g. `APPLICATION_INSIGHTS_NO_PATCH_MODULES=console,redis` to avoid patching the `console` and `redis` packages.
|
162 |
|
163 | Currently there are 9 packages which are instrumented: `bunyan`, `console`, `mongodb`, `mongodb-core`, `mysql`, `redis`, `winston`,
|
164 | `pg`, and `pg-pool`. Visit the [diagnostic-channel-publishers' README](https://github.com/Microsoft/node-diagnostic-channel/blob/master/src/diagnostic-channel-publishers/README.md)
|
165 | for information about exactly which versions of these packages are patched.
|
166 |
|
167 | The `bunyan`, `winston`, and `console` patches will generate Application Insights Trace events based on whether `setAutoCollectConsole` is enabled.
|
168 | The rest will generate Application Insights Dependency events based on whether `setAutoCollectDependencies` is enabled.
|
169 |
|
170 | ## Track custom telemetry
|
171 |
|
172 | You can track any request, event, metric or exception using the Application
|
173 | Insights client. Examples follow:
|
174 |
|
175 | ```javascript
|
176 | let appInsights = require("applicationinsights");
|
177 | appInsights.setup().start(); // assuming ikey in env var. start() can be omitted to disable any non-custom data
|
178 | let client = appInsights.defaultClient;
|
179 | client.trackEvent({name: "my custom event", properties: {customProperty: "custom property value"}});
|
180 | client.trackException({exception: new Error("handled exceptions can be logged with this method")});
|
181 | client.trackMetric({name: "custom metric", value: 3});
|
182 | client.trackTrace({message: "trace message"});
|
183 | client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:231, resultCode:0, success: true, dependencyTypeName: "ZSQL"});
|
184 | client.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true});
|
185 |
|
186 | let http = require("http");
|
187 | http.createServer( (req, res) => {
|
188 | client.trackNodeHttpRequest({request: req, response: res}); // Place at the beginning of your request handler
|
189 | });
|
190 | ```
|
191 |
|
192 | An example utility using `trackMetric` to measure how long event loop scheduling takes:
|
193 |
|
194 | ```javascript
|
195 | function startMeasuringEventLoop() {
|
196 | var startTime = process.hrtime();
|
197 | var sampleSum = 0;
|
198 | var sampleCount = 0;
|
199 |
|
200 | // Measure event loop scheduling delay
|
201 | setInterval(() => {
|
202 | var elapsed = process.hrtime(startTime);
|
203 | sampleSum += elapsed[0] * 1e9 + elapsed[1];
|
204 | sampleCount++;
|
205 | }, 0);
|
206 |
|
207 | // Report custom metric every second
|
208 | setInterval(() => {
|
209 | var samples = sampleSum;
|
210 | var count = sampleCount;
|
211 | sampleSum = 0;
|
212 | sampleCount = 0;
|
213 |
|
214 | if (count > 0) {
|
215 | var avgNs = samples / count;
|
216 | var avgMs = Math.round(avgNs / 1e6);
|
217 | client.trackMetric({name: "Event Loop Delay", value: avgMs});
|
218 | }
|
219 | }, 1000);
|
220 | }
|
221 | ```
|
222 |
|
223 | ## Preprocess data with Telemetry Processors
|
224 |
|
225 | ```javascript
|
226 | public addTelemetryProcessor(telemetryProcessor: (envelope: Contracts.Envelope, context: { http.RequestOptions, http.ClientRequest, http.ClientResponse, correlationContext }) => boolean)
|
227 | ```
|
228 |
|
229 | You can process and filter collected data before it is sent for retention using
|
230 | _Telemetry Processors_. Telemetry processors are called one by one in the
|
231 | order they were added before the telemetry item is sent to the cloud.
|
232 |
|
233 | If a telemetry processor returns false that telemetry item will not be sent.
|
234 |
|
235 | All telemetry processors receive the telemetry data and its envelope to inspect and
|
236 | modify. They also receive a context object. The contents of this object is defined by
|
237 | the `contextObjects` parameter when calling a track method for manually tracked telemetry.
|
238 | For automatically collected telemetry, this object is filled with available request information
|
239 | and the persistent request context as provided by `appInsights.getCorrelationContext()` (if
|
240 | automatic dependency correlation is enabled).
|
241 |
|
242 | The TypeScript type for a telemetry processor is:
|
243 |
|
244 | ```typescript
|
245 | telemetryProcessor: (envelope: ContractsModule.Contracts.Envelope, context: { http.RequestOptions, http.ClientRequest, http.ClientResponse, correlationContext }) => boolean;
|
246 | ```
|
247 |
|
248 | For example, a processor that removes stack trace data from exceptions might be
|
249 | written and added as follows:
|
250 |
|
251 | ```javascript
|
252 | function removeStackTraces ( envelope, context ) {
|
253 | if (envelope.data.baseType === "Microsoft.ApplicationInsights.ExceptionData") {
|
254 | var data = envelope.data.baseData;
|
255 | if (data.exceptions && data.exceptions.length > 0) {
|
256 | for (var i = 0; i < data.exceptions.length; i++) {
|
257 | var exception = data.exceptions[i];
|
258 | exception.parsedStack = null;
|
259 | exception.hasFullStack = false;
|
260 | }
|
261 | }
|
262 | }
|
263 | return true;
|
264 | }
|
265 |
|
266 | appInsights.defaultClient.addTelemetryProcessor(removeStackTraces);
|
267 | ```
|
268 |
|
269 | More info on the telemetry API is available in [the docs][].
|
270 |
|
271 | [the docs]: https://azure.microsoft.com/documentation/articles/app-insights-api-custom-events-metrics/
|
272 |
|
273 | ## Use multiple instrumentation keys
|
274 |
|
275 | You can create multiple Azure Application Insights resources and send different
|
276 | data to each by using their respective instrumentation keys ("ikey"). For
|
277 | example:
|
278 |
|
279 | ```javascript
|
280 | let appInsights = require("applicationinsights");
|
281 |
|
282 | // configure auto-collection under one ikey
|
283 | appInsights.setup("_ikey-A_").start();
|
284 |
|
285 | // track some events manually under another ikey
|
286 | let otherClient = new appInsights.TelemetryClient("_ikey-B_");
|
287 | otherClient.trackEvent({name: "my custom event"});
|
288 | ```
|
289 |
|
290 | ## Examples
|
291 |
|
292 | * Track dependencies
|
293 |
|
294 | ```javascript
|
295 | let appInsights = require("applicationinsights");
|
296 | let client = new appInsights.TelemetryClient();
|
297 |
|
298 | var success = false;
|
299 | let startTime = Date.now();
|
300 | // execute dependency call here....
|
301 | let duration = Date.now() - startTime;
|
302 | success = true;
|
303 |
|
304 | client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:duration, resultCode:0, success: true, dependencyTypeName: "ZSQL"});
|
305 | ```
|
306 |
|
307 | * Assign custom properties to be included with all events
|
308 |
|
309 | ```javascript
|
310 | appInsights.defaultClient.commonProperties = {
|
311 | environment: process.env.SOME_ENV_VARIABLE
|
312 | };
|
313 | ```
|
314 |
|
315 | * Manually track all HTTP GET requests
|
316 |
|
317 | Note that all requests are tracked by default. To disable automatic
|
318 | collection, call `.setAutoCollectRequests(false)` before calling `start()`.
|
319 |
|
320 | ```javascript
|
321 | appInsights.defaultClient.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true});
|
322 | ```
|
323 | Alternatively you can track requests using ```trackNodeHttpRequest``` method:
|
324 |
|
325 | ```javascript
|
326 | var server = http.createServer((req, res) => {
|
327 | if ( req.method === "GET" ) {
|
328 | appInsights.defaultClient.trackNodeHttpRequest({request:req, response:res});
|
329 | }
|
330 | // other work here....
|
331 | res.end();
|
332 | });
|
333 | ```
|
334 |
|
335 | * Track server startup time
|
336 |
|
337 | ```javascript
|
338 | let start = Date.now();
|
339 | server.on("listening", () => {
|
340 | let duration = Date.now() - start;
|
341 | appInsights.defaultClient.trackMetric({name: "server startup time", value: duration});
|
342 | });
|
343 | ```
|
344 |
|
345 | ## Advanced configuration options
|
346 | The Client object contains a `config` property with many optional settings for
|
347 | advanced scenarios. These can be set as follows:
|
348 | ```
|
349 | client.config.PROPERTYNAME = VALUE;
|
350 | ```
|
351 | These properties are client specific, so you can configure `appInsights.defaultClient`
|
352 | separately from clients created with `new appInsights.TelemetryClient()`.
|
353 |
|
354 | | Property | Description |
|
355 | | ------------------------------- |------------------------------------------------------------------------------------------------------------|
|
356 | | instrumentationKey | An identifier for your Application Insights resource |
|
357 | | endpointUrl | The ingestion endpoint to send telemetry payloads to |
|
358 | | proxyHttpUrl | A proxy server for SDK HTTP traffic (Optional, Default pulled from `http_proxy` environment variable) |
|
359 | | proxyHttpsUrl | A proxy server for SDK HTTPS traffic (Optional, Default pulled from `https_proxy` environment variable) |
|
360 | | httpAgent | An http.Agent to use for SDK HTTP traffic (Optional, Default undefined) |
|
361 | | httpsAgent | An https.Agent to use for SDK HTTPS traffic (Optional, Default undefined) |
|
362 | | maxBatchSize | The maximum number of telemetry items to include in a payload to the ingestion endpoint (Default `250`) |
|
363 | | maxBatchIntervalMs | The maximum amount of time to wait to for a payload to reach maxBatchSize (Default `15000`) |
|
364 | | disableAppInsights | A flag indicating if telemetry transmission is disabled (Default `false`) |
|
365 | | samplingPercentage | The percentage of telemetry items tracked that should be transmitted (Default `100`) |
|
366 | | correlationIdRetryIntervalMs | The time to wait before retrying to retrieve the id for cross-component correlation (Default `30000`) |
|
367 | | correlationHeaderExcludedDomains| A list of domains to exclude from cross-component correlation header injection (Default See [Config.ts][]) |
|
368 |
|
369 | [Config.ts]: https://github.com/Microsoft/ApplicationInsights-node.js/blob/develop/Library/Config.ts
|
370 |
|
371 | ## Branches
|
372 |
|
373 | - Ongoing development takes place on the [develop][] branch. **Please submit
|
374 | pull requests to this branch.**
|
375 | - Releases are merged to the [master][] branch and published to [npm][].
|
376 |
|
377 | [master]: https://github.com/Microsoft/ApplicationInsights-node.js/tree/master
|
378 | [develop]: https://github.com/Microsoft/ApplicationInsights-node.js/tree/develop
|
379 | [npm]: https://www.npmjs.com/package/applicationinsights
|
380 |
|
381 | ## Links
|
382 |
|
383 | * [ApplicationInsights-Home][] is our central repo for libraries and info for
|
384 | all languages and platforms.
|
385 | * Follow the latest Application Insights changes and announcements on the
|
386 | [ApplicationInsights-Announcements][] repo.
|
387 | * [SDK Release Schedule][]
|
388 |
|
389 | [ApplicationInsights-Announcements]: https://github.com/Microsoft/ApplicationInsights-Announcements
|
390 | [ApplicationInsights-Home]: https://github.com/Microsoft/ApplicationInsights-Home
|
391 | [SDK Release Schedule]: https://github.com/Microsoft/ApplicationInsights-Home/wiki/SDK-Release-Schedule
|
392 |
|
393 | ## Contributing
|
394 |
|
395 | 1. Install all dependencies with `npm install`.
|
396 | 2. Set an environment variable to your instrumentation key (optional).
|
397 | ```bash
|
398 | // windows
|
399 | set APPINSIGHTS_INSTRUMENTATIONKEY=<insert_your_instrumentation_key_here>
|
400 | // linux/macos
|
401 | export APPINSIGHTS_INSTRUMENTATIONKEY=<insert_your_instrumentation_key_here>
|
402 | ```
|
403 | 3. Run tests
|
404 | ```bash
|
405 | npm run test
|
406 | npm run backcompattest
|
407 | npm run functionaltest
|
408 | ```
|
409 | _Note: Functional tests require Docker_
|
410 |
|
411 | ---
|
412 |
|
413 | This project has adopted the [Microsoft Open Source Code of Conduct][]. For more
|
414 | information see the [Code of Conduct FAQ][] or contact
|
415 | [opencode@microsoft.com][] with any additional questions or comments.
|
416 |
|
417 | [Microsoft Open Source Code of Conduct]: https://opensource.microsoft.com/codeofconduct/
|
418 | [Code of Conduct FAQ]: https://opensource.microsoft.com/codeofconduct/faq/
|
419 | [opencode@microsoft.com]: mailto:opencode@microsoft.com
|