Skip to content

Commit

Permalink
Capture githubRateLimitRemaining metric in CloudWatch
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebroberts committed Sep 23, 2024
1 parent d3bd054 commit 7c0b4f6
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/app/domain/github/crawler/crawlInstallation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export async function crawlInstallation(
logger.info(`Crawling Installation for ${installation.accountLogin}`)
const githubInstallationClient = appState.githubClient.clientForInstallation(installation.installationId)
await crawlUsers(appState, installation, githubInstallationClient)
publishGithubInstallationClientMetrics(installation, githubInstallationClient)
publishGithubInstallationClientMetrics(githubInstallationClient)
const repos = await crawlRepositories(appState, installation, githubInstallationClient)
// Eventually consider doing some parallelization here (or move back to step function) but
// need to be careful since GitHub gets twitchy about concurrent requests to the API
Expand All @@ -25,6 +25,6 @@ export async function crawlInstallation(
await crawlPushes(appState, installation, repo, githubInstallationClient)
await crawlWorkflowRunEvents(appState, installation, repo, lookbackDays, githubInstallationClient)
}
publishGithubInstallationClientMetrics(installation, githubInstallationClient)
publishGithubInstallationClientMetrics(githubInstallationClient)
logger.info('Github Metadata after crawls', { ...githubInstallationClient.meta() })
}
11 changes: 5 additions & 6 deletions src/app/outboundInterfaces/githubInstallationClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { RawGithubWorkflowRunEvent } from '../domain/types/rawGithub/RawGithubWo
import { RawGithubRepository } from '../domain/types/rawGithub/RawGithubRepository'
import { RawGithubUser } from '../domain/types/rawGithub/RawGithubUser'
import { RawGithubEvent } from '../domain/types/rawGithub/RawGithubEvent'
import { GithubInstallation } from '../domain/types/GithubInstallation'
import { metrics } from '../util/metrics'
import { MetricUnit } from '@aws-lambda-powertools/metrics'

Expand Down Expand Up @@ -132,13 +131,13 @@ export type OctokitResponseHeaders = {
}

// ToEventually - move this into the actual GithubInstallationClient object
export function publishGithubInstallationClientMetrics(
installation: GithubInstallation,
githubInstallationClient: GithubInstallationClient
) {
export function publishGithubInstallationClientMetrics(githubInstallationClient: GithubInstallationClient) {
// Eventually considering adding "installation" as a dimension here to allow different metrics / alarms
// for different installations. The reason I didn't just do that immediately is that, for now, Alarms
// are defined at deployment time, but installations are a runtime concept.
const rateLimitMetric = metrics.singleMetric()
rateLimitMetric.addDimension('installationAccount', installation.accountLogin)
rateLimitMetric.addMetric(
// ToEventually - this is a shared string with CDK so move to constant
'githubRateLimitRemaining',
MetricUnit.Count,
githubInstallationClient.meta().ratelimitRemaining
Expand Down
3 changes: 3 additions & 0 deletions src/cdk/stacks/main/MainStack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { saveInSSMViaCloudFormation } from '../../support/ssm'
import { SSM_PARAM_NAMES, SsmParamName } from '../../../multipleContexts/ssmParams'
import { defineGithubCrawlers } from './githubCrawlers'
import { ReportingStack } from './reporting/ReportingStack'
import { defineMonitoring } from './monitoring'

export class MainStack extends Stack {
constructor(scope: Construct, id: string, props: AllStacksProps) {
Expand All @@ -32,6 +33,8 @@ export class MainStack extends Stack {

savePreGeneratedConfiguration(this, props)

defineMonitoring(this, mainStackProps)

new ReportingStack(this, 'ReportingStack', {
...props,
stackName: `${props.appName}-reporting`
Expand Down
29 changes: 29 additions & 0 deletions src/cdk/stacks/main/monitoring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Alarm, ComparisonOperator, Metric, TreatMissingData } from 'aws-cdk-lib/aws-cloudwatch'
import { Construct } from 'constructs'
import { MainStackProps } from './mainStackProps'
import { Duration } from 'aws-cdk-lib'
import { SnsAction } from 'aws-cdk-lib/aws-cloudwatch-actions'
import { Topic } from 'aws-cdk-lib/aws-sns'

export function defineMonitoring(scope: Construct, props: MainStackProps) {
const githubRateLimitRemainingAlarm = new Alarm(scope, 'Errors', {
comparisonOperator: ComparisonOperator.LESS_THAN_THRESHOLD,
threshold: 1000,
evaluationPeriods: 1,
treatMissingData: TreatMissingData.IGNORE,
alarmName: `${props.appName} - Github Rate Limit Remaining`,
metric: new Metric({
namespace: 'cicada',
dimensionsMap: {
service: props.appName
},
// ToEventually - this is a shared string with app code so move to constant
metricName: 'githubRateLimitRemaining',
statistic: 'Minimum',
period: Duration.days(1)
})
})

const actionTopic = new Topic(scope, 'alarmActionTopic', { topicName: `${props.appName}-alarms` })
githubRateLimitRemainingAlarm.addAlarmAction(new SnsAction(actionTopic))
}

0 comments on commit 7c0b4f6

Please sign in to comment.