Skip to content

Instantly share code, notes, and snippets.

@gregfenton
Created February 10, 2024 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregfenton/2bc30fcd096aed6080fe4dec68218e9a to your computer and use it in GitHub Desktop.
Save gregfenton/2bc30fcd096aed6080fe4dec68218e9a to your computer and use it in GitHub Desktop.
Failing attempt at using @google-cloud/monitoring to add LogEvent policies -- API does not currently support it
// This code fails with the error described in:
// https://github.com/googleapis/google-cloud-node/issues/4361
//
// The Node/JS version of the SDK currently does not support adding LogEvent policies.
//
//
// To run this code:
// - save to a file (e.g. "create-alerts.js")
// - be logged into your gcloud account (`gcloud auth login`)
// - set the env var `PROJ_ID` with your project ID
// - run the file: `node ./create-alerts.js`
//
// [you can do both last 2 steps with: `PROJ_ID=<YOUR_PROJECT_NAME> node ./create-alerts.js`
//
/* eslint-disable no-console */
import util from 'util';
// Imports the Google Cloud client library
import {
AlertPolicyServiceClient,
NotificationChannelServiceClient,
} from '@google-cloud/monitoring';
// Creates a client
const alertClient = new AlertPolicyServiceClient();
const notificationClient = new NotificationChannelServiceClient();
let POLICY_CF_NOT_OK = {
alertStrategy: {
autoClose: '604800s',
notificationRateLimit: {
period: '3600s',
},
},
combiner: 'OR',
conditions: [
{
displayName: 'Log match condition',
conditionMatchedLog: {
filter: `textPayload=~"Function execution took ((?:\\d[,.]?)*\\d) ms, finished with status: \'" AND
textPayload!~"Function execution took ((?:\\d[,.]?)*\\d) ms, finished with status: \'ok\'"`,
},
},
],
displayName: 'Non-OK Cloud Functions',
documentation: {
content: 'something no good happen, eh?',
mimeType: 'text/markdown',
},
enabled: true,
severity: 'ERROR',
userLabels: {},
};
const main = async () => {
const instanceId = process.env.PROJ_ID;
if (!instanceId) {
console.error('Please set the environment variable PROJ_ID');
return;
}
for (const policy of [POLICY_CF_NOT_OK]) {
await restorePolicy(instanceId, policy);
}
};
const restorePolicy = async (instanceId, currPolicy) => {
// Note: The policies are restored one at a time due to limitations in
// the API. Otherwise, you may receive a 'service unavailable' error
// while trying to create multiple alerts simultaneously.
const request = {
name: notificationClient.projectPath(instanceId),
};
const notificationChannels =
await notificationClient.listNotificationChannels(request);
const notificationChannelNames = notificationChannels[0].map((nc) => nc.name);
console.log('notificationChannels:', notificationChannelNames.join(', '));
// Restore each policy one at a time
const existingPolicy = await doesAlertPolicyExist(
'projects/' + instanceId,
currPolicy.displayName
);
if (existingPolicy) {
console.log(`*** Delete existing ${existingPolicy.name}.`);
currPolicy = await alertClient.deleteAlertPolicy({
name: existingPolicy.name,
});
}
// Clear away output-only fields
delete currPolicy.name;
delete currPolicy.creationRecord;
delete currPolicy.mutationRecord;
currPolicy.conditions.forEach((condition) => delete condition.name);
const newDisplay = [
instanceId.toLocaleUpperCase(),
currPolicy.displayName,
].join(' ');
currPolicy.displayName = newDisplay;
currPolicy.notificationChannels = notificationChannelNames;
const req = {
name: alertClient.projectPath(instanceId),
alertPolicy: currPolicy,
};
console.log('Calling CREATE:', util.inspect(req, {depth: 10}));
let newPolicy = await alertClient.createAlertPolicy(req);
console.log(`Restored ${newPolicy[0].name}.`);
};
const doesAlertPolicyExist = async (projectName, displayName) => {
try {
const result = await alertClient.listAlertPolicies({
name: projectName,
});
const policyNames = result[0];
return policyNames.find((policy) =>
policy.displayName.includes(displayName)
);
} catch (err) {
if (err && err.code === 5) {
// Error code 5 comes from the google.rpc.code.NOT_FOUND protobuf
return false;
}
throw err;
}
};
main().then(() => {
console.log('Done.');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment