Given a table cdk object, how can I list the secondary indexes it has?
This is the tricky bit. The indexes are not available on the ITable, only the CfnTable. Getting from the ITable to the CfnTable can be done through table.node.defaultChild. Then the variables with the indexes have to be resolved in the CDK stack.
Having retrieved the secondary indexes, how can I [know] if they are local or global?
This is the easy bit. The indexes are in separate variables, globalSecondaryIndexes and localSecondaryIndexes.
Having retrieved a global secondary index, how can I get the metrics associated with it; capacity usage and throttled requests?
By passing { GlobalSecondaryIndexName: <indexName> } to the dimensions parameter of the metric call.
Below is a class, based on something I just built for work, that does all of the above. It compiles and should even run (not 100% sure it will run because I removed some intermediate scaffolding from our solution and haven't tested this exact code).
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
import * as dynamo from '@aws-cdk/aws-dynamodb';
import { Construct, Duration } from '@aws-cdk/core';
export class DynamoMonitor extends Construct {
private static getIndexNames(dynamoTable: dynamo.ITable) {
// pull the names of any indexes on the current table from construct
const table = dynamoTable.node.defaultChild as dynamo.CfnTable;
const indexes = dynamoTable.stack.resolve(table.globalSecondaryIndexes) as
Array<dynamo.CfnTable.GlobalSecondaryIndexProperty> | undefined;
const indexNames: string[] = [];
if (indexes) {
for (const index of indexes) {
indexNames.push(index.indexName);
}
}
return indexNames;
}
constructor(scope: Construct, id: string, dynamoTable: dynamo.ITable) {
super(scope, id);
const period = Duration.seconds(30);
const threshold = 50;
const evaluationPeriods = 5;
const indexNames = DynamoMonitor.getIndexNames(dynamoTable);
for (const indexName of indexNames) {
const throttleEvents = dynamoTable.metric('WriteThrottleEvents', {
period: period,
dimensions: { GlobalSecondaryIndexName: indexName },
statistic: cloudwatch.Statistic.SAMPLE_COUNT,
unit: cloudwatch.Unit.COUNT,
});
const consumedWriteCapacityUnits = dynamoTable.metricConsumedWriteCapacityUnits({
label: 'ConsumedWriteCapacityUnits',
dimensions: { GlobalSecondaryIndexName: indexName },
period: period,
statistic: cloudwatch.Statistic.SAMPLE_COUNT,
unit: cloudwatch.Unit.COUNT,
});
const throttleRate = new cloudwatch.MathExpression({
expression: '(throttleEvents/consumedWriteCapacityUnits) * 100',
label: 'WriteThrottleRate',
usingMetrics: {
throttleEvents: throttleEvents,
consumedWriteCapacityUnits: consumedWriteCapacityUnits,
},
});
throttleRate.createAlarm(this, `WriteIndex${indexName}ThrottleRateAlarm`, {
threshold: threshold,
evaluationPeriods: evaluationPeriods,
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
alarmDescription: 'this.description',
treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
});
}
}
}