Skip to content

Commit

Permalink
add log links to alarm chat messages
Browse files Browse the repository at this point in the history
  • Loading branch information
johnduffell committed Oct 9, 2024
1 parent e7467b1 commit b77f1c0
Show file tree
Hide file tree
Showing 5 changed files with 363 additions and 119 deletions.
116 changes: 86 additions & 30 deletions handlers/alarms-handler/src/alarmMappings.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { groupBy } from '@modules/arrayFunctions';
import { getIfDefined } from '@modules/nullAndUndefined';

type Team = 'VALUE' | 'GROWTH' | 'PORTFOLIO' | 'PLATFORM' | 'SRE';
Expand All @@ -17,7 +18,8 @@ const sharedMobilePurchasesApps = [
'mobile-purchases-google-update-subscriptions',
];

const teamToAppMappings: Record<Team, string[]> = {
type AppInfo = string | { app: string; logGroups: string[] };
export const teamToAppMappings: Record<Team, AppInfo[]> = {
GROWTH: [
'acquisition-events-api',
'admin-console',
Expand Down Expand Up @@ -71,11 +73,17 @@ const teamToAppMappings: Record<Team, string[]> = {
'zuora-creditor',

// support-frontend
'frontend',
{ app: 'frontend', logGroups: ['support-frontend'] },
'it-test-runner',
'stripe-intent',
'workers',
'payment-api',
{
app: 'workers',
logGroups: [
'/aws/lambda/CreatePaymentMethod',
'/aws/lambda/CreateZuoraSubscription', //etc
],
},
{ app: 'payment-api', logGroups: ['support-payment-api'] },

// support-service-lambdas
'digital-voucher-suspension-processor',
Expand Down Expand Up @@ -107,33 +115,81 @@ const teamToAppMappings: Record<Team, string[]> = {
],
};

const buildAppToTeamMappings = (): Record<string, Team[]> => {
const mappings: Record<string, Team[]> = {};

for (const [team, apps] of Object.entries(teamToAppMappings)) {
for (const app of apps) {
const teams = mappings[app] ?? [];
teams.push(team as Team);

mappings[app] = teams;
}
export class AlarmMappings {
constructor(mappings: Record<string, AppInfo[]> = teamToAppMappings) {
this.appToTeamMappings = this.buildAppToTeamMappings(mappings);
this.appToLogGroupOverrides = this.buildAppToLogGroupOverrides(mappings);
}
return mappings;
};

const appToTeamMappings: Record<string, Team[]> = buildAppToTeamMappings();

export const getTeams = (appName?: string): Team[] => {
if (appName && appToTeamMappings[appName]) {
return appToTeamMappings[appName] as Team[];
}
private buildAppToTeamMappings = (
theMappings: Record<Team, AppInfo[]>,
): Record<string, Team[]> => {
const entries: Array<[Team, AppInfo[]]> = Object.entries(theMappings) as Array<[
Team,
AppInfo[],
]>; // `as` - hmm?

const teamToApp: Array<{ app: string; team: Team }> = entries.flatMap(
([team, appInfos]) =>
appInfos.map((appInfo) => {
const app = typeof appInfo === 'string' ? appInfo : appInfo.app;
return { team, app };
}),
);
const groups = groupBy(teamToApp, ({ app }) => app);

const mappings: Record<string, Team[]> = Object.fromEntries(
Object.entries(groups).map(([app, info]) => [
app,
info.map(({ team }) => team),
]),
);

return mappings;
};

private buildAppToLogGroupOverrides = (
theMappings: Record<Team, AppInfo[]>,
): Record<string, string[]> => {
return Object.fromEntries(
Object.values(theMappings)
.flatMap((appInfos) => appInfos)
.flatMap((appInfo) =>
typeof appInfo !== 'string' ? [[appInfo.app, appInfo.logGroups]] : [],
),
);
};

private appToTeamMappings: Record<string, Team[]>;
private appToLogGroupOverrides: Record<string, string[]>;

getTeams = (appName?: string): Team[] => {
if (appName && this.appToTeamMappings[appName]) {
return this.appToTeamMappings[appName] as Team[];
}

return ['SRE'];
};
return ['SRE'];
};

getTeamWebhookUrl = (team: Team): string => {
return getIfDefined<string>(
process.env[`${team}_WEBHOOK`],
`${team}_WEBHOOK environment variable not set`,
);
};

getLogGroups = (appName: string, stage: string): string[] => {
// currently we assume the log group is /aws/lambda/<app>-<stage>, we can add overrides to the appToTeamMappings later
const logGroup = this.appToLogGroupOverrides[appName];
if (logGroup === undefined) {
// assume it's a lambda
console.log('logGroup', logGroup);
const lambdaName = appName + '-' + stage;

const logGroupName = '/aws/lambda/' + lambdaName;
return [logGroupName];
}

export const getTeamWebhookUrl = (team: Team): string => {
return getIfDefined<string>(
process.env[`${team}_WEBHOOK`],
`${team}_WEBHOOK environment variable not set`,
);
};
return logGroup.map((override) => override + '-' + stage);
};
}
23 changes: 12 additions & 11 deletions handlers/alarms-handler/src/cloudwatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,25 @@ const buildCloudwatchClient = (awsAccountId: string): CloudWatchClient => {
return new CloudWatchClient({ region: 'eu-west-1' });
};

const getTags = async (
export type Tags = {
App?: string;
Stage?: string;
};

export const getTags = async (
alarmArn: string,
awsAccountId: string,
): Promise<Tag[]> => {
): Promise<Tags> => {
const client = buildCloudwatchClient(awsAccountId);

const request = new ListTagsForResourceCommand({
ResourceARN: alarmArn,
});

const response = await client.send(request);
return response.Tags ?? [];
};

export const getAppNameTag = async (
alarmArn: string,
awsAccountId: string,
): Promise<string | undefined> => {
const tags = await getTags(alarmArn, awsAccountId);
return tags.find((tag: Tag) => tag.Key === 'App')?.Value;
const tags = response.Tags ?? [];
const entries = tags.flatMap((tag: Tag) =>
tag.Key && tag.Value ? [[tag.Key, tag.Value]] : [],
);
return Object.fromEntries(entries) as Tags;
};
Loading

0 comments on commit b77f1c0

Please sign in to comment.