@composurecdk/neptune 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -0
- package/dist/commonjs/cluster-alarm-config.d.ts +77 -0
- package/dist/commonjs/cluster-alarm-config.d.ts.map +1 -0
- package/dist/commonjs/cluster-alarm-config.js +3 -0
- package/dist/commonjs/cluster-alarm-config.js.map +1 -0
- package/dist/commonjs/cluster-alarm-defaults.d.ts +20 -0
- package/dist/commonjs/cluster-alarm-defaults.d.ts.map +1 -0
- package/dist/commonjs/cluster-alarm-defaults.js +52 -0
- package/dist/commonjs/cluster-alarm-defaults.js.map +1 -0
- package/dist/commonjs/cluster-alarms.d.ts +25 -0
- package/dist/commonjs/cluster-alarms.d.ts.map +1 -0
- package/dist/commonjs/cluster-alarms.js +133 -0
- package/dist/commonjs/cluster-alarms.js.map +1 -0
- package/dist/commonjs/cluster-builder.d.ts +194 -0
- package/dist/commonjs/cluster-builder.d.ts.map +1 -0
- package/dist/commonjs/cluster-builder.js +140 -0
- package/dist/commonjs/cluster-builder.js.map +1 -0
- package/dist/commonjs/cluster-defaults.d.ts +19 -0
- package/dist/commonjs/cluster-defaults.d.ts.map +1 -0
- package/dist/commonjs/cluster-defaults.js +87 -0
- package/dist/commonjs/cluster-defaults.js.map +1 -0
- package/dist/commonjs/cluster-parameter-group-defaults.d.ts +30 -0
- package/dist/commonjs/cluster-parameter-group-defaults.d.ts.map +1 -0
- package/dist/commonjs/cluster-parameter-group-defaults.js +53 -0
- package/dist/commonjs/cluster-parameter-group-defaults.js.map +1 -0
- package/dist/commonjs/index.d.ts +6 -0
- package/dist/commonjs/index.d.ts.map +1 -0
- package/dist/commonjs/index.js +13 -0
- package/dist/commonjs/index.js.map +1 -0
- package/dist/commonjs/package.json +3 -0
- package/dist/esm/cluster-alarm-config.d.ts +77 -0
- package/dist/esm/cluster-alarm-config.d.ts.map +1 -0
- package/dist/esm/cluster-alarm-config.js +2 -0
- package/dist/esm/cluster-alarm-config.js.map +1 -0
- package/dist/esm/cluster-alarm-defaults.d.ts +20 -0
- package/dist/esm/cluster-alarm-defaults.d.ts.map +1 -0
- package/dist/esm/cluster-alarm-defaults.js +49 -0
- package/dist/esm/cluster-alarm-defaults.js.map +1 -0
- package/dist/esm/cluster-alarms.d.ts +25 -0
- package/dist/esm/cluster-alarms.d.ts.map +1 -0
- package/dist/esm/cluster-alarms.js +129 -0
- package/dist/esm/cluster-alarms.js.map +1 -0
- package/dist/esm/cluster-builder.d.ts +194 -0
- package/dist/esm/cluster-builder.d.ts.map +1 -0
- package/dist/esm/cluster-builder.js +137 -0
- package/dist/esm/cluster-builder.js.map +1 -0
- package/dist/esm/cluster-defaults.d.ts +19 -0
- package/dist/esm/cluster-defaults.d.ts.map +1 -0
- package/dist/esm/cluster-defaults.js +84 -0
- package/dist/esm/cluster-defaults.js.map +1 -0
- package/dist/esm/cluster-parameter-group-defaults.d.ts +30 -0
- package/dist/esm/cluster-parameter-group-defaults.d.ts.map +1 -0
- package/dist/esm/cluster-parameter-group-defaults.js +49 -0
- package/dist/esm/cluster-parameter-group-defaults.js.map +1 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/package.json +71 -0
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# @composurecdk/neptune
|
|
2
|
+
|
|
3
|
+
Amazon Neptune cluster builder for [ComposureCDK](../../README.md).
|
|
4
|
+
|
|
5
|
+
This package provides a fluent builder for Amazon Neptune clusters with secure, AWS-recommended defaults. It wraps the CDK alpha [`DatabaseCluster`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-neptune-alpha-readme.html) L2 construct — refer to the CDK documentation for the full set of configurable properties.
|
|
6
|
+
|
|
7
|
+
> **Alpha dependency.** Neptune's CDK L2 lives in `@aws-cdk/aws-neptune-alpha`, which is production-usable but semver-unstable and version-locked to its matching `aws-cdk-lib` release. It is a **peer dependency** of this package — install it (and a matching `aws-cdk-lib`) in your app and pin the version you want.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @composurecdk/neptune @aws-cdk/aws-neptune-alpha aws-cdk-lib
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Cluster Builder
|
|
14
|
+
|
|
15
|
+
A Neptune cluster owns its writer/reader instances — the CDK L2 creates them from the instance type and instance count — so a single cluster builder covers both serverless and provisioned topologies. There is intentionally no separate instance builder: in-region read replicas are added via the instance count (`.instances(n)`), and cross-region scale-out is a [Neptune Global Database](https://docs.aws.amazon.com/neptune/latest/userguide/neptune-global-database.html) (separate read-only clusters per region, future work), not extra instances on one cluster.
|
|
16
|
+
|
|
17
|
+
### Serverless
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { compose, ref } from "@composurecdk/core";
|
|
21
|
+
import { createVpcBuilder, type VpcBuilderResult } from "@composurecdk/ec2";
|
|
22
|
+
import { createClusterBuilder } from "@composurecdk/neptune";
|
|
23
|
+
import { InstanceType } from "@aws-cdk/aws-neptune-alpha";
|
|
24
|
+
|
|
25
|
+
const system = compose(
|
|
26
|
+
{
|
|
27
|
+
network: createVpcBuilder().maxAzs(2),
|
|
28
|
+
graph: createClusterBuilder()
|
|
29
|
+
.vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
30
|
+
.instanceType(InstanceType.SERVERLESS)
|
|
31
|
+
.serverlessScalingConfiguration({ minCapacity: 1, maxCapacity: 8 }),
|
|
32
|
+
},
|
|
33
|
+
{ network: [], graph: ["network"] },
|
|
34
|
+
);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Provisioned
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const graph = createClusterBuilder()
|
|
41
|
+
.vpc(ref<VpcBuilderResult>("network").get("vpc"))
|
|
42
|
+
.instanceType(InstanceType.R6G_LARGE)
|
|
43
|
+
.instances(2); // one writer + one reader
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The `vpc` is set via the dedicated `.vpc()` method (it is required and accepts a `Ref` for cross-component wiring). `securityGroups` likewise accept `Resolvable` values. Every other [`DatabaseClusterProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/@aws-cdk_aws-neptune-alpha.DatabaseClusterProps.html) property is available as a fluent setter. The `instanceType` is **required** — defaulting it would create surprise cost.
|
|
47
|
+
|
|
48
|
+
## Build result
|
|
49
|
+
|
|
50
|
+
`build()` returns every construct the builder creates, per the [build-results-must-be-complete](../../docs/architecture.md) rule:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
interface ClusterBuilderResult {
|
|
54
|
+
cluster: DatabaseCluster;
|
|
55
|
+
subnetGroup: ISubnetGroup;
|
|
56
|
+
clusterParameterGroup: IClusterParameterGroup;
|
|
57
|
+
alarms: Record<string, Alarm>;
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Secure Defaults
|
|
62
|
+
|
|
63
|
+
`createClusterBuilder` applies the following defaults. Each can be overridden via the builder's fluent API. Defaults are anchored to the [AWS Well-Architected Framework — Neptune lens](https://docs.aws.amazon.com/prescriptive-guidance/latest/neptune-well-architected-framework/introduction.html).
|
|
64
|
+
|
|
65
|
+
| Property | Default | Rationale |
|
|
66
|
+
| ------------------------- | ------------------------- | --------------------------------------------------------------------- |
|
|
67
|
+
| `storageEncrypted` | `true` | Encryption at rest; supply a CMK via `.kmsKey()`. |
|
|
68
|
+
| `iamAuthentication` | `true` | Removes long-lived static credentials. |
|
|
69
|
+
| `removalPolicy` | `RETAIN` | Protects graph data from an errant `cdk destroy`. |
|
|
70
|
+
| `deletionProtection` | `true` | Blocks accidental deletion of the cluster. |
|
|
71
|
+
| `backupRetention` | `Duration.days(7)` | Production-grade window (CDK default is 1 day). |
|
|
72
|
+
| `cloudwatchLogsExports` | `[LogType.AUDIT]` | Exports audit logs (the only CloudWatch-exportable Neptune log type). |
|
|
73
|
+
| `cloudwatchLogsRetention` | `RetentionDays.ONE_MONTH` | Bounds log storage cost. |
|
|
74
|
+
| `copyTagsToSnapshot` | `true` | Preserves cost-allocation tags on backups. |
|
|
75
|
+
| `autoMinorVersionUpgrade` | `true` | Stays on patched engine versions. |
|
|
76
|
+
|
|
77
|
+
The defaults are exported as `CLUSTER_DEFAULTS` for visibility and testing.
|
|
78
|
+
|
|
79
|
+
### Audit-log parameter group
|
|
80
|
+
|
|
81
|
+
Audit log _export_ only emits data once audit logging is _enabled_ in the cluster parameter group. So the builder auto-creates a cluster parameter group with `neptune_enable_audit_log = "1"` (parallel to how `createVpcBuilder` auto-creates a flow-log group), with the family derived from the configured engine version. Add or override parameters with `.clusterParameters({...})`, or supply your own group with `.clusterParameterGroup(myGroup)` (mutually exclusive with `.clusterParameters()`).
|
|
82
|
+
|
|
83
|
+
## Granting access — `allowAccessFrom`
|
|
84
|
+
|
|
85
|
+
Because IAM authentication is on by default, a principal needs both a network path (security-group ingress) and an IAM `connect` grant to reach the cluster. `allowAccessFrom(peer)` does both in one declaration, and accepts a `Ref` so the grant lives inside `compose()` rather than in post-build glue:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { createInstanceBuilder, type InstanceBuilderResult } from "@composurecdk/ec2";
|
|
89
|
+
|
|
90
|
+
const system = compose(
|
|
91
|
+
{
|
|
92
|
+
network: createVpcBuilder().maxAzs(2),
|
|
93
|
+
bastion: createInstanceBuilder().vpc(ref("network").get("vpc")).instanceType(/* ... */),
|
|
94
|
+
graph: createClusterBuilder()
|
|
95
|
+
.vpc(ref("network").get("vpc"))
|
|
96
|
+
.instanceType(InstanceType.SERVERLESS)
|
|
97
|
+
.serverlessScalingConfiguration({ minCapacity: 1, maxCapacity: 8 })
|
|
98
|
+
.allowAccessFrom(ref<InstanceBuilderResult>("bastion").get("instance")),
|
|
99
|
+
},
|
|
100
|
+
{ network: [], bastion: ["network"], graph: ["network", "bastion"] },
|
|
101
|
+
);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The `peer` is any `IConnectable & IGrantable` (an EC2 instance, a Lambda function, a Fargate task, …). At build time the builder applies `cluster.connections.allowDefaultPortFrom(peer)` and `cluster.grantConnect(peer)`.
|
|
105
|
+
|
|
106
|
+
If you disable IAM authentication (`.iamAuthentication(false)`), `allowAccessFrom` adapts: it opens only the network path and skips the `grantConnect` IAM policy, which would be inert without IAM auth. Authentication then falls to whatever mechanism you've configured on the cluster.
|
|
107
|
+
|
|
108
|
+
## Recommended Alarms
|
|
109
|
+
|
|
110
|
+
The builder creates recommended CloudWatch alarms by default. Neptune is not yet covered by the [CloudWatch out-of-the-box alarm recommendations](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html), so thresholds follow the [Neptune metrics guidance](https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-general-metrics.html). No alarm actions are configured — access alarms from the build result to add actions.
|
|
111
|
+
|
|
112
|
+
| Alarm | Metric | Default threshold | Created when |
|
|
113
|
+
| --------------------------------- | -------------------------------------------- | -------------------- | ------------------------ |
|
|
114
|
+
| `cpuUtilization` | CPUUtilization (Average, 1 min) | >= 80% | Always |
|
|
115
|
+
| `mainRequestQueuePendingRequests` | MainRequestQueuePendingRequests (Avg, 1 min) | > 100 | Always |
|
|
116
|
+
| `bufferCacheHitRatio` | BufferCacheHitRatio (Average, 1 min) | < 99.9% | Always |
|
|
117
|
+
| `clusterReplicaLag` | ClusterReplicaLag (Average, 1 min) | > 30000 ms | Always[^lag] |
|
|
118
|
+
| `serverlessDatabaseCapacity` | ServerlessDatabaseCapacity (Average, 1 min) | 90% of `maxCapacity` | Serverless clusters only |
|
|
119
|
+
|
|
120
|
+
[^lag]: Only emits data when the cluster has a read replica. `TreatMissingData` defaults to `notBreaching`, so it stays quiet on a single-instance cluster.
|
|
121
|
+
|
|
122
|
+
The defaults are exported as `CLUSTER_ALARM_DEFAULTS` for visibility and testing.
|
|
123
|
+
|
|
124
|
+
### Customizing and disabling alarms
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
createClusterBuilder()
|
|
128
|
+
// tune one alarm, disable another
|
|
129
|
+
.recommendedAlarms({ cpuUtilization: { threshold: 90 }, bufferCacheHitRatio: false })
|
|
130
|
+
// add a custom alarm
|
|
131
|
+
.addAlarm("gremlinErrors", (a) =>
|
|
132
|
+
a
|
|
133
|
+
.metric((cluster) => cluster.metric("NumGremlinErrorsPerSec"))
|
|
134
|
+
.threshold(0)
|
|
135
|
+
.greaterThan(),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// disable all recommended alarms
|
|
139
|
+
createClusterBuilder().recommendedAlarms(false);
|
|
140
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { AlarmConfig } from "@composurecdk/cloudwatch";
|
|
2
|
+
/**
|
|
3
|
+
* Controls which recommended alarms are created for a Neptune cluster.
|
|
4
|
+
* All applicable alarms are enabled by default with thresholds drawn from
|
|
5
|
+
* the Neptune team's own metric guidance. Set an individual alarm to `false`
|
|
6
|
+
* to disable it, or provide an {@link AlarmConfig} to tune its thresholds.
|
|
7
|
+
*
|
|
8
|
+
* Neptune is not yet covered by the CloudWatch out-of-the-box alarm
|
|
9
|
+
* recommendations table, so these thresholds are anchored to the Neptune
|
|
10
|
+
* User Guide's metrics guidance and the Neptune Well-Architected lens rather
|
|
11
|
+
* than to that table.
|
|
12
|
+
*
|
|
13
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-general-metrics.html
|
|
14
|
+
* @see https://docs.aws.amazon.com/prescriptive-guidance/latest/neptune-well-architected-framework/introduction.html
|
|
15
|
+
*/
|
|
16
|
+
export interface NeptuneClusterAlarmConfig {
|
|
17
|
+
/**
|
|
18
|
+
* Master switch: set to `false` to disable all recommended alarms.
|
|
19
|
+
* Individual alarms can also be disabled via their own entry.
|
|
20
|
+
* @default true
|
|
21
|
+
*/
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Alarm on sustained high CPU on the cluster's instances — the primary
|
|
25
|
+
* signal of a saturated writer or undersized instance.
|
|
26
|
+
*
|
|
27
|
+
* Metric: `AWS/Neptune CPUUtilization`, statistic Average, period 1 minute.
|
|
28
|
+
* Default threshold: >= 80%.
|
|
29
|
+
*
|
|
30
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/cloudwatch-monitoring-instances.html
|
|
31
|
+
*/
|
|
32
|
+
cpuUtilization?: AlarmConfig | false;
|
|
33
|
+
/**
|
|
34
|
+
* Alarm when requests are queuing faster than the engine can execute them.
|
|
35
|
+
*
|
|
36
|
+
* Metric: `AWS/Neptune MainRequestQueuePendingRequests`, statistic Average,
|
|
37
|
+
* period 1 minute. Default threshold: > 100 pending requests.
|
|
38
|
+
*
|
|
39
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-general-metrics.html
|
|
40
|
+
*/
|
|
41
|
+
mainRequestQueuePendingRequests?: AlarmConfig | false;
|
|
42
|
+
/**
|
|
43
|
+
* Alarm when the buffer cache hit ratio drops, indicating the working set
|
|
44
|
+
* no longer fits in memory and query latency is dominated by I/O.
|
|
45
|
+
*
|
|
46
|
+
* Metric: `AWS/Neptune BufferCacheHitRatio`, statistic Average, period 1
|
|
47
|
+
* minute. Default threshold: < 99.9%.
|
|
48
|
+
*
|
|
49
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-general-metrics.html
|
|
50
|
+
*/
|
|
51
|
+
bufferCacheHitRatio?: AlarmConfig | false;
|
|
52
|
+
/**
|
|
53
|
+
* Alarm when a read replica falls too far behind the writer. Only emits
|
|
54
|
+
* data when the cluster has at least one replica, so it stays quiet on a
|
|
55
|
+
* single-instance cluster (`TreatMissingData.NOT_BREACHING`).
|
|
56
|
+
*
|
|
57
|
+
* Metric: `AWS/Neptune ClusterReplicaLag`, statistic Average, period 1
|
|
58
|
+
* minute. Default threshold: > 30000 ms.
|
|
59
|
+
*
|
|
60
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/cw-metrics.html
|
|
61
|
+
*/
|
|
62
|
+
clusterReplicaLag?: AlarmConfig | false;
|
|
63
|
+
/**
|
|
64
|
+
* Alarm when a serverless cluster sustains capacity near its configured
|
|
65
|
+
* ceiling, indicating the max NCU setting is too low or query load is
|
|
66
|
+
* running away. Only created when the cluster is serverless (i.e.
|
|
67
|
+
* `serverlessScalingConfiguration` is set); the default threshold is
|
|
68
|
+
* derived as 90% of the configured `maxCapacity`.
|
|
69
|
+
*
|
|
70
|
+
* Metric: `AWS/Neptune ServerlessDatabaseCapacity`, statistic Average,
|
|
71
|
+
* period 1 minute.
|
|
72
|
+
*
|
|
73
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/neptune-serverless-capacity-scaling.html
|
|
74
|
+
*/
|
|
75
|
+
serverlessDatabaseCapacity?: AlarmConfig | false;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=cluster-alarm-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-alarm-config.d.ts","sourceRoot":"","sources":["../../src/cluster-alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAErC;;;;;;;OAOG;IACH,+BAA+B,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEtD;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAE1C;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAExC;;;;;;;;;;;OAWG;IACH,0BAA0B,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CAClD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-alarm-config.js","sourceRoot":"","sources":["../../src/cluster-alarm-config.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AlarmConfigDefaults } from "@composurecdk/cloudwatch";
|
|
2
|
+
interface ClusterAlarmDefaults {
|
|
3
|
+
enabled: true;
|
|
4
|
+
cpuUtilization: AlarmConfigDefaults;
|
|
5
|
+
mainRequestQueuePendingRequests: AlarmConfigDefaults;
|
|
6
|
+
bufferCacheHitRatio: AlarmConfigDefaults;
|
|
7
|
+
clusterReplicaLag: AlarmConfigDefaults;
|
|
8
|
+
/** `threshold` is unused — the real value is derived from `maxCapacity` at build time. */
|
|
9
|
+
serverlessDatabaseCapacity: AlarmConfigDefaults;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Recommended default alarm configuration for Neptune clusters. Thresholds
|
|
13
|
+
* follow the Neptune team's metric guidance; Neptune is absent from the
|
|
14
|
+
* CloudWatch recommended-alarms table, so no anchor to that page exists.
|
|
15
|
+
*
|
|
16
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-general-metrics.html
|
|
17
|
+
*/
|
|
18
|
+
export declare const CLUSTER_ALARM_DEFAULTS: ClusterAlarmDefaults;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=cluster-alarm-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-alarm-defaults.d.ts","sourceRoot":"","sources":["../../src/cluster-alarm-defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,IAAI,CAAC;IACd,cAAc,EAAE,mBAAmB,CAAC;IACpC,+BAA+B,EAAE,mBAAmB,CAAC;IACrD,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,0FAA0F;IAC1F,0BAA0B,EAAE,mBAAmB,CAAC;CACjD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,oBA4CpC,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLUSTER_ALARM_DEFAULTS = void 0;
|
|
4
|
+
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
|
|
5
|
+
/**
|
|
6
|
+
* Recommended default alarm configuration for Neptune clusters. Thresholds
|
|
7
|
+
* follow the Neptune team's metric guidance; Neptune is absent from the
|
|
8
|
+
* CloudWatch recommended-alarms table, so no anchor to that page exists.
|
|
9
|
+
*
|
|
10
|
+
* @see https://docs.aws.amazon.com/neptune/latest/userguide/best-practices-general-metrics.html
|
|
11
|
+
*/
|
|
12
|
+
exports.CLUSTER_ALARM_DEFAULTS = {
|
|
13
|
+
enabled: true,
|
|
14
|
+
/** Sustained CPU at/above 80% over several minutes signals saturation. */
|
|
15
|
+
cpuUtilization: {
|
|
16
|
+
threshold: 80,
|
|
17
|
+
evaluationPeriods: 5,
|
|
18
|
+
datapointsToAlarm: 3,
|
|
19
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
20
|
+
},
|
|
21
|
+
/** A growing request backlog means the engine cannot keep up with load. */
|
|
22
|
+
mainRequestQueuePendingRequests: {
|
|
23
|
+
threshold: 100,
|
|
24
|
+
evaluationPeriods: 5,
|
|
25
|
+
datapointsToAlarm: 3,
|
|
26
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
27
|
+
},
|
|
28
|
+
/** A cache hit ratio below 99.9% indicates the working set exceeds memory. */
|
|
29
|
+
bufferCacheHitRatio: {
|
|
30
|
+
threshold: 99.9,
|
|
31
|
+
evaluationPeriods: 15,
|
|
32
|
+
datapointsToAlarm: 10,
|
|
33
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
34
|
+
},
|
|
35
|
+
/** Replica lag over 30s risks stale reads; quiet on single-instance clusters. */
|
|
36
|
+
clusterReplicaLag: {
|
|
37
|
+
threshold: 30_000,
|
|
38
|
+
evaluationPeriods: 5,
|
|
39
|
+
datapointsToAlarm: 3,
|
|
40
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
41
|
+
},
|
|
42
|
+
// `threshold` is a required-shape filler: the serverless capacity alarm
|
|
43
|
+
// always derives its threshold from `maxCapacity` at build time (or a user
|
|
44
|
+
// override), so this value is never read. The evaluation window is.
|
|
45
|
+
serverlessDatabaseCapacity: {
|
|
46
|
+
threshold: 0,
|
|
47
|
+
evaluationPeriods: 15,
|
|
48
|
+
datapointsToAlarm: 10,
|
|
49
|
+
treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=cluster-alarm-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-alarm-defaults.js","sourceRoot":"","sources":["../../src/cluster-alarm-defaults.ts"],"names":[],"mappings":";;;AAAA,+DAA8D;AAa9D;;;;;;GAMG;AACU,QAAA,sBAAsB,GAAyB;IAC1D,OAAO,EAAE,IAAI;IAEb,0EAA0E;IAC1E,cAAc,EAAE;QACd,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;IAED,2EAA2E;IAC3E,+BAA+B,EAAE;QAC/B,SAAS,EAAE,GAAG;QACd,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;IAED,8EAA8E;IAC9E,mBAAmB,EAAE;QACnB,SAAS,EAAE,IAAI;QACf,iBAAiB,EAAE,EAAE;QACrB,iBAAiB,EAAE,EAAE;QACrB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;IAED,iFAAiF;IACjF,iBAAiB,EAAE;QACjB,SAAS,EAAE,MAAM;QACjB,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,oEAAoE;IACpE,0BAA0B,EAAE;QAC1B,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,EAAE;QACrB,iBAAiB,EAAE,EAAE;QACrB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;CACF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
|
|
2
|
+
import type { IDatabaseCluster, ServerlessScalingConfiguration } from "@aws-cdk/aws-neptune-alpha";
|
|
3
|
+
import type { IConstruct } from "constructs";
|
|
4
|
+
import type { AlarmDefinition, AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
5
|
+
import type { NeptuneClusterAlarmConfig } from "./cluster-alarm-config.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resolves the recommended alarm configuration into fully-resolved
|
|
8
|
+
* {@link AlarmDefinition}s for a Neptune cluster. The serverless capacity
|
|
9
|
+
* alarm is only emitted when `serverlessScaling` is provided.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveClusterAlarmDefinitions(cluster: IDatabaseCluster, config: NeptuneClusterAlarmConfig | undefined, serverlessScaling: ServerlessScalingConfiguration | undefined): AlarmDefinition[];
|
|
12
|
+
/**
|
|
13
|
+
* Creates recommended CloudWatch alarms for a Neptune cluster, merging the
|
|
14
|
+
* recommended definitions with any custom alarm builders.
|
|
15
|
+
*
|
|
16
|
+
* @param scope - CDK construct scope for creating alarm constructs.
|
|
17
|
+
* @param id - Base identifier for alarm construct ids.
|
|
18
|
+
* @param cluster - The Neptune cluster to create alarms for.
|
|
19
|
+
* @param config - User-provided alarm configuration, or `false` to disable all.
|
|
20
|
+
* @param serverlessScaling - The cluster's serverless scaling config, if any.
|
|
21
|
+
* @param customAlarms - Custom alarm builders added via `addAlarm()`.
|
|
22
|
+
* @returns A record mapping alarm keys to their created Alarm constructs.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createClusterAlarms(scope: IConstruct, id: string, cluster: IDatabaseCluster, config: NeptuneClusterAlarmConfig | false | undefined, serverlessScaling: ServerlessScalingConfiguration | undefined, customAlarms?: AlarmDefinitionBuilder<IDatabaseCluster>[]): Record<string, Alarm>;
|
|
25
|
+
//# sourceMappingURL=cluster-alarms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-alarms.d.ts","sourceRoot":"","sources":["../../src/cluster-alarms.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAsB,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAY3E;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,yBAAyB,GAAG,SAAS,EAC7C,iBAAiB,EAAE,8BAA8B,GAAG,SAAS,GAC5D,eAAe,EAAE,CA4GnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,yBAAyB,GAAG,KAAK,GAAG,SAAS,EACrD,iBAAiB,EAAE,8BAA8B,GAAG,SAAS,EAC7D,YAAY,GAAE,sBAAsB,CAAC,gBAAgB,CAAC,EAAO,GAC5D,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAUvB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveClusterAlarmDefinitions = resolveClusterAlarmDefinitions;
|
|
4
|
+
exports.createClusterAlarms = createClusterAlarms;
|
|
5
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
6
|
+
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
|
|
7
|
+
const cloudwatch_1 = require("@composurecdk/cloudwatch");
|
|
8
|
+
const cluster_alarm_defaults_js_1 = require("./cluster-alarm-defaults.js");
|
|
9
|
+
const METRIC_PERIOD = aws_cdk_lib_1.Duration.minutes(1);
|
|
10
|
+
const METRIC_PERIOD_LABEL = `${String(METRIC_PERIOD.toMinutes())} minute`;
|
|
11
|
+
/**
|
|
12
|
+
* Fraction of a serverless cluster's configured `maxCapacity` at which the
|
|
13
|
+
* `serverlessDatabaseCapacity` alarm fires by default.
|
|
14
|
+
*/
|
|
15
|
+
const SERVERLESS_CAPACITY_ALARM_FRACTION = 0.9;
|
|
16
|
+
/**
|
|
17
|
+
* Resolves the recommended alarm configuration into fully-resolved
|
|
18
|
+
* {@link AlarmDefinition}s for a Neptune cluster. The serverless capacity
|
|
19
|
+
* alarm is only emitted when `serverlessScaling` is provided.
|
|
20
|
+
*/
|
|
21
|
+
function resolveClusterAlarmDefinitions(cluster, config, serverlessScaling) {
|
|
22
|
+
if (config?.enabled === false)
|
|
23
|
+
return [];
|
|
24
|
+
const definitions = [];
|
|
25
|
+
if (config?.cpuUtilization !== false) {
|
|
26
|
+
const cfg = (0, cloudwatch_1.resolveAlarmConfig)(config?.cpuUtilization, cluster_alarm_defaults_js_1.CLUSTER_ALARM_DEFAULTS.cpuUtilization);
|
|
27
|
+
definitions.push({
|
|
28
|
+
key: "cpuUtilization",
|
|
29
|
+
alarmName: cfg.alarmName,
|
|
30
|
+
metric: cluster.metric("CPUUtilization", { period: METRIC_PERIOD, statistic: "Average" }),
|
|
31
|
+
threshold: cfg.threshold,
|
|
32
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
33
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
34
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
35
|
+
treatMissingData: cfg.treatMissingData,
|
|
36
|
+
description: `Neptune cluster CPU utilization is high. Threshold: >= ${String(cfg.threshold)}% over ${METRIC_PERIOD_LABEL} periods.`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (config?.mainRequestQueuePendingRequests !== false) {
|
|
40
|
+
const cfg = (0, cloudwatch_1.resolveAlarmConfig)(config?.mainRequestQueuePendingRequests, cluster_alarm_defaults_js_1.CLUSTER_ALARM_DEFAULTS.mainRequestQueuePendingRequests);
|
|
41
|
+
definitions.push({
|
|
42
|
+
key: "mainRequestQueuePendingRequests",
|
|
43
|
+
alarmName: cfg.alarmName,
|
|
44
|
+
metric: cluster.metric("MainRequestQueuePendingRequests", {
|
|
45
|
+
period: METRIC_PERIOD,
|
|
46
|
+
statistic: "Average",
|
|
47
|
+
}),
|
|
48
|
+
threshold: cfg.threshold,
|
|
49
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
50
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
51
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
52
|
+
treatMissingData: cfg.treatMissingData,
|
|
53
|
+
description: `Neptune cluster request queue is backing up. Threshold: > ${String(cfg.threshold)} pending requests over ${METRIC_PERIOD_LABEL} periods.`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (config?.bufferCacheHitRatio !== false) {
|
|
57
|
+
const cfg = (0, cloudwatch_1.resolveAlarmConfig)(config?.bufferCacheHitRatio, cluster_alarm_defaults_js_1.CLUSTER_ALARM_DEFAULTS.bufferCacheHitRatio);
|
|
58
|
+
definitions.push({
|
|
59
|
+
key: "bufferCacheHitRatio",
|
|
60
|
+
alarmName: cfg.alarmName,
|
|
61
|
+
metric: cluster.metric("BufferCacheHitRatio", {
|
|
62
|
+
period: METRIC_PERIOD,
|
|
63
|
+
statistic: "Average",
|
|
64
|
+
}),
|
|
65
|
+
threshold: cfg.threshold,
|
|
66
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.LESS_THAN_THRESHOLD,
|
|
67
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
68
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
69
|
+
treatMissingData: cfg.treatMissingData,
|
|
70
|
+
description: `Neptune cluster buffer cache hit ratio is low; working set may exceed memory. Threshold: < ${String(cfg.threshold)}% over ${METRIC_PERIOD_LABEL} periods.`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (config?.clusterReplicaLag !== false) {
|
|
74
|
+
const cfg = (0, cloudwatch_1.resolveAlarmConfig)(config?.clusterReplicaLag, cluster_alarm_defaults_js_1.CLUSTER_ALARM_DEFAULTS.clusterReplicaLag);
|
|
75
|
+
definitions.push({
|
|
76
|
+
key: "clusterReplicaLag",
|
|
77
|
+
alarmName: cfg.alarmName,
|
|
78
|
+
metric: cluster.metric("ClusterReplicaLag", { period: METRIC_PERIOD, statistic: "Average" }),
|
|
79
|
+
threshold: cfg.threshold,
|
|
80
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
|
|
81
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
82
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
83
|
+
treatMissingData: cfg.treatMissingData,
|
|
84
|
+
description: `Neptune read replica is lagging the writer. Threshold: > ${String(cfg.threshold)} ms over ${METRIC_PERIOD_LABEL} periods.`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Contextual: only meaningful for a serverless cluster, where capacity is
|
|
88
|
+
// measured in NCUs and a ceiling is configured. The threshold defaults to a
|
|
89
|
+
// fraction of the configured maximum.
|
|
90
|
+
if (serverlessScaling !== undefined && config?.serverlessDatabaseCapacity !== false) {
|
|
91
|
+
const cfg = (0, cloudwatch_1.resolveAlarmConfig)(config?.serverlessDatabaseCapacity, cluster_alarm_defaults_js_1.CLUSTER_ALARM_DEFAULTS.serverlessDatabaseCapacity);
|
|
92
|
+
const threshold = config?.serverlessDatabaseCapacity?.threshold ??
|
|
93
|
+
serverlessScaling.maxCapacity * SERVERLESS_CAPACITY_ALARM_FRACTION;
|
|
94
|
+
definitions.push({
|
|
95
|
+
key: "serverlessDatabaseCapacity",
|
|
96
|
+
alarmName: cfg.alarmName,
|
|
97
|
+
metric: cluster.metric("ServerlessDatabaseCapacity", {
|
|
98
|
+
period: METRIC_PERIOD,
|
|
99
|
+
statistic: "Average",
|
|
100
|
+
}),
|
|
101
|
+
threshold,
|
|
102
|
+
comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
|
|
103
|
+
evaluationPeriods: cfg.evaluationPeriods,
|
|
104
|
+
datapointsToAlarm: cfg.datapointsToAlarm,
|
|
105
|
+
treatMissingData: cfg.treatMissingData,
|
|
106
|
+
description: `Neptune serverless capacity is sustained near its ${String(serverlessScaling.maxCapacity)} NCU ceiling. Threshold: >= ${String(threshold)} NCU over ${METRIC_PERIOD_LABEL} periods.`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return definitions;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates recommended CloudWatch alarms for a Neptune cluster, merging the
|
|
113
|
+
* recommended definitions with any custom alarm builders.
|
|
114
|
+
*
|
|
115
|
+
* @param scope - CDK construct scope for creating alarm constructs.
|
|
116
|
+
* @param id - Base identifier for alarm construct ids.
|
|
117
|
+
* @param cluster - The Neptune cluster to create alarms for.
|
|
118
|
+
* @param config - User-provided alarm configuration, or `false` to disable all.
|
|
119
|
+
* @param serverlessScaling - The cluster's serverless scaling config, if any.
|
|
120
|
+
* @param customAlarms - Custom alarm builders added via `addAlarm()`.
|
|
121
|
+
* @returns A record mapping alarm keys to their created Alarm constructs.
|
|
122
|
+
*/
|
|
123
|
+
function createClusterAlarms(scope, id, cluster, config, serverlessScaling, customAlarms = []) {
|
|
124
|
+
if (config === false)
|
|
125
|
+
return {};
|
|
126
|
+
const enabled = config?.enabled ?? cluster_alarm_defaults_js_1.CLUSTER_ALARM_DEFAULTS.enabled;
|
|
127
|
+
if (!enabled)
|
|
128
|
+
return {};
|
|
129
|
+
const recommended = resolveClusterAlarmDefinitions(cluster, config, serverlessScaling);
|
|
130
|
+
const custom = customAlarms.map((b) => b.resolve(cluster));
|
|
131
|
+
return (0, cloudwatch_1.createAlarms)(scope, id, [...recommended, ...custom]);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=cluster-alarms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-alarms.js","sourceRoot":"","sources":["../../src/cluster-alarms.ts"],"names":[],"mappings":"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"}
|