Skip to content

Commit

Permalink
fix: Revert "feat(dashboards): improve customizability (#349)" (#354)
Browse files Browse the repository at this point in the history
This reverts commit 6db09b0.

This had some unexpected effects on extended uses of the library. We'll do a followup to this to reintroduce the change but with a major version bump.

---

_By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license_
  • Loading branch information
echeung-amzn authored Apr 11, 2023
1 parent 7f02cf6 commit acd69cb
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 1,566 deletions.
1,078 changes: 10 additions & 1,068 deletions API.md

Large diffs are not rendered by default.

73 changes: 0 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,79 +265,6 @@ This is a general procedure on how to do it:

Both of these monitoring base classes are dashboard segments, so you can add them to your monitoring by calling `.addSegment()` on the `MonitoringFacade`.

### Custom dashboards

If you want *even* more flexibility, you can take complete control over dashboard generation by leveraging dynamic dashboarding features. This allows you to create an arbitrary number of dashboards while configuring each of them separately. You can do this in three simple steps:

1. Create a dynamic dashboard factory
2. Create `IDynamicDashboardSegment` implementations
3. Add Dynamic Segments to your `MonitoringFacade`

#### Create a dynamic dashboard factory

The below code sample will generate two dashboards with the following names:
* ExampleDashboards-HostedService
* ExampleDashboards-Infrastructure


```ts
// create the dynamic dashboard factory.
const factory = new DynamicDashboardFactory(stack, "DynamicDashboards", {
dashboardNamePrefix: "ExampleDashboards",
dashboardConfigs: [
// 'name' is the minimum required configuration
{ name: "HostedService" },
// below is an example of additional dashboard-specific config options
{
name: "Infrastructure",
range: Duration.hours(3),
periodOverride: PeriodOverride.AUTO,
renderingPreference: DashboardRenderingPreference.BITMAP_ONLY
},
],
});
```

#### Create `IDynamicDashboardSegment` implementations
For each construct you want monitored, you will need to create an implementation of an `IDynamicDashboardSegment`. The following is a basic reference implementation as an example:

```ts
export enum DashboardTypes {
HostedService = "HostedService",
Infrastructure = "Infrastructure",
}

class ExampleSegment implements IDynamicDashboardSegment {
widgetsForDashboard(name: string): IWidget[] {
// this logic is what's responsible for allowing your dynamic segment to return
// different widgets for different dashboards
switch (name) {
case DashboardTypes.HostedService:
return [new TextWidget({ markdown: "This shows metrics for your service hosted on AWS Infrastructure" })];
case DashboardTypes.Infrastructure:
return [new TextWidget({ markdown: "This shows metrics for the AWS Infrastructure supporting your hosted service" })];
default:
throw new Error("Unexpected dashboard name!");
}
}
}
```

#### Add Dynamic Segments to MonitoringFacade

When you have instances of an `IDynamicDashboardSegment` to use, they can be added to your dashboard like this:

```ts
monitoring.addDynamicSegment(new ExampleSegment());
```

Now, this widget will be added to both dashboards and will show different content depending on the dashboard. Using the above example code, two dashboards will be generated with the following content:

* Dashboard Name: "ExampleDashboards-HostedService"
* Content: "This shows metrics for your service hosted on AWS Infrastructure"
* Dashboard Name: "ExampleDashboards-Infrastructure"
* Content: "This shows metrics for the AWS Infrastructure supporting your hosted service"

### Monitoring scopes

You can monitor complete CDK construct scopes using an aspect. It will automatically discover all monitorable resources within the scope recursively and add them to your dashboard.
Expand Down
19 changes: 1 addition & 18 deletions lib/common/monitoring/Monitoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { IWidget } from "aws-cdk-lib/aws-cloudwatch";

import { MonitoringScope } from "./MonitoringScope";
import {
DefaultDashboards,
IDashboardSegment,
IDynamicDashboardSegment,
MonitoringDashboardsOverrideProps,
UserProvidedNames,
} from "../../dashboard";
Expand All @@ -30,9 +28,7 @@ export interface BaseMonitoringProps
/**
* An independent unit of monitoring. This is the base for all monitoring classes with alarm support.
*/
export abstract class Monitoring
implements IDashboardSegment, IDynamicDashboardSegment
{
export abstract class Monitoring implements IDashboardSegment {
protected readonly scope: MonitoringScope;
protected readonly alarms: AlarmWithAnnotation[];
protected readonly localAlarmNamePrefixOverride?: string;
Expand Down Expand Up @@ -105,17 +101,4 @@ export abstract class Monitoring
* Returns widgets to be placed on the main dashboard.
*/
abstract widgets(): IWidget[];

widgetsForDashboard(name: string): IWidget[] {
switch (name) {
case DefaultDashboards.SUMMARY:
return this.summaryWidgets();
case DefaultDashboards.DETAIL:
return this.widgets();
case DefaultDashboards.ALARMS:
return this.alarmWidgets();
default:
return [];
}
}
}
73 changes: 17 additions & 56 deletions lib/dashboard/DefaultDashboardFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import {
PeriodOverride,
} from "aws-cdk-lib/aws-cloudwatch";
import { Construct } from "constructs";

import { BitmapDashboard } from "./BitmapDashboard";
import { DashboardRenderingPreference } from "./DashboardRenderingPreference";
import { DashboardWithBitmapCopy } from "./DashboardWithBitmapCopy";
import { IDynamicDashboardSegment } from "./DynamicDashboardSegment";
import { IDashboardFactory, IDashboardFactoryProps } from "./IDashboardFactory";
import { IDynamicDashboardFactory } from "./IDynamicDashboardFactory";

export interface MonitoringDashboardsProps {
/**
Expand Down Expand Up @@ -68,25 +67,15 @@ export interface MonitoringDashboardsProps {
readonly renderingPreference?: DashboardRenderingPreference;
}

export enum DefaultDashboards {
SUMMARY = "Summary",
DETAIL = "Detail",
ALARMS = "Alarms",
}

export class DefaultDashboardFactory
extends Construct
implements IDashboardFactory, IDynamicDashboardFactory
implements IDashboardFactory
{
// Legacy Dashboard Fields
readonly dashboard?: Dashboard;
readonly summaryDashboard?: Dashboard;
readonly alarmDashboard?: Dashboard;
readonly anyDashboardCreated: boolean;

// Dynamic Dashboard Fields
readonly dashboards: Record<string, Dashboard> = {};

constructor(scope: Construct, id: string, props: MonitoringDashboardsProps) {
super(scope, id);

Expand Down Expand Up @@ -119,7 +108,6 @@ export class DefaultDashboardFactory
periodOverride:
props.detailDashboardPeriodOverride ?? PeriodOverride.INHERIT,
});
this.dashboards[DefaultDashboards.DETAIL] = this.dashboard;
}
if (createSummaryDashboard) {
anyDashboardCreated = true;
Expand All @@ -133,7 +121,6 @@ export class DefaultDashboardFactory
props.summaryDashboardPeriodOverride ?? PeriodOverride.INHERIT,
}
);
this.dashboards[DefaultDashboards.SUMMARY] = this.summaryDashboard;
}
if (createAlarmDashboard) {
anyDashboardCreated = true;
Expand All @@ -147,12 +134,26 @@ export class DefaultDashboardFactory
props.detailDashboardPeriodOverride ?? PeriodOverride.INHERIT,
}
);
this.dashboards[DefaultDashboards.ALARMS] = this.alarmDashboard;
}

this.anyDashboardCreated = anyDashboardCreated;
}

protected createDashboard(
renderingPreference: DashboardRenderingPreference,
id: string,
props: DashboardProps
) {
switch (renderingPreference) {
case DashboardRenderingPreference.INTERACTIVE_ONLY:
return new Dashboard(this, id, props);
case DashboardRenderingPreference.BITMAP_ONLY:
return new BitmapDashboard(this, id, props);
case DashboardRenderingPreference.INTERACTIVE_AND_BITMAP:
return new DashboardWithBitmapCopy(this, id, props);
}
}

addSegment(props: IDashboardFactoryProps) {
if ((props.overrideProps?.addToDetailDashboard ?? true) && this.dashboard) {
this.dashboard.addWidgets(...props.segment.widgets());
Expand All @@ -171,33 +172,6 @@ export class DefaultDashboardFactory
}
}

addDynamicSegment(segment: IDynamicDashboardSegment): void {
this.dashboard?.addWidgets(
...segment.widgetsForDashboard(DefaultDashboards.DETAIL)
);
this.summaryDashboard?.addWidgets(
...segment.widgetsForDashboard(DefaultDashboards.SUMMARY)
);
this.alarmDashboard?.addWidgets(
...segment.widgetsForDashboard(DefaultDashboards.ALARMS)
);
}

protected createDashboard(
renderingPreference: DashboardRenderingPreference,
id: string,
props: DashboardProps
) {
switch (renderingPreference) {
case DashboardRenderingPreference.INTERACTIVE_ONLY:
return new Dashboard(this, id, props);
case DashboardRenderingPreference.BITMAP_ONLY:
return new BitmapDashboard(this, id, props);
case DashboardRenderingPreference.INTERACTIVE_AND_BITMAP:
return new DashboardWithBitmapCopy(this, id, props);
}
}

createdDashboard(): Dashboard | undefined {
return this.dashboard;
}
Expand All @@ -209,17 +183,4 @@ export class DefaultDashboardFactory
createdAlarmDashboard(): Dashboard | undefined {
return this.alarmDashboard;
}

getDashboard(name: string): Dashboard | undefined {
switch (name) {
case DefaultDashboards.SUMMARY:
return this.summaryDashboard;
case DefaultDashboards.DETAIL:
return this.dashboard;
case DefaultDashboards.ALARMS:
return this.alarmDashboard;
default:
throw new Error("Unexpected dashboard name!");
}
}
}
133 changes: 0 additions & 133 deletions lib/dashboard/DynamicDashboardFactory.ts

This file was deleted.

Loading

0 comments on commit acd69cb

Please sign in to comment.