Skip to content

Commit

Permalink
feat: updated telemetry with tags (#37)
Browse files Browse the repository at this point in the history
* updated telemetry with tags

* pr suggestions
  • Loading branch information
tobuck-aws committed May 9, 2024
1 parent d6ddff8 commit 5017ae0
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 30 deletions.
2 changes: 2 additions & 0 deletions src/control-plane/auth/cognito-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Runtime, IFunction, LayerVersion } from 'aws-cdk-lib/aws-lambda';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { IAuth } from './auth-interface';
import { addTemplateTag } from '../../utils';

/**
* Properties for the CognitoAuth construct.
Expand Down Expand Up @@ -105,6 +106,7 @@ export class CognitoAuth extends Construct implements IAuth {

constructor(scope: Construct, id: string, props: CognitoAuthProps) {
super(scope, id);
addTemplateTag(this, 'CognitoAuth');

const idpName = 'COGNITO';
const systemAdminRoleName = props.systemAdminRoleName ?? 'SystemAdmin';
Expand Down
3 changes: 2 additions & 1 deletion src/control-plane/billing/billing-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { IFunction } from 'aws-cdk-lib/aws-lambda';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { IBilling, IFunctionTrigger } from './billing-interface';
import { DetailType, IEventManager } from '../../utils';
import { DetailType, IEventManager, addTemplateTag } from '../../utils';

/**
* Encapsulates the list of properties for a BillingProvider.
Expand Down Expand Up @@ -54,6 +54,7 @@ export class BillingProvider extends Construct {
*/
constructor(scope: Construct, id: string, props: BillingProviderProps) {
super(scope, id);
addTemplateTag(this, 'BillingProvider');

this.createEventTarget(
props.eventManager,
Expand Down
3 changes: 2 additions & 1 deletion src/control-plane/control-plane-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { IAuth } from './auth/auth-interface';
import { Services } from './services';
import { addTemplateTag } from '../utils';

export interface ControlPlaneAPIProps {
readonly services: Services;
Expand All @@ -26,7 +27,7 @@ export class ControlPlaneAPI extends Construct {
public readonly tenantUpdateServiceTarget: targets.ApiGateway;
constructor(scope: Construct, id: string, props: ControlPlaneAPIProps) {
super(scope, id);

addTemplateTag(this, 'ControlPlaneAPI');
let options: any = {
defaultCorsPreflightOptions: {
allowOrigins: apigateway.Cors.ALL_ORIGINS,
Expand Down
4 changes: 2 additions & 2 deletions src/control-plane/control-plane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Services } from './services';
import { Tables } from './tables';
import { TenantConfigService } from './tenant-config/tenant-config-service';
import { DestroyPolicySetter } from '../cdk-aspect/destroy-policy-setter';
import { setTemplateDesc, DetailType, EventManager, IEventManager } from '../utils';
import { addTemplateTag, DetailType, EventManager, IEventManager } from '../utils';

export interface ControlPlaneProps {
/**
Expand Down Expand Up @@ -55,7 +55,7 @@ export class ControlPlane extends Construct {

constructor(scope: Construct, id: string, props: ControlPlaneProps) {
super(scope, id);
setTemplateDesc(this, 'SaaS Builder Toolkit - CoreApplicationPlane (uksb-1tupboc57)');
addTemplateTag(this, 'ControlPlane');

cdk.Aspects.of(this).add(new DestroyPolicySetter());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { IDataIngestorAggregator } from './ingestor-aggregator-interface';
import { addTemplateTag } from '../../utils';

/**
* Encapsulates the list of properties for a FirehoseAggregator construct.
Expand Down Expand Up @@ -68,6 +69,7 @@ export class FirehoseAggregator extends Construct implements IDataIngestorAggreg

constructor(scope: Construct, id: string, props: FirehoseAggregatorProps) {
super(scope, id);
addTemplateTag(this, 'FirehoseAggregator');

const serviceName = 'FirehoseAggregator';

Expand Down
3 changes: 2 additions & 1 deletion src/control-plane/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { Table, AttributeType, ProjectionType } from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
import { addTemplateTag } from '../utils';

export class Tables extends Construct {
public readonly tenantDetails: Table;
Expand All @@ -14,7 +15,7 @@ export class Tables extends Construct {
public readonly tenantIdColumn: string = 'tenantId';
constructor(scope: Construct, id: string) {
super(scope, id);

addTemplateTag(this, 'Tables');
this.tenantDetails = new Table(this, 'TenantDetails', {
partitionKey: { name: this.tenantIdColumn, type: AttributeType.STRING },
pointInTimeRecovery: true,
Expand Down
2 changes: 2 additions & 0 deletions src/control-plane/tenant-config/tenant-config-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Table } from 'aws-cdk-lib/aws-dynamodb';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { addTemplateTag } from '../../utils';

export interface TenantConfigServiceProps {
readonly tenantDetails: Table;
Expand All @@ -20,6 +21,7 @@ export class TenantConfigService extends Construct {
public readonly tenantConfigServiceLambda: lambda.Function;
constructor(scope: Construct, id: string, props: TenantConfigServiceProps) {
super(scope, id);
addTemplateTag(this, 'TenantConfigService');

// https://docs.powertools.aws.dev/lambda/python/2.31.0/#lambda-layer
const lambdaPowerToolsLayerARN = `arn:aws:lambda:${
Expand Down
2 changes: 2 additions & 0 deletions src/core-app-plane/bash-job-orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as tasks from 'aws-cdk-lib/aws-stepfunctions-tasks';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { BashJobRunner } from './bash-job-runner';
import { addTemplateTag } from '../utils';

/**
* Encapsulates the list of properties for a BashJobOrchestrator.
Expand Down Expand Up @@ -67,6 +68,7 @@ export class BashJobOrchestrator extends Construct {

constructor(scope: Construct, id: string, props: BashJobOrchestratorProps) {
super(scope, id);
addTemplateTag(this, 'BashJobOrchestrator');

const eventSource = props.eventSource;
const detailType = props.detailType;
Expand Down
3 changes: 3 additions & 0 deletions src/core-app-plane/bash-job-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as iam from 'aws-cdk-lib/aws-iam';
import * as kms from 'aws-cdk-lib/aws-kms';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { addTemplateTag } from '../utils';

/**
* Encapsulates the list of properties for a BashJobRunner.
Expand Down Expand Up @@ -75,6 +76,8 @@ export class BashJobRunner extends Construct {

constructor(scope: Construct, id: string, props: BashJobRunnerProps) {
super(scope, id);
addTemplateTag(this, 'BashJobRunner');

const environmentVariablesOverride: {
name: string;
value: string;
Expand Down
4 changes: 2 additions & 2 deletions src/core-app-plane/core-app-plane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
import { BashJobOrchestrator } from './bash-job-orchestrator';
import { BashJobRunner } from './bash-job-runner';
import { EventManager, IEventManager, DetailType, setTemplateDesc } from '../utils';
import { EventManager, IEventManager, DetailType, addTemplateTag } from '../utils';

/**
* Encapsulates the list of properties for a CoreApplicationPlaneJobRunner.
Expand Down Expand Up @@ -95,7 +95,7 @@ export class CoreApplicationPlane extends Construct {

constructor(scope: Construct, id: string, props: CoreApplicationPlaneProps) {
super(scope, id);
setTemplateDesc(this, 'SaaS Builder Toolkit - CoreApplicationPlane (uksb-1tupboc57)');
addTemplateTag(this, 'CoreApplicationPlane');
this.eventManager = props.eventManager ?? new EventManager(this, 'EventManager');
const eventBus = EventBus.fromEventBusArn(this, 'EventBus', this.eventManager.busArn);

Expand Down
2 changes: 2 additions & 0 deletions src/utils/event-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { IEventBus, Rule, IRuleTarget, EventBus } from 'aws-cdk-lib/aws-events';
import { IGrantable } from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
import { addTemplateTag } from './utils';

/**
* Provides an easy way of accessing event detail types.
Expand Down Expand Up @@ -221,6 +222,7 @@ export class EventManager extends Construct implements IEventManager {

constructor(scope: Construct, id: string, props?: EventManagerProps) {
super(scope, id);
addTemplateTag(this, 'EventManager');
this.eventBus = props?.eventBus ?? new EventBus(this, 'SbtEventBus');
this.busName = this.eventBus.eventBusName;
this.busArn = this.eventBus.eventBusArn;
Expand Down
41 changes: 39 additions & 2 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,45 @@
import { Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export const setTemplateDesc = (construct: Construct, sbtDesc: string) => {
export const addTemplateTag = (construct: Construct, tag: string) => {
const stackDesc = Stack.of(construct).templateOptions.description;
let description = stackDesc === undefined ? sbtDesc : stackDesc + ' - ' + sbtDesc;
const baseTelemetry = 'sbt-aws (uksb-1tupboc57)';
let description = stackDesc;
// There is no description, just make it telemetry + tags
if (stackDesc === undefined) {
description = appendTagToDescription(baseTelemetry, tag);
}
// There is a description, and it doesn't contain telemetry. We need to append telemetry + tags to it
else if (!stackDesc.includes(baseTelemetry)) {
description = appendTagToDescription(`${stackDesc} - ${baseTelemetry}`, tag);
}
// There is a telemetry description already
else {
description = appendTagToDescription(stackDesc, tag);
}
Stack.of(construct).templateOptions.description = description;
};

const appendTagToDescription = (existingDescription: string, newTag: string): string => {
// Check if the existing description already has tags
if (existingDescription.includes('(Tags:')) {
// Extract the existing tags
const startIndex = existingDescription.indexOf('(Tags:') + 6;
const endIndex = existingDescription.lastIndexOf(')');
const existingTags = existingDescription.substring(startIndex, endIndex).split(', ');

// Check if the new tag already exists
if (!existingTags.includes(newTag)) {
// Append the new tag to the existing tags
existingTags.push(newTag);
const newDescription = `${existingDescription.substring(0, startIndex)}${existingTags.join(', ')})`;
return newDescription;
} else {
// The new tag already exists, return the original description
return existingDescription;
}
} else {
// Append the new tag to the description
return `${existingDescription} (Tags: ${newTag})`;
}
};
21 changes: 0 additions & 21 deletions test/control-plane.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,6 @@ describe('ControlPlane Targets', () => {
});
});

describe('ControlPlane description', () => {
it('should have a fixed template description, when the containing stack does not have description', () => {
const stackWithoutDescription = new TestStack(app, 'stackWithoutDescription', {
systemAdminEmail: '[email protected]',
});
const actual = stackWithoutDescription.templateOptions.description;
const expected = 'SaaS Builder Toolkit - CoreApplicationPlane (uksb-1tupboc57)';
expect(actual).toStrictEqual(expected);
});

it('should have a concatenated template description, when the containing stack has an existing desc', () => {
const stackWithDescription = new TestStack(app, 'stackWithDescription', {
systemAdminEmail: '[email protected]',
description: 'ABC',
});
const actual = stackWithDescription.templateOptions.description;
const expected = 'ABC - SaaS Builder Toolkit - CoreApplicationPlane (uksb-1tupboc57)';
expect(expected).toStrictEqual(actual);
});
});

describe('ControlPlane cloudwatch roles', () => {
it('should create the cloudwatch IAM apigw push to cw role by default', () => {
const stackWithLogging = new TestStack(new cdk.App(), 'stackWithLogging', {
Expand Down
43 changes: 43 additions & 0 deletions test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { App, Stack } from 'aws-cdk-lib';
import { addTemplateTag } from '../src/utils';
const app = new App();
const telemetryConst = 'sbt-aws (uksb-1tupboc57)';

describe('addTemplateTag', () => {
it('should append telemetry and tags to existing template description', () => {
const stackA = new Stack(app, 'TestStackA', { description: 'test' });
const newTag = 'new-tag';
const expectedDescription = `test - ${telemetryConst} (Tags: new-tag)`;
addTemplateTag(stackA, newTag);
expect(stackA.templateOptions.description).toBe(expectedDescription);
});

it('should append a new tag to the description if it does not have any tags', () => {
const stackB = new Stack(app, 'TestStackB');
const newTag = 'new-tag';
const expectedDescription = `${telemetryConst} (Tags: new-tag)`;
addTemplateTag(stackB, newTag);
expect(stackB.templateOptions.description).toBe(expectedDescription);
});

it('should append a new tag to the existing tags in the description', () => {
const existingDescription = `This is a sample description - ${telemetryConst} (Tags: tag1, tag2)`;
const stackC = new Stack(app, 'TestStackC', { description: existingDescription });
const newTag = 'new-tag';
const expectedDescription = `This is a sample description - ${telemetryConst} (Tags: tag1, tag2, new-tag)`;
addTemplateTag(stackC, newTag);
expect(stackC.templateOptions.description).toBe(expectedDescription);
});

it('should not append a new tag if it already exists in the description', () => {
const existingDescription = `This is a sample description - ${telemetryConst} (Tags: tag1, tag2, new-tag)`;
const stackD = new Stack(app, 'TestStackD', { description: existingDescription });
const newTag = 'new-tag';
const expectedDescription = `This is a sample description - ${telemetryConst} (Tags: tag1, tag2, new-tag)`;
addTemplateTag(stackD, newTag);
expect(stackD.templateOptions.description).toBe(expectedDescription);
});
});

0 comments on commit 5017ae0

Please sign in to comment.