microsoft / ApplicationInsights-node.js

Microsoft Application Insights SDK for Node.js
MIT License
325 stars 139 forks source link

Application Insights - AWS Lambda, not reporting #540

Open jtbruch-fixdrepair opened 5 years ago

jtbruch-fixdrepair commented 5 years ago

Attempt:

Code:


import { APIGatewayEvent, Callback, Context, Handler } from 'aws-lambda';
import { logger } from '../../lib/logger';
import { getStatusResponse } from '../../lib/aws';

const appInsights = require("applicationinsights");
appInsights.setup('key')
.setInternalLogging(true).setUseDiskRetryCaching(false).start();

appInsights.defaultClient.config.maxBatchIntervalMs = 0;

export const endpoint: Handler = async (event: APIGatewayEvent, _context: Context, cb: Callback) => {
  logger('event body', event.body);
  logger('event.headers', event.headers);

  let client = appInsights.defaultClient;
  logger('get client', client);
  let val = client.trackMetric(
    { name: "AI Test", value: 25 }
  );
  logger('track metric', val);
  client.flush({callback: () => {
    cb(null, getStatusResponse(200, `This is the data from event.body (or what you passed in from --path example_data.json) == ${event.body}`));
  }});
  return cb(null, getStatusResponse(200, `This is the data from event.body (or what you passed in from --path example_data.json) == ${event.body}`));
};

Reference Functions:

export function logger(message: string, jsonObject: any = null) {
  console.log(`${new Date().toTimeString()}: ${message}`);
  if (typeof jsonObject === 'string' || typeof jsonObject === 'number') {
    console.log(`${new Date().toTimeString()}: ${jsonObject}`);
  }
  if (jsonObject != null && typeof jsonObject === 'object') {
    console.log(`${new Date().toTimeString()}: ${JSON.stringify(inspect(jsonObject))}`);
  }
}

export const getStatusResponse = (status: number, returnMessage: string | any): AwsCallBackResponse => {

  if (typeof returnMessage === 'string' || typeof returnMessage === 'number') {
    returnMessage = `${returnMessage}`;
  }
  if (returnMessage != null && typeof returnMessage === 'object') {
    returnMessage = `${JSON.stringify(inspect(returnMessage))}`;
  }
  let response = {
    statusCode: status,
    body: returnMessage
  };
  logger('return_response:', response);
  return response;
};

Cloudwatch Logs:

START RequestId: cc397086-32aa-40b3-bcfe-dde45998ed3b Version: $LATEST

17:39:49
2019-07-31T17:39:49.248Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    ApplicationInsights:CorrelationIdManager [ { method: 'GET', disableAppInsightsAutoCollection: true } ]

17:39:49
2019-07-31T17:39:49.270Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): event body

17:39:49
2019-07-31T17:39:49.270Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): {"subscriptionId":"8a25e43a-063b-4d2f-a350-4b909487b527","notificationId":518,"id":"eb33f0d2-ba2e-4895-b06d-eae75a87c9f2","eventType":"workitem.commented",

17:39:49
2019-07-31T17:39:49.280Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): event.headers

17:39:49
2019-07-31T17:39:49.281Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): "{ 'CloudFront-Forwarded-Proto': 'https',\n 'CloudFront-Is-Desktop-Viewer': 'true',\n 'CloudFront-Is-Mobile-Viewer': 'false',\n 'CloudFront-Is-SmartTV-Viewer': 'false',\n 'CloudFront-Is-Tablet-Viewer': 'false',\n 'CloudFront-Viewer-Country': 'US',\n 'Content-Type': 'application/json; charset=utf-8',\n Hos

17:39:49
2019-07-31T17:39:49.281Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): get client

17:39:49
2019-07-31T17:39:49.282Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): "NodeClient {\n _telemetryProcessors: [],\n config: \n Config {\n endpointBase: 'https://dc.services.visualstudio.com',\n instrumentationKey: '49a561df-4a8a-4291-b174-e870e95f4619',\n endpointUrl: 'https://dc.services.visualstudio.com/v2/track',\n maxBatchSize: 250,\n maxBatchIntervalMs:
2019-07-31T17:39:49.282Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): "NodeClient {\n _telemetryProcessors: [],\n config: \n Config {\n endpointBase: 'https://dc.services.visualstudio.com',\n instrumentationKey: '49a561df-4a8a-4291-b174-e870e95f4619',\n endpointUrl: 'https://dc.services.visualstudio.com/v2/track',\n maxBatchSize: 250,\n maxBatchIntervalMs: 0,\n disableAppInsights: false,\n samplingPercentage: 100,\n correlationIdRetryIntervalMs: 30000,\n correlationHeaderExcludedDomains: \n [ '*.core.windows.net',\n '*.core.chinacloudapi.cn',\n '*.core.cloudapi.de',\n '*.core.usgovcloudapi.net' ],\n setCorrelationId: [Function],\n _profileQueryEndpoint: 'https://dc.services.visualstudio.com',\n correlationId: 'cid-v1:',\n proxyHttpUrl: undefined,\n proxyHttpsUrl: undefined,\n httpAgent: undefined,\n httpsAgent: undefined,\n _quickPulseHost: 'rt.services.visualstudio.com' },\n context: \n Context {\n keys: \n ContextTagKeys {\n applicationVersion: 'ai.application.ver',\n deviceId: 'ai.device.id',\n deviceLocale: 'ai.device.locale',\n deviceModel: 'ai.device.model',\n deviceOEMName: 'ai.device.oemName',\n deviceOSVersion: 'ai.device.osVersion',\n deviceType: 'ai.device.type',\n locationIp: 'ai.location.ip',\n operationId: 'ai.operation.id',\n operationName: 'ai.operation.name',\n operationParentId: 'ai.operation.parentId',\n operationSyntheticSource: 'ai.operation.syntheticSource',\n operationCorrelationVector: 'ai.operation.correlationVector',\n sessionId: 'ai.session.id',\n sessionIsFirst: 'ai.session.isFirst',\n userAccountId: 'ai.user.accountId',\n userId: 'ai.user.id',\n userAuthUserId: 'ai.user.authUserId',\n cloudRole: 'ai.cloud.role',\n cloudRoleInstance: 'ai.cloud.roleInstance',\n internalSdkVersion: 'ai.internal.sdkVersion',\n internalAgentVersion: 'ai.internal.agentVersion',\n internalNodeName: 'ai.internal.nodeName' },\n tags: \n { 'ai.application.ver': 'unknown',\n 'ai.device.id': '',\n 'ai.cloud.roleInstance': '169.254.58.189',\n 'ai.device.osVersion': 'Linux 4.14.123-95.109.amzn2.x86_64',\n 'ai.cloud.role': 'Web',\n 'ai.device.osArchitecture': 'x64',\n 'ai.device.osPlatform': 'linux',\n 'ai.internal.sdkVersion': 'node:unknown' } },\n commonProperties: {},\n channel: \n Channel {\n _buffer: [],\n _lastSend: 0,\n _isDisabled: [Function],\n _getBatchSize: [Function],\n _getBatchIntervalMs: [Function],\n _sender: \n Sender {\n _config: [Object],\n _onSuccess: undefined,\n _onError: undefined,\n _enableDiskRetryMode: false,\n _resendInterval: 60000,\n _maxBytesOnDisk: 50000000,\n _numConsecutiveFailures: 0 } } }"

17:39:49
2019-07-31T17:39:49.283Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): track metric

17:39:49
2019-07-31T17:39:49.285Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): return_response:

17:39:49
2019-07-31T17:39:49.285Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    17:39:49 GMT+0000 (UTC): "{ statusCode: 200,\n body: 'This is the data from event.body (or what you passed in from --path example_data.json) == {\"subscriptionId\":\"8a25e43a-063b-4d2f-a350-4b909487b527\",\"notificationId\":518,\"id\":\"eb33f0d2-ba2e-4895-b06d-eae75a87c9f2\",\"eventType\":\"workitem.commented\",\"publisherId\":\"tfs\",

17:39:49
2019-07-31T17:39:49.288Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    ApplicationInsights:Sender [ { method: 'POST', withCredentials: false, headers: { 'Content-Type': 'application/x-json-stream', 'Content-Encoding': 'gzip', 'Content-Length': 405 } } ]

17:39:49
2019-07-31T17:39:49.329Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    ApplicationInsights:CorrelationIdManager [ '7f2de232-b8e1-4591-8cfe-ae80d3f6f7e6' ]

17:39:49
2019-07-31T17:39:49.583Z    cc397086-32aa-40b3-bcfe-dde45998ed3b    ApplicationInsights:Sender [ '{"itemsReceived":1,"itemsAccepted":1,"errors":[]}' ]
carlo-quinonez commented 5 years ago

I was able to get logs from an AWS Lambda. I ended up creating a version of flush() that returns a promise like this:

appInsights
    .setup(appInsightsKey)
    .setUseDiskRetryCaching(false)
    .start();
const flushAsync = appInsights.defaultClient.flush.bind(appInsights.defaultClient);
const client = appInsights.defaultClient;
client.flush = function(): Promise<string> {
  return new Promise(resolve =>
    flushAsync({
      callback: () => resolve('Sent'),
    }),
  );
};

Then in the handler function:

// handle the event

await client.flush()
return

This way the lambda won't shut down until after the AppInishgts client flushes the telemetry.

franklanganke commented 2 years ago

@carlo-quinonez thanks for your template, I created a variation based on your snippet.


const status = await new Promise((resolve) => {
  client.flush({ callback: () => resolve("appInsights flushed") });
});
console.log(status);