Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
corymhall committed Sep 5, 2023
1 parent 0dae1b5 commit f3c6e78
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 91 deletions.
16 changes: 8 additions & 8 deletions .projen/deps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions .projenrc.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { awscdk } from 'projen';
import { Transform } from 'projen/lib/javascript';
import { EcsAutoDiscover, LambdaAutoDiscover } from './projenrc/auto-discover';
const alphaVersion = '^2.86.0-alpha.0';
const alphaVersion = '^2.87.0-alpha.0';
const project = new awscdk.AwsCdkTypeScriptApp({
cdkVersion: '2.83.0',
cdkVersion: '2.87.0',
defaultReleaseBranch: 'main',
name: 'cdk-example-app',
projenrcTs: true,
Expand Down Expand Up @@ -72,9 +72,9 @@ project.addTask('deploy', {
// project.cdkConfig.json.addOverride('app', 'npx ts-node -P tsconfig.json --prefer-ts-exts src/main.ts');
// project.cdkConfig.json.addOverride('app', 'npx node -r ts-node/register --inspect-brk src/main.ts');
const buildCommand = 'yarn projen && yarn projen compile && yarn projen bundle';
// project.tsconfig?.file.addOverride('ts-node', {
// swc: true,
// });
project.tsconfig?.file.addOverride('ts-node', {
swc: true,
});
project.tsconfigDev.file.addOverride('ts-node', {
swc: true,
});
Expand Down
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,84 @@ pipeline.addStage(new AppStage(app, 'ProdStage', {
},
}));
```

## Operating the application

Everything described above helps you get an application deployed to production,
but it doesn't help very much with operating the application. I haven't set up
any monitoring or observability, there are no metrics, alarms, or dashboards.

### Monitoring

Monitoring/observability can be broadly split between two layers; the
Infrastructure layer, and the application layer.

#### Application layer

At the application layer we need to determine what our business metrics are.
This is very specific to the individual components in our application. If we
take the `GetPost` component, we might say the metric we care about is the
number of `getPost` requests we receive. For that we will need to update our
application logic to emit this metric.

Using the [Lambda Powertools]() library we can do this using `Metrics`
[src/posts/get-post.ecs-task.ts](./src/posts/get-post.ecs-task.ts)
```ts
const metrics = new Metrics();

app.get('/posts/:id', async (req: Request, res: Response) => {
try {
// get the item
metrics.addMetric('getItemSuccess', Metrics.Count, 1);
} catch (e) {
metrics.addMetric('getItemFailure', Metrics.Count, 1);
}
});
```

Then we can monitor that metric, add it to a dashboard and setup alarms based on
what we expect it to be.

```ts
const getItemSuccessMetric = new Metric({
metricName: 'getItemSuccess',
dimensionsMap: { service: 'GetPost' },
namespace: 'blogApp',
});

new GraphWidget({
left: [getItemSuccessMetric],
});
```

Using the [ecs-monitoring-constructs]() I might setup anomaly detection for this
metric since I expect to have different levels depending on the time of day or
day of the week.

```ts
const getItemSuccessMetric = new Metric({...});
const facade = new MonitoringFacade();
const metricFactory = facade.createMetricFactory();
const alarmFactory = facade.createAlarmFactory();
const getItemAnomalyMetric = metricFactory.createMetricAnomalyDetection(
getItemSuccessMetric,
3, // standard deviation
'getItemSuccess', // label
undefined, // color
'getItemSuccess', // expressionId
);
alarmFactory.addAlarmWhenOutOfBand(
getItemAnomalyMetric,
'getItemSuccess-Anomaly', // alarm name suffix
'Warning', // disambiguator
{
alarmWhenAboveBand: false,
alarmWhenBelowBand: true,
standardDeviationForAlarm: 4,
},
);
```

#### Infrastructure layer


18 changes: 9 additions & 9 deletions package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class AppStage extends Stage {
const appStack = new Stack(this, 'AppStack');
const network = new Network(appStack, 'Network', { });


// ------------Create Rest API-------------------
const api = new Api(appStack, 'Api', { monitor, vpc: network.cluster.vpc });

Expand Down
7 changes: 4 additions & 3 deletions src/constructs/fargate-service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Duration } from 'aws-cdk-lib';
import { Alarm, Metric, TreatMissingData, Unit } from 'aws-cdk-lib/aws-cloudwatch';
import { SubnetType } from 'aws-cdk-lib/aws-ec2';
import { DeploymentControllerType, FargatePlatformVersion, FargateTaskDefinition, ICluster, FargateService, IFargateTaskDefinition, CfnService } from 'aws-cdk-lib/aws-ecs';
import { DeploymentControllerType, FargatePlatformVersion, FargateTaskDefinition, ICluster, FargateService, IFargateTaskDefinition, CfnService, LaunchType } from 'aws-cdk-lib/aws-ecs';
import { Rule } from 'aws-cdk-lib/aws-events';
import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
import { DnsRecordType } from 'aws-cdk-lib/aws-servicediscovery';
Expand Down Expand Up @@ -46,7 +46,9 @@ export class ApiGatewayService extends Construct {
const logGroup = new LogGroup(this, 'LogGroup', {
retention: RetentionDays.ONE_MONTH,
});
const taskDefinition = new FargateTaskDefinition(this, 'TaskDef', { });
const taskDefinition = new FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: 1024,
});

taskDefinition.addExtension(props.appContainer.bind(logGroup));
taskDefinition.addExtension(Extensions.xray(logGroup));
Expand All @@ -55,7 +57,6 @@ export class ApiGatewayService extends Construct {
const service = new FargateService(this, 'AppService', {
enableECSManagedTags: true,
minHealthyPercent: 50,
platformVersion: FargatePlatformVersion.VERSION1_4,
cluster: props.cluster,
circuitBreaker: {
rollback: true,
Expand Down
14 changes: 10 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard';
// import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard';
import { LinuxBuildImage } from 'aws-cdk-lib/aws-codebuild';
import { App, Stack } from 'aws-cdk-lib/core';
import * as cr from 'aws-cdk-lib/custom-resources';
import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines';
import { AppStage } from './app';

const app = new App({
policyValidationBeta1: [new CfnGuardValidator({
controlTowerRulesEnabled: false,
})],
postCliContext: {
'@aws-cdk/core:validationReportJson': true,
},
Expand Down Expand Up @@ -56,6 +54,14 @@ const pipeline = new CodePipeline(pipelineStack, 'DeliveryPipeline', {
crossAccountKeys: true,
useChangeSets: false,
});
new cr.AwsCustomResource(pipelineStack, 'CR', {
onUpdate: {
action: 'some',
service: 'service',
physicalResourceId: cr.PhysicalResourceId.of('abc'),
},
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE }),
});

/**
* Add a stage to the deployment pipeline for my pre-prod environment
Expand Down
5 changes: 4 additions & 1 deletion tsconfig.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f3c6e78

Please sign in to comment.