@senacor/azure-function-middleware
Version:
Middleware for azure functions to handle authentication, authorization, error handling and logging
188 lines (187 loc) • 9.99 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppInsightForNoNHttpTrigger = exports.AppInsightForHttpTrigger = void 0;
const appInsights = __importStar(require("applicationinsights"));
const applicationinsights_1 = require("applicationinsights");
const middleware_1 = require("../middleware");
const Logger_1 = require("./Logger");
const telemetryClients = {};
const isDisabled = process.env.APPINSIGHTS_INSTRUMENTATIONKEY === undefined &&
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING === undefined;
if (!isDisabled) {
console.log('Starting appInsights');
appInsights
.setup()
.setAutoDependencyCorrelation(true)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(false, false)
.setAutoCollectExceptions(true)
.setAutoCollectDependencies(true)
.setUseDiskRetryCaching(false)
.setSendLiveMetrics(false)
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)
.setAutoCollectHeartbeat(false)
.setInternalLogging(false, true);
appInsights.defaultClient.commonProperties = Object.assign({ environment: (_a = process.env.ENVIRONMENT) !== null && _a !== void 0 ? _a : 'UNDEFINED' }, appInsights.defaultClient.commonProperties);
appInsights.defaultClient.config.disableAppInsights = isDisabled;
appInsights.start();
console.log('Started appInsights');
}
const setupTelemetryClient = (req, context, additionalProperties) => {
context.log('Setting up AppInsights');
const telemetryClient = new applicationinsights_1.TelemetryClient();
telemetryClients[context.invocationId] = telemetryClient;
Object.assign(context, Object.assign({}, (0, Logger_1.createAppInsightsLogger)(telemetryClient)));
const { invocationId, triggerMetadata } = context;
telemetryClient.commonProperties = Object.assign(Object.assign(Object.assign({ invocationId }, triggerMetadata), additionalProperties), appInsights.defaultClient.commonProperties);
context.log('Set up AppInsights');
};
const setupAppInsightForHttpTrigger = (req, context) => __awaiter(void 0, void 0, void 0, function* () {
if (isDisabled) {
return;
}
setupTelemetryClient(req, context);
});
const setupAppInsightForNonHttpTrigger = (req, context) => __awaiter(void 0, void 0, void 0, function* () {
if (isDisabled) {
return;
}
setupTelemetryClient(req, context);
});
const noOpLogDataSanitizer = (data) => data;
const shouldLog = (logBehavior, isError) => {
switch (logBehavior) {
case 'always':
return true;
case 'on_error':
return isError;
case 'on_success':
return !isError;
case 'never':
return false;
}
};
const finalizeAppInsightForHttpTrigger = (req, context, result) => __awaiter(void 0, void 0, void 0, function* () { return finalizeAppInsightForHttpTriggerWithConfig(req, context, result, 'on_error', noOpLogDataSanitizer); });
const finalizeAppInsightForHttpTriggerWithConfig = (req, context, res, logBodyBehavior, bodySanitizer) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
if (isDisabled) {
return;
}
context.log('Finalizing AppInsights');
const telemetryClient = telemetryClients[context.invocationId];
if (telemetryClient === undefined) {
context.error(`No telemetry client could be found for invocationId ${context.invocationId}`);
return;
}
const correlationContext = appInsights.getCorrelationContext();
telemetryClient.commonProperties = Object.assign({ ['traceparent']: (_b = (_a = correlationContext === null || correlationContext === void 0 ? void 0 : correlationContext.operation.traceparent) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : 'UNDEFINED' }, telemetryClient.commonProperties);
if (res === undefined) {
context.warn("res is empty and properly shouldn't be");
}
if ((0, middleware_1.isErrorResult)(res)) {
return;
}
const result = res.$result;
if (result == undefined) {
context.warn("res is empty and properly shouldn't be");
return;
}
if (shouldLog(logBodyBehavior, result.status ? result.status >= 400 : true)) {
context.log('Request body:', result.body ? bodySanitizer(result.body) : 'NO_REQ_BODY');
context.log('Response body:', result.body ? bodySanitizer(result.body) : 'NO_RES_BODY');
}
telemetryClient.trackRequest({
name: context.functionName,
resultCode: (_c = result.status) !== null && _c !== void 0 ? _c : '0',
// important so that requests with a non-OK response show up as failed
success: result.status ? result.status < 400 : true,
url: req.url.includes('?') ? req.url.split('?')[0] : req.url,
duration: 0,
id: (_e = (_d = correlationContext === null || correlationContext === void 0 ? void 0 : correlationContext.operation) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : 'UNDEFINED',
});
telemetryClient.flush();
delete telemetryClients[context.invocationId];
context.log('Finalized AppInsights');
});
const finalizeAppInsightForNonHttpTrigger = (req, context, result) => __awaiter(void 0, void 0, void 0, function* () { return finalizeAppInsightForNonHttpTriggerWithConfig(req, context, result, 'on_error', noOpLogDataSanitizer); });
const finalizeAppInsightForNonHttpTriggerWithConfig = (req_1, context_1, result_1, ...args_1) => __awaiter(void 0, [req_1, context_1, result_1, ...args_1], void 0, function* (req, context, result, logBodyBehavior = 'on_error', // eslint-disable-line @typescript-eslint/no-unused-vars
bodySanitizer = noOpLogDataSanitizer) {
var _a, _b, _c, _d, _e;
if (isDisabled) {
return;
}
context.log('Finalizing AppInsights');
const telemetryClient = telemetryClients[context.invocationId];
if (telemetryClient === undefined) {
context.error(`No telemetry client could be found for invocationId ${context.invocationId}`);
return;
}
const correlationContext = appInsights.getCorrelationContext();
telemetryClient.commonProperties = Object.assign({ ['traceparent']: (_c = (_b = (_a = correlationContext === null || correlationContext === void 0 ? void 0 : correlationContext.operation) === null || _a === void 0 ? void 0 : _a.traceparent) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : 'UNDEFINED' }, telemetryClient.commonProperties);
telemetryClient.trackRequest({
name: context.functionName,
resultCode: 0,
// important so that requests with a non-OK response show up as failed
success: !(0, middleware_1.isErrorResult)(result),
url: context.functionName,
duration: 0,
id: (_e = (_d = correlationContext === null || correlationContext === void 0 ? void 0 : correlationContext.operation) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : 'UNDEFINED',
});
telemetryClient.flush();
delete telemetryClients[context.invocationId];
});
const AppInsightForHttpTrigger = {
setup: setupAppInsightForHttpTrigger,
finalize: finalizeAppInsightForHttpTrigger,
finalizeWithConfig: (logBodyBehavior, bodySanitizer) => (req, context, res) => finalizeAppInsightForHttpTriggerWithConfig(req, context, res, logBodyBehavior, bodySanitizer),
};
exports.AppInsightForHttpTrigger = AppInsightForHttpTrigger;
const AppInsightForNoNHttpTrigger = {
setup: setupAppInsightForNonHttpTrigger,
finalize: finalizeAppInsightForNonHttpTrigger,
finalizeWithConfig: (logBodyBehavior, bodySanitizer) => (req, context, res) => finalizeAppInsightForHttpTriggerWithConfig(req, context, res, logBodyBehavior, bodySanitizer),
};
exports.AppInsightForNoNHttpTrigger = AppInsightForNoNHttpTrigger;