From df65ae5966a910928cf92b3ed4811185c7e9d956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Sun, 12 Jun 2022 22:31:39 +0200 Subject: [PATCH] feat: Add failed/aborted reload task and app tags as metadata for New Relic events and logs Implements #479 --- src/lib/incident_mgmt/new_relic.js | 224 +++++++++++++++++++++++------ src/qrs_util/app_tag_util.js | 62 ++++++++ src/qrs_util/task_tag_util.js | 62 ++++++++ src/udp/udp_handlers.js | 69 ++++++++- 4 files changed, 368 insertions(+), 49 deletions(-) create mode 100644 src/qrs_util/app_tag_util.js create mode 100644 src/qrs_util/task_tag_util.js diff --git a/src/lib/incident_mgmt/new_relic.js b/src/lib/incident_mgmt/new_relic.js index a52c6aa4..ceb18b28 100644 --- a/src/lib/incident_mgmt/new_relic.js +++ b/src/lib/incident_mgmt/new_relic.js @@ -62,7 +62,7 @@ function getReloadFailedEventConfig() { !globals.config.has('Butler.incidentTool.newRelic.url.event') ) { // Not enough info in config file - globals.logger.error('NEWRELIC: Reload failure New Relic event config info missing in Butler config file'); + globals.logger.error('RELOADFAILEDEVENT: Reload failure New Relic event config info missing in Butler config file'); return false; } @@ -90,7 +90,7 @@ function getReloadFailedEventConfig() { } } - // Get event-specific attributes + // Get event-specific static attributes if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.attribute.static') !== null) { // eslint-disable-next-line no-restricted-syntax for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.attribute.static')) { @@ -116,7 +116,7 @@ function getReloadFailedEventConfig() { return cfg; } catch (err) { - globals.logger.error(`NEWRELIC: ${err}`); + globals.logger.error(`NEWRELIC RELOADFAILEDEVENT: ${err}`); return false; } } @@ -130,7 +130,7 @@ function getReloadFailedLogConfig() { !globals.config.has('Butler.incidentTool.newRelic.url.event') ) { // Not enough info in config file - globals.logger.error('NEWRELIC: Reload failure New Relic log config info missing in Butler config file'); + globals.logger.error('NEWRELIC RELOADFAILEDLOG: Reload failure New Relic log config info missing in Butler config file'); return false; } @@ -181,7 +181,7 @@ function getReloadFailedLogConfig() { return cfg; } catch (err) { - globals.logger.error(`NEWRELIC: ${err}`); + globals.logger.error(`NEWRELIC RELOADFAILEDLOG: ${err}`); return false; } } @@ -190,12 +190,12 @@ function getReloadAbortedEventConfig() { try { // First make sure this tool is enabled in the config file and that we have needed parameters if ( - !globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination') || - !globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.enable') || + !globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event') || + !globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.enable') || !globals.config.has('Butler.incidentTool.newRelic.url.event') ) { // Not enough info in config file - globals.logger.error('NEWRELIC: Reload aborted New Relic event config info missing in Butler config file'); + globals.logger.error('NEWRELIC RELOADABORTEDEVENT: Reload aborted New Relic event config info missing in Butler config file'); return false; } @@ -205,24 +205,30 @@ function getReloadAbortedEventConfig() { 'Api-Key': globals.config.get('Butler.thirdPartyToolsCredentials.newRelic.insertApiKey'), }; - // eslint-disable-next-line no-restricted-syntax - for (const header of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.header')) { - headers[header.name] = header.value; + if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.header') !== null) { + // eslint-disable-next-line no-restricted-syntax + for (const header of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.header')) { + headers[header.name] = header.value; + } } // Add static attributes const attributes = {}; // Get shared static settings - // eslint-disable-next-line no-restricted-syntax - for (const header of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.attribute.static')) { - attributes[header.name] = header.value; + if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.attribute.static') !== null) { + // eslint-disable-next-line no-restricted-syntax + for (const header of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.attribute.static')) { + attributes[header.name] = header.value; + } } - // Get event-specific attributes - // eslint-disable-next-line no-restricted-syntax - for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.static')) { - attributes[item.name] = item.value; + // Get event-specific static attributes + if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.static') !== null) { + // eslint-disable-next-line no-restricted-syntax + for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.static')) { + attributes[item.name] = item.value; + } } // Add dynamic attributes @@ -243,7 +249,7 @@ function getReloadAbortedEventConfig() { return cfg; } catch (err) { - globals.logger.error(`NEWRELIC: ${err}`); + globals.logger.error(`NEWRELIC RELOADABORTEDEVENT: ${err}`); return false; } } @@ -257,7 +263,7 @@ function getReloadAbortedLogConfig() { !globals.config.has('Butler.incidentTool.newRelic.url.event') ) { // Not enough info in config file - globals.logger.error('NEWRELIC: Reload aborted New Relic log config info missing in Butler config file'); + globals.logger.error('NEWRELIC RELOADABORTEDLOG: Reload aborted New Relic log config info missing in Butler config file'); return false; } @@ -267,24 +273,30 @@ function getReloadAbortedLogConfig() { 'Api-Key': globals.config.get('Butler.thirdPartyToolsCredentials.newRelic.insertApiKey'), }; - // eslint-disable-next-line no-restricted-syntax - for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.header')) { - headers[item.name] = item.value; + if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.header') !== null) { + // eslint-disable-next-line no-restricted-syntax + for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.header')) { + headers[item.name] = item.value; + } } // Add static attributes const attributes = {}; // Get shared static attributes - // eslint-disable-next-line no-restricted-syntax - for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.attribute.static')) { - attributes[item.name] = item.value; + if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.attribute.static') !== null) { + // eslint-disable-next-line no-restricted-syntax + for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.sharedSettings.attribute.static')) { + attributes[item.name] = item.value; + } } // Get log-specific attributes - // eslint-disable-next-line no-restricted-syntax - for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.static')) { - attributes[item.name] = item.value; + if (globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.static') !== null) { + // eslint-disable-next-line no-restricted-syntax + for (const item of globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.static')) { + attributes[item.name] = item.value; + } } // Add dynamic attributes @@ -302,7 +314,7 @@ function getReloadAbortedLogConfig() { return cfg; } catch (err) { - globals.logger.error(`NEWRELIC: ${err}`); + globals.logger.error(`NEWRELIC RELOADABORTEDLOG: ${err}`); return false; } } @@ -422,12 +434,14 @@ async function sendNewRelicLog(incidentConfig, reloadParams) { } function sendReloadTaskFailureEvent(reloadParams) { + const params = reloadParams; + rateLimiterFailedReloadsEvent - .consume(reloadParams.qs_taskId, 1) + .consume(params.qs_taskId, 1) .then(async (rateLimiterRes) => { try { globals.logger.info( - `TASK FAILED NEWRELIC: Rate limiting ok: Sending reload failure event to New Relic for task "${reloadParams.qs_taskName}"` + `TASK FAILED NEWRELIC: Rate limiting ok: Sending reload failure event to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK FAILED NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); @@ -437,7 +451,35 @@ function sendReloadTaskFailureEvent(reloadParams) { return 1; } - sendNewRelicEvent(incidentConfig, reloadParams); + // Convert task and app tag arrays to attributes that can be sent to New Relic + + // Should task tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.attribute.dynamic.useTaskTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.attribute.dynamic.useTaskTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_taskTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_taskTag_${item}`] = 'true'; + } + } + delete params.qs_taskTags; + + // Should app tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.attribute.dynamic.useAppTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.attribute.dynamic.useAppTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_appTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_appTag_${item}`] = 'true'; + } + } + delete params.qs_appTags; + + sendNewRelicEvent(incidentConfig, params); return null; } catch (err) { globals.logger.error(`TASK FAILED NEWRELIC: ${err}`); @@ -446,19 +488,21 @@ function sendReloadTaskFailureEvent(reloadParams) { }) .catch((rateLimiterRes) => { globals.logger.verbose( - `TASK FAILED NEWRELIC: Rate limiting failed. Not sending reload failure event to New Relic for task "${reloadParams.qs_taskName}"` + `TASK FAILED NEWRELIC: Rate limiting failed. Not sending reload failure event to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK FAILED NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); } function sendReloadTaskFailureLog(reloadParams) { + const params = reloadParams; + rateLimiterFailedReloadsLog - .consume(reloadParams.qs_taskId, 1) + .consume(params.qs_taskId, 1) .then(async (rateLimiterRes) => { try { globals.logger.info( - `TASK FAILED NEWRELIC: Rate limiting ok: Sending reload failure log entry to New Relic for task "${reloadParams.qs_taskName}"` + `TASK FAILED NEWRELIC: Rate limiting ok: Sending reload failure log entry to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK FAILED NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); @@ -468,7 +512,35 @@ function sendReloadTaskFailureLog(reloadParams) { return 1; } - sendNewRelicLog(incidentConfig, reloadParams); + // Convert task and app tag arrays to attributes that can be sent to New Relic + + // Should task tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.attribute.dynamic.useTaskTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.attribute.dynamic.useTaskTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_taskTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_taskTag_${item}`] = 'true'; + } + } + delete params.qs_taskTags; + + // Should app tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.attribute.dynamic.useAppTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.attribute.dynamic.useAppTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_appTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_appTag_${item}`] = 'true'; + } + } + delete params.qs_appTags; + + sendNewRelicLog(incidentConfig, params); return null; } catch (err) { globals.logger.error(`TASK FAILED NEWRELIC: ${err}`); @@ -477,19 +549,21 @@ function sendReloadTaskFailureLog(reloadParams) { }) .catch((rateLimiterRes) => { globals.logger.verbose( - `TASK FAILED NEWRELIC: Rate limiting failed. Not sending reload failure log entry to New Relic for task "${reloadParams.qs_taskName}"` + `TASK FAILED NEWRELIC: Rate limiting failed. Not sending reload failure log entry to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK FAILED NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); } function sendReloadTaskAbortedEvent(reloadParams) { + const params = reloadParams; + rateLimiterAbortedReloadsEvent - .consume(reloadParams.qs_taskId, 1) + .consume(params.qs_taskId, 1) .then(async (rateLimiterRes) => { try { globals.logger.info( - `TASK ABORT NEWRELIC: Rate limiting ok: Sending reload aborted event to New Relic for task "${reloadParams.taskName}"` + `TASK ABORT NEWRELIC: Rate limiting ok: Sending reload aborted event to New Relic for task "${params.taskName}"` ); globals.logger.verbose(`TASK ABORT NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); @@ -499,7 +573,35 @@ function sendReloadTaskAbortedEvent(reloadParams) { return 1; } - sendNewRelicEvent(incidentConfig, reloadParams); + // Convert task and app tag arrays to attributes that can be sent to New Relic + + // Should task tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.dynamic.useTaskTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.dynamic.useTaskTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_taskTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_taskTag_${item}`] = 'true'; + } + } + delete params.qs_taskTags; + + // Should app tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.dynamic.useAppTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.attribute.dynamic.useAppTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_appTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_appTag_${item}`] = 'true'; + } + } + delete params.qs_appTags; + + sendNewRelicEvent(incidentConfig, params); return null; } catch (err) { globals.logger.error(`TASK ABORT NEWRELIC: ${err}`); @@ -508,19 +610,21 @@ function sendReloadTaskAbortedEvent(reloadParams) { }) .catch((rateLimiterRes) => { globals.logger.verbose( - `TASK ABORT NEWRELIC: Rate limiting failed. Not sending reload aborted event to New Relic for task "${reloadParams.qs_taskName}"` + `TASK ABORT NEWRELIC: Rate limiting failed. Not sending reload aborted event to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK ABORT NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); } function sendReloadTaskAbortedLog(reloadParams) { + const params = reloadParams; + rateLimiterAbortedReloadsLog - .consume(reloadParams.qs_taskId, 1) + .consume(params.qs_taskId, 1) .then(async (rateLimiterRes) => { try { globals.logger.info( - `TASK ABORT NEWRELIC: Rate limiting ok: Sending reload abort log entry to New Relic for task "${reloadParams.qs_taskName}"` + `TASK ABORT NEWRELIC: Rate limiting ok: Sending reload abort log entry to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK ABORT NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); @@ -530,7 +634,35 @@ function sendReloadTaskAbortedLog(reloadParams) { return 1; } - sendNewRelicLog(incidentConfig, reloadParams); + // Convert task and app tag arrays to attributes that can be sent to New Relic + + // Should task tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.dynamic.useTaskTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.dynamic.useTaskTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_taskTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_taskTag_${item}`] = 'true'; + } + } + delete params.qs_taskTags; + + // Should app tags be included as New Relic attributes? + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.dynamic.useAppTags') && + globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.attribute.dynamic.useAppTags') + ) { + // eslint-disable-next-line no-restricted-syntax + for (const item of params.qs_appTags) { + // params[`qs_taskTag_${item.replace(/ /g, '_')}`] = 'true'; + params[`qs_appTag_${item}`] = 'true'; + } + } + delete params.qs_appTags; + + sendNewRelicLog(incidentConfig, params); return null; } catch (err) { globals.logger.error(`TASK ABORT NEWRELIC: ${err}`); @@ -539,7 +671,7 @@ function sendReloadTaskAbortedLog(reloadParams) { }) .catch((rateLimiterRes) => { globals.logger.verbose( - `TASK ABORT NEWRELIC: Rate limiting failed. Not sending reload abort log entry to New Relic for task "${reloadParams.qs_taskName}"` + `TASK ABORT NEWRELIC: Rate limiting failed. Not sending reload abort log entry to New Relic for task "${params.qs_taskName}"` ); globals.logger.verbose(`TASK ABORT NEWRELIC: Rate limiting details "${JSON.stringify(rateLimiterRes, null, 2)}"`); }); diff --git a/src/qrs_util/app_tag_util.js b/src/qrs_util/app_tag_util.js new file mode 100644 index 00000000..b9ff49b0 --- /dev/null +++ b/src/qrs_util/app_tag_util.js @@ -0,0 +1,62 @@ +const path = require('path'); +const QrsInteract = require('qrs-interact'); + +const globals = require('../globals'); + +/** + * + * @param {*} appId + * @returns + */ +function getAppTags(appId) { + return new Promise(async (resolve, reject) => { + globals.logger.debug(`GETAPPTAGS: Retrieving all tags of app ${appId}`); + + try { + const qrsInstance = new QrsInteract({ + hostname: globals.configQRS.host, + portNumber: globals.configQRS.port, + headers: { + 'X-Qlik-User': 'UserDirectory=Internal; UserId=sa_repository', + }, + certificates: { + certFile: path.resolve(globals.configQRS.certPaths.certPath), + keyFile: path.resolve(globals.configQRS.certPaths.keyPath), + }, + }); + + // Get info about the task + try { + globals.logger.debug(`GETAPPTAGS: app/full?filter=id eq ${appId}`); + + const result = await qrsInstance.Get(`app/full?filter=id eq ${appId}`); + globals.logger.debug(`GETAPPTAGS: Got response: ${result.statusCode}`); + + if (result.body.length === 1) { + // Yes, the task exists. Return all tags for this task + + // Get array of all values for this CP, for this task + const appTags1 = result.body[0].tags; + + // Get array of all CP values + const appTags2 = appTags1.map((item) => item.name); + + resolve(appTags2); + } else { + // The task does not exist + resolve([]); + } + } catch (err) { + globals.logger.error(`GETAPPTAGS: Error while getting tags: ${err.message}`); + resolve([]); + } + } catch (err) { + globals.logger.error(`GETAPPTAGS: Error while getting tags: ${err}`); + reject(); + } + }); +} + +module.exports = { + getAppTags, +}; diff --git a/src/qrs_util/task_tag_util.js b/src/qrs_util/task_tag_util.js new file mode 100644 index 00000000..5a6d0343 --- /dev/null +++ b/src/qrs_util/task_tag_util.js @@ -0,0 +1,62 @@ +const path = require('path'); +const QrsInteract = require('qrs-interact'); + +const globals = require('../globals'); + +/** + * + * @param {*} taskId + * @returns + */ +function getTaskTags(taskId) { + return new Promise(async (resolve, reject) => { + globals.logger.debug(`GETTASKTAGS: Retrieving all tags of reload task ${taskId}`); + + try { + const qrsInstance = new QrsInteract({ + hostname: globals.configQRS.host, + portNumber: globals.configQRS.port, + headers: { + 'X-Qlik-User': 'UserDirectory=Internal; UserId=sa_repository', + }, + certificates: { + certFile: path.resolve(globals.configQRS.certPaths.certPath), + keyFile: path.resolve(globals.configQRS.certPaths.keyPath), + }, + }); + + // Get info about the task + try { + globals.logger.debug(`GETTASKTAGS: task/full?filter=id eq ${taskId}`); + + const result = await qrsInstance.Get(`task/full?filter=id eq ${taskId}`); + globals.logger.debug(`GETTASKTAGS: Got response: ${result.statusCode}`); + + if (result.body.length === 1) { + // Yes, the task exists. Return all tags for this task + + // Get array of all values for this CP, for this task + const taskTags1 = result.body[0].tags; + + // Get array of all CP values + const taskTags2 = taskTags1.map((item) => item.name); + + resolve(taskTags2); + } else { + // The task does not exist + resolve([]); + } + } catch (err) { + globals.logger.error(`GETTASKTAGS: Error while getting tags: ${err.message}`); + resolve([]); + } + } catch (err) { + globals.logger.error(`GETTASKTAGS: Error while getting tags: ${err}`); + reject(); + } + }); +} + +module.exports = { + getTaskTags, +}; diff --git a/src/udp/udp_handlers.js b/src/udp/udp_handlers.js index 5744b94e..2ae47702 100644 --- a/src/udp/udp_handlers.js +++ b/src/udp/udp_handlers.js @@ -1,5 +1,6 @@ // Load global variables and functions const globals = require('../globals'); +const QrsInteract = require('qrs-interact'); const smtp = require('../lib/smtp'); const slack = require('../lib/slack_notification'); const webhookOut = require('../lib/webhook_notification'); @@ -7,15 +8,30 @@ const msteams = require('../lib/msteams_notification'); const signl4 = require('../lib/incident_mgmt/signl4'); const newRelic = require('../lib/incident_mgmt/new_relic'); const { failedTaskStoreLogOnDisk } = require('../lib/scriptlog'); +const { getTaskTags } = require('../qrs_util/task_tag_util'); +const { getAppTags } = require('../qrs_util/app_tag_util'); // Handler for failed scheduler initiated reloads -const schedulerAborted = (msg) => { +const schedulerAborted = async (msg) => { globals.logger.verbose( `TASKABORTED: Received reload aborted UDP message from scheduler: UDP msg=${msg[0]}, Host=${msg[1]}, App name=${msg[3]}, Task name=${msg[2]}, Log level=${msg[8]}, Log msg=${msg[10]}` ); // First field in message (msg[0]) is message category (this is the modern/recent message format) + // Check if app/task tags are used by any of the alert destinations. + // If so, get those tags once so they can be re-used where needed. + let appTags = []; + let taskTags = []; + + // Get tags for the app that failed reloading + appTags = await getAppTags(msg[6]); + globals.logger.verbose(`Tags for app ${msg[6]}: ${JSON.stringify(appTags, null, 2)}`); + + // Get tags for the task that failed reloading + taskTags = await getTaskTags(msg[5]); + globals.logger.verbose(`Tags for task ${msg[5]}: ${JSON.stringify(taskTags, null, 2)}`); + // Post to Signl4 when a task has been aborted if ( globals.config.has('Butler.incidentTool.signl4.enable') && @@ -34,6 +50,8 @@ const schedulerAborted = (msg) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -55,6 +73,8 @@ const schedulerAborted = (msg) => { qs_logLevel: msg[8], qs_executionId: msg[9], qs_logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -76,6 +96,8 @@ const schedulerAborted = (msg) => { qs_logLevel: msg[8], qs_executionId: msg[9], qs_logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -97,6 +119,8 @@ const schedulerAborted = (msg) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -118,6 +142,8 @@ const schedulerAborted = (msg) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -139,6 +165,8 @@ const schedulerAborted = (msg) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -157,6 +185,8 @@ const schedulerAborted = (msg) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -190,13 +220,15 @@ const schedulerAborted = (msg) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }) ); } }; // Handler for failed scheduler initiated reloads -const schedulerFailed = (msg, legacyFlag) => { +const schedulerFailed = async (msg, legacyFlag) => { if (legacyFlag) { // First field in message (msg[0]) is host name @@ -406,6 +438,19 @@ const schedulerFailed = (msg, legacyFlag) => { // First field in message (msg[0]) is message category (this is the modern/recent message format) + // Check if app/task tags are used by any of the alert destinations. + // If so, get those tags once so they can be re-used where needed. + let appTags = []; + let taskTags = []; + + // Get tags for the app that failed reloading + appTags = await getAppTags(msg[6]); + globals.logger.verbose(`Tags for app ${msg[6]}: ${JSON.stringify(appTags, null, 2)}`); + + // Get tags for the task that failed reloading + taskTags = await getTaskTags(msg[5]); + globals.logger.verbose(`Tags for task ${msg[5]}: ${JSON.stringify(taskTags, null, 2)}`); + // Store script log to disk if ( globals.config.has('Butler.scriptLog.storeOnDisk.reloadTaskFailure.enable') && @@ -422,6 +467,8 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -443,10 +490,12 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } - // Post evemt to New Relic when a task has failed + // Post event to New Relic when a task has failed if ( globals.config.has('Butler.incidentTool.newRelic.enable') && globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.enable') && @@ -464,6 +513,8 @@ const schedulerFailed = (msg, legacyFlag) => { qs_logLevel: msg[8], qs_executionId: msg[9], qs_logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -485,6 +536,8 @@ const schedulerFailed = (msg, legacyFlag) => { qs_logLevel: msg[8], qs_executionId: msg[9], qs_logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -506,6 +559,8 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -527,6 +582,8 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -548,6 +605,8 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -566,6 +625,8 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }); } @@ -599,6 +660,8 @@ const schedulerFailed = (msg, legacyFlag) => { logLevel: msg[8], executionId: msg[9], logMessage: msg[10], + qs_appTags: appTags, + qs_taskTags: taskTags, }) ); }