@empire-builder-kit/nx 1.0.0-rc.44 → 1.0.0-rc.45
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/package.json +3 -3
- package/src/blueprints/external-sandbox.d.ts +1 -1
- package/src/cli/main.d.ts +11 -5
- package/src/cli/main.js +88 -29
- package/src/container-images.d.ts +1 -1
- package/src/container-images.js +1 -1
- package/src/executors/deployment-plan/deployment-plan.js +5 -1
- package/src/executors/deployment-plan/schema.json +1 -1
- package/src/executors/fleet/fleet.js +4 -0
- package/src/executors/fleet/schema.json +1 -1
- package/src/executors/local-deploy/federated-credential-transport.d.ts +4 -3
- package/src/executors/local-deploy/federated-credential-transport.js +15 -5
- package/src/foundation/cost-estimate.d.ts +8 -3
- package/src/foundation/cost-estimate.js +42 -19
- package/src/foundation/index.d.ts +1 -0
- package/src/foundation/index.js +1 -0
- package/src/foundation/local-private-smoke-access.js +6 -0
- package/src/foundation/logging.d.ts +3 -1
- package/src/foundation/logging.js +8 -1
- package/src/foundation/observability.d.ts +42 -0
- package/src/foundation/observability.js +181 -0
- package/src/foundation/preflight.js +1 -1
- package/src/generators/function/function.js +5 -2
- package/src/generators/observability-infrastructure.d.ts +2 -0
- package/src/generators/observability-infrastructure.js +31 -0
- package/src/generators/observability-policy.d.ts +4 -0
- package/src/generators/observability-policy.js +23 -0
- package/src/generators/preset/dependency-overrides.d.ts +17 -6
- package/src/generators/preset/dependency-overrides.js +17 -6
- package/src/generators/preset/tool-versions.d.ts +2 -2
- package/src/generators/preset/tool-versions.js +2 -2
- package/src/generators/preset/workspace-files-adopter-skills.js +28 -17
- package/src/generators/preset/workspace-files-agent-development.d.ts +9 -0
- package/src/generators/preset/workspace-files-agent-development.js +42 -0
- package/src/generators/preset/workspace-files-thin-deploy.js +12 -3
- package/src/generators/preset/workspace-files-thin-docs.js +10 -22
- package/src/generators/preset/workspace-files.d.ts +1 -0
- package/src/generators/preset/workspace-files.js +89 -7
- package/src/generators/slice/built-in-plan-alarm-identity.d.ts +173 -0
- package/src/generators/slice/built-in-plan-alarm-identity.js +202 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js +136 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js +1 -1
- package/src/generators/slice/built-in-plan-event-contract-literal.d.ts +6 -0
- package/src/generators/slice/built-in-plan-event-contract-literal.js +52 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js +304 -144
- package/src/generators/slice/built-in-plan-key-value-retention-infrastructure.js +2 -2
- package/src/generators/slice/built-in-plan-metadata-files.js +33 -1
- package/src/generators/slice/built-in-plan-operations-files.js +106 -6
- package/src/generators/slice/built-in-plan-project-files.js +1 -0
- package/src/generators/slice/built-in-plan-release-files.js +2 -43
- package/src/generators/slice/built-in-plan-reliability-files.js +222 -236
- package/src/generators/slice/built-in-plan-shared.d.ts +29 -3
- package/src/generators/slice/built-in-plan-shared.js +29 -2
- package/src/generators/slice/built-in-plan-web-files.js +18 -1
- package/src/generators/slice/built-in-plan.js +1 -0
- package/src/generators/slice/slice.js +2 -0
- package/src/generators/upgrade/upgrade.d.ts +4 -3
- package/src/generators/upgrade/upgrade.js +50 -26
- package/src/generators/workload/frozen-container.d.ts +1 -1
- package/src/generators/workload/workload.js +5 -1
- package/src/local-dev/dev-command-core.d.ts +24 -3
- package/src/local-dev/dev-command-core.js +124 -12
- package/src/local-dev/errors.d.ts +19 -1
- package/src/local-dev/errors.js +18 -1
- package/src/local-dev/fleet-client.d.ts +64 -6
- package/src/local-dev/fleet-client.js +189 -15
- package/src/local-dev/fleet-process.d.ts +47 -2
- package/src/local-dev/fleet-process.js +248 -31
- package/src/local-dev/fleet-runtime.d.ts +37 -0
- package/src/local-dev/fleet-runtime.js +127 -69
- package/src/local-dev/fleet-session.d.ts +1 -0
- package/src/local-dev/fleet-session.js +42 -3
- package/src/local-dev/fleet-state.d.ts +5 -0
- package/src/local-dev/fleet-state.js +11 -2
- package/src/local-dev/fleet-supervisor.d.ts +6 -0
- package/src/local-dev/fleet-supervisor.js +49 -1
- package/src/local-dev/slice-runner.d.ts +19 -1
- package/src/local-dev/slice-runner.js +290 -91
- package/src/repository-policy/deployment-plan.d.ts +1 -1
- package/src/repository-policy/deployment-plan.js +16 -1
- package/src/secrets/generated-aws-control-plane.d.ts +11 -1
- package/src/secrets/generated-aws-control-plane.js +92 -29
- package/src/secrets/operator.d.ts +3 -2
- package/src/secrets/operator.js +27 -5
- package/src/supply-chain/generated-files.js +9 -0
|
@@ -541,6 +541,9 @@ writeFileSync(
|
|
|
541
541
|
function renderThinDeployWorkflow(options) {
|
|
542
542
|
const { actionPins, deploymentProfile, name, toolVersions } = options;
|
|
543
543
|
const trunkPromotion = options.productionApprovalMode === 'trunk-promotion';
|
|
544
|
+
// The starter protected pair deploys development from protected develop;
|
|
545
|
+
// in the trunk lane develop is unprotected and owns no stage.
|
|
546
|
+
const developmentFromProtectedDevelop = deploymentProfile === 'starter' && options.deliveryLane !== 'trunk';
|
|
544
547
|
return `name: Deploy
|
|
545
548
|
run-name: Deploy \${{ inputs.source_commit || github.sha }}
|
|
546
549
|
|
|
@@ -707,14 +710,17 @@ jobs:
|
|
|
707
710
|
plan_action="$action"
|
|
708
711
|
[ "$action" != rehearse ] || plan_action=deploy
|
|
709
712
|
case "$EBK_SOURCE_BRANCH" in
|
|
710
|
-
main) stage=production
|
|
713
|
+
main) stage=production ;;${options.deliveryLane === 'trunk'
|
|
714
|
+
? `
|
|
715
|
+
develop) echo 'Trunk lane protected lifecycle runs from main'; exit 1 ;;`
|
|
716
|
+
: `
|
|
711
717
|
develop)
|
|
712
718
|
if [ "$EBK_PROFILE" = starter ]; then
|
|
713
719
|
stage=development
|
|
714
720
|
else
|
|
715
721
|
stage=staging
|
|
716
722
|
fi
|
|
717
|
-
|
|
723
|
+
;;`}
|
|
718
724
|
*) echo 'Protected lifecycle must run from develop or main'; exit 1 ;;
|
|
719
725
|
esac
|
|
720
726
|
echo "action=$action" >> "$GITHUB_OUTPUT"
|
|
@@ -1665,7 +1671,10 @@ ${indentedScript(restoredCandidateValidationScript(), 10)}
|
|
|
1665
1671
|
{ echo 'Protected Blueprint authority must be one full Git object ID'; exit 1; }
|
|
1666
1672
|
test "$(git rev-parse HEAD)" = "$EBK_PROTECTED_BLUEPRINT_COMMIT" ||
|
|
1667
1673
|
{ echo 'Protected Blueprint authority differs from the exact workflow checkout'; exit 1; }
|
|
1668
|
-
case "$EBK_STAGE" in
|
|
1674
|
+
case "$EBK_STAGE" in${developmentFromProtectedDevelop
|
|
1675
|
+
? `
|
|
1676
|
+
development) protected_branch=develop ;;`
|
|
1677
|
+
: ''}
|
|
1669
1678
|
staging) protected_branch=develop ;;
|
|
1670
1679
|
production) protected_branch=main ;;
|
|
1671
1680
|
*) exit 1 ;;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderThinLifecycleDocumentation = renderThinLifecycleDocumentation;
|
|
4
|
+
const workspace_files_agent_development_js_1 = require("./workspace-files-agent-development.js");
|
|
4
5
|
const index_js_1 = require("../../repository-policy/index.js");
|
|
5
6
|
function renderThinLifecycleDocumentation(options) {
|
|
6
7
|
const stages = (0, index_js_1.activeDeploymentStages)(options.deploymentProfile);
|
|
@@ -18,19 +19,13 @@ The committed \`${options.deploymentProfile}\` profile activates: ${stageList}.
|
|
|
18
19
|
|
|
19
20
|
For ordinary feature work, run affected tests, typecheck, lint, and ownership
|
|
20
21
|
checks. Run \`pnpm verify\` at a milestone, not before each development edit.
|
|
21
|
-
Configure the
|
|
22
|
+
Configure the development profile and the stage deployment role described
|
|
22
23
|
in \`docs/stage-deployment-authority.md\` before deploying development through
|
|
23
|
-
\`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`
|
|
24
|
-
(the root \`deploy-local\` target).
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
human approves the request in the browser, so the session stays the human's
|
|
29
|
-
own identity. In a hosted or headless shell, add \`--use-device-code\` and the
|
|
30
|
-
human approves the printed code from their own browser. Confirm
|
|
31
|
-
\`aws sts get-caller-identity\` reports that identity before continuing.
|
|
32
|
-
Never embed access keys, export, copy, or read credentials from the SSO cache,
|
|
33
|
-
or assume a separate or stronger principal. Do not invoke SST directly.
|
|
24
|
+
\`ebk deploy development --profile=<development-profile> --expectedRoleArn=<role-arn>\`
|
|
25
|
+
(the root \`deploy-local\` target).
|
|
26
|
+
|
|
27
|
+
${workspace_files_agent_development_js_1.AGENT_DEVELOPMENT_AUTHORITY}
|
|
28
|
+
Do not invoke SST directly.
|
|
34
29
|
|
|
35
30
|
Slice \`verify\` runs \`test-integration\`, which needs a running Docker engine
|
|
36
31
|
for DynamoDB Local (and PostgreSQL when SQL is declared).
|
|
@@ -143,7 +138,7 @@ removal, unlock, discovery, and secret resolution.
|
|
|
143
138
|
|
|
144
139
|
## Native lifecycle
|
|
145
140
|
|
|
146
|
-
Use \`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`.
|
|
141
|
+
Use \`ebk deploy development --profile=<development-profile> --expectedRoleArn=<role-arn>\`.
|
|
147
142
|
Add Slice names, for example \`ebk deploy development billing\` with the same
|
|
148
143
|
authority options, for focused deployment after Foundation. Other Slices are
|
|
149
144
|
not redeployed; required peers must already exist. Omit Slice names for the
|
|
@@ -248,16 +243,9 @@ The resolved ${rehearsalStage} stage is rehearsed with
|
|
|
248
243
|
Use temporary IAM Identity Center credentials and the stable stage deployment
|
|
249
244
|
role. Development accepts a dirty tree and requires no acknowledgement:
|
|
250
245
|
|
|
251
|
-
\`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`
|
|
246
|
+
\`ebk deploy development --profile=<development-profile> --expectedRoleArn=<role-arn>\`
|
|
252
247
|
|
|
253
|
-
|
|
254
|
-
agent (local or hosted) may run \`aws sso login --profile <profile>\`; the
|
|
255
|
-
human approves the request in the browser, so the session stays the human's
|
|
256
|
-
own identity. In a hosted or headless shell, add \`--use-device-code\` and the
|
|
257
|
-
human approves the printed code from their own browser. Confirm
|
|
258
|
-
\`aws sts get-caller-identity\` reports that identity before continuing.
|
|
259
|
-
Never embed access keys, export, copy, or read credentials from the SSO cache,
|
|
260
|
-
or assume a separate or stronger principal.
|
|
248
|
+
${workspace_files_agent_development_js_1.AGENT_DEVELOPMENT_AUTHORITY}
|
|
261
249
|
|
|
262
250
|
Local staging, when active, requires a clean commit and an interactive
|
|
263
251
|
\`approve:deploy:staging:<source-commit>\` response. Starter production requires
|
|
@@ -11,6 +11,7 @@ export interface WorkspaceFileOptions {
|
|
|
11
11
|
/** Seeded supply-chain/dependency-overrides.json data. When absent, the
|
|
12
12
|
* workspace is seeded with DEFAULT_DEPENDENCY_OVERRIDES. */
|
|
13
13
|
dependencyOverrides?: unknown;
|
|
14
|
+
observabilityPolicy?: unknown;
|
|
14
15
|
deploymentAccounts?: ConfiguredDeploymentAccounts;
|
|
15
16
|
deploymentProfile?: DeploymentProfile;
|
|
16
17
|
deploymentRegion?: string | null;
|
|
@@ -11,6 +11,7 @@ const dependency_overrides_js_1 = require("./dependency-overrides.js");
|
|
|
11
11
|
const index_js_1 = require("../../ownership/index.js");
|
|
12
12
|
const index_js_2 = require("../../frontend-security/index.js");
|
|
13
13
|
const capability_plan_js_1 = require("../../foundation/capability-plan.js");
|
|
14
|
+
const observability_js_1 = require("../../foundation/observability.js");
|
|
14
15
|
const cost_estimate_js_1 = require("../../foundation/cost-estimate.js");
|
|
15
16
|
const index_js_3 = require("../../git-policy/index.js");
|
|
16
17
|
const index_js_4 = require("../../repository-policy/index.js");
|
|
@@ -1059,6 +1060,7 @@ const SUPPLY_CHAIN_WORKSPACE_FILE_PLAN = (0, index_js_6.renderSupplyChainWorkspa
|
|
|
1059
1060
|
});
|
|
1060
1061
|
const WORKSPACE_SEEDED_PATHS = new Set([
|
|
1061
1062
|
dependency_overrides_js_1.DEPENDENCY_OVERRIDES_PATH,
|
|
1063
|
+
observability_js_1.OBSERVABILITY_POLICY_PATH,
|
|
1062
1064
|
...SUPPLY_CHAIN_WORKSPACE_FILE_PLAN.seeded,
|
|
1063
1065
|
...workspace_files_developer_agent_js_1.DEVELOPER_AGENT_WORKSPACE_SEEDED_PATHS,
|
|
1064
1066
|
'.github/CODEOWNERS',
|
|
@@ -1066,6 +1068,7 @@ const WORKSPACE_SEEDED_PATHS = new Set([
|
|
|
1066
1068
|
'CLAUDE.md',
|
|
1067
1069
|
'README.md',
|
|
1068
1070
|
'docs/architecture.md',
|
|
1071
|
+
'docs/observability.md',
|
|
1069
1072
|
'docs/git-workflow.md',
|
|
1070
1073
|
'docs/repository-operating-policy.md',
|
|
1071
1074
|
'docs/stage-deployment-authority.md',
|
|
@@ -7874,6 +7877,72 @@ convention, current only as far as the copy each actor reads.
|
|
|
7874
7877
|
`,
|
|
7875
7878
|
[workspace_files_shared_operation_claims_js_1.SHARED_OPERATION_CLAIMS_PATH]: (0, workspace_files_shared_operation_claims_js_1.renderSharedOperationClaims)(name),
|
|
7876
7879
|
'ebk.repository-policy.json': json(initialRepositoryPolicy),
|
|
7880
|
+
[observability_js_1.OBSERVABILITY_POLICY_PATH]: json(options.observabilityPolicy === undefined
|
|
7881
|
+
? (0, observability_js_1.defaultObservabilityPolicy)(activeStages, {
|
|
7882
|
+
productionProfile: initialRepositoryPolicy.productionFoundation.profile,
|
|
7883
|
+
})
|
|
7884
|
+
: (0, observability_js_1.parseObservabilityPolicy)(options.observabilityPolicy, activeStages)),
|
|
7885
|
+
'docs/observability.md': `# Observability spending and diagnostics
|
|
7886
|
+
|
|
7887
|
+
The seeded ebk.observability.json is the stage-specific policy. New development
|
|
7888
|
+
uses cost-optimized, active staging uses balanced, and production gets an explicit
|
|
7889
|
+
profile initialized from its capacity choice. Later capacity changes never alter
|
|
7890
|
+
that seeded observability choice. Task diagnostics are lean, but explicit retention
|
|
7891
|
+
and dormant-log preservation still apply; local hot diagnostics remain complete.
|
|
7892
|
+
This policy never pauses work or
|
|
7893
|
+
changes database protection, encryption, backups, topology or deployment authority.
|
|
7894
|
+
|
|
7895
|
+
Cost-optimized retains 5% of marked neutral request-start/success diagnostics, WARN Lambda
|
|
7896
|
+
system logs and no dashboards. Balanced retains 25%, INFO system logs and one
|
|
7897
|
+
Foundation dashboard. Standard retains 100%, INFO system logs and Foundation plus
|
|
7898
|
+
Slice dashboards. All retain errors, warnings, security, migration/event receipts,
|
|
7899
|
+
required counters and core failure/backlog alarms. Custom metrics are not free;
|
|
7900
|
+
batching reduces ingestion bytes, not billable metric series.
|
|
7901
|
+
|
|
7902
|
+
Mixed application/security log groups retain at least 30 days (90 for new standard
|
|
7903
|
+
production). diagnosticRetentionDays is an extension default; no generated log
|
|
7904
|
+
group uses it. Shorter diagnostic retention applies only to separately declared
|
|
7905
|
+
diagnostic groups, never mixed groups. Insights, enhanced database monitoring and
|
|
7906
|
+
tracing have no control in this policy. Retain Standard class for EMF and generated
|
|
7907
|
+
receipt queries. WAF enforcement and existing request-log privacy are unchanged.
|
|
7908
|
+
|
|
7909
|
+
Upgrades from older workspaces seed explicit prior retention and verbosity; they
|
|
7910
|
+
do not silently adopt shorter retention or remove dormant log groups. Review this
|
|
7911
|
+
seeded file to opt in deliberately. Profile changes require ordinary deployment;
|
|
7912
|
+
generators never change AWS. Workspace upgrade comes before Foundation/Slices.
|
|
7913
|
+
When enabling a new canonical stage, declare it here as well as in repository policy.
|
|
7914
|
+
|
|
7915
|
+
Stage overrides: profile; routineSuccessSampleRate (0–1); diagnosticRetentionDays;
|
|
7916
|
+
protectedRetentionDays (AWS-supported, at least 30); dashboards (none, stage, slice);
|
|
7917
|
+
systemLogLevel (WARN, INFO); retainDormantComponentLogs (boolean). Declared optional
|
|
7918
|
+
components always keep their logs. Only absent provider/webhook components may
|
|
7919
|
+
omit their otherwise unused log groups and findings alarms.
|
|
7920
|
+
|
|
7921
|
+
Fractional sampling uses a server-owned ID, not client correlation/request headers.
|
|
7922
|
+
Request starts are neutral, never successful. Legacy/standard retain an entry
|
|
7923
|
+
breadcrumb even for handlers that never return; cheap profiles may omit routine
|
|
7924
|
+
starts, but failures and receipts remain unsampled.
|
|
7925
|
+
|
|
7926
|
+
Custom reliability labels belong in each Slice's seeded reliability/metric-declarations.ts.
|
|
7927
|
+
Declare finite component/feature/operation values, never user, tenant, request or
|
|
7928
|
+
resource identifiers. Keep high-cardinality context in redacted logs. Only reviewed
|
|
7929
|
+
routine INFO successes may use routineSuccess; never mark receipts or security events.
|
|
7930
|
+
Upgrades flag the new declaration requirement with a reconciliation work marker.
|
|
7931
|
+
Undeclared tuples and invalid observations produce bounded reason-only warnings;
|
|
7932
|
+
invalid latency never suppresses the valid operation counters.
|
|
7933
|
+
|
|
7934
|
+
At low traffic, fixed dashboards, alarms and metric series can dominate the bill.
|
|
7935
|
+
Profile savings primarily change dashboard inventory; fresh disabled adapters omit
|
|
7936
|
+
two dormant groups and findings alarms. Sampling/batching affect ingestion and
|
|
7937
|
+
scanning volume, while retention affects storage only where applied. No live
|
|
7938
|
+
saving or free-tier discount is implied by the list-price estimate.
|
|
7939
|
+
|
|
7940
|
+
Diagnostics are on demand. Budget CloudWatch API metric retrieval as well as
|
|
7941
|
+
alarms, storage, ingestion, scanning and custom series. Narrow queries to the
|
|
7942
|
+
exact owned stage/resources/window; account-wide repeated sweeps are not a
|
|
7943
|
+
default application behavior. Never reduce a safety check's coverage or cadence
|
|
7944
|
+
to hide its cost. Measure actual billing after deployment, not just estimates.
|
|
7945
|
+
`,
|
|
7877
7946
|
'nx.json': json({
|
|
7878
7947
|
$schema: './node_modules/nx/schemas/nx-schema.json',
|
|
7879
7948
|
defaultBase: 'develop',
|
|
@@ -8222,6 +8291,7 @@ ${foundationPlan.resources.postgres ? ' foundationDatabaseEndpointHost,' : ''}
|
|
|
8222
8291
|
foundationSsmPath,
|
|
8223
8292
|
normalizeRouterWafPolicy,
|
|
8224
8293
|
reconcileRouterWafBlockingRehearsal,
|
|
8294
|
+
resolveObservabilityPolicy,
|
|
8225
8295
|
routerWafContractDigest,
|
|
8226
8296
|
type FoundationSsmKey,
|
|
8227
8297
|
} from '@empire-builder-kit/nx/foundation';
|
|
@@ -8242,6 +8312,7 @@ import routerWafBlockingRehearsal from '../security/router-waf-blocking-rehearsa
|
|
|
8242
8312
|
import routerWafLiveEvidence from '../security/router-waf-live-evidence.json';
|
|
8243
8313
|
import routerWafPolicy from '../security/router-waf.json';
|
|
8244
8314
|
import repositoryPolicy from '../../../ebk.repository-policy.json';
|
|
8315
|
+
import observabilityPolicy from '../../../ebk.observability.json';
|
|
8245
8316
|
|
|
8246
8317
|
function identityDomainPrefix(stage: string, accountId: string): string {
|
|
8247
8318
|
if (!/^\\d{12}$/.test(accountId)) {
|
|
@@ -8277,6 +8348,11 @@ function publishFoundation(values: Partial<Record<FoundationSsmKey, any>>) {
|
|
|
8277
8348
|
|
|
8278
8349
|
export function foundation() {
|
|
8279
8350
|
const isProduction = $app.stage === 'production';
|
|
8351
|
+
const observability = resolveObservabilityPolicy({
|
|
8352
|
+
policy: observabilityPolicy,
|
|
8353
|
+
stage: $app.stage,
|
|
8354
|
+
productionProfile: process.env.EBK_PRODUCTION_FOUNDATION_PROFILE,
|
|
8355
|
+
});
|
|
8280
8356
|
${foundationPlan.resources.postgres ? " const isStaging = $app.stage === 'staging';" : ''}
|
|
8281
8357
|
const rootDomain = process.env.EBK_ROOT_DOMAIN?.trim();
|
|
8282
8358
|
const productionConfiguration = isProduction
|
|
@@ -8753,7 +8829,7 @@ ${foundationPlan.resources.postgres
|
|
|
8753
8829
|
{ dependsOn: [alertTopicPolicy] },
|
|
8754
8830
|
)
|
|
8755
8831
|
: undefined;
|
|
8756
|
-
const dashboard = new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8832
|
+
const dashboard = observability.dashboards === 'none' ? undefined : new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8757
8833
|
dashboardName: 'ebk-' + $app.stage + '-foundation',
|
|
8758
8834
|
dashboardBody: databaseInstanceId.apply((identifier: string) => JSON.stringify({
|
|
8759
8835
|
widgets: [
|
|
@@ -8824,12 +8900,18 @@ ${foundationPlan.resources.postgres
|
|
|
8824
8900
|
treatMissingData: 'notBreaching',
|
|
8825
8901
|
},
|
|
8826
8902
|
);`
|
|
8827
|
-
: ` const dashboard = new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8903
|
+
: ` const dashboard = observability.dashboards === 'none' ? undefined : new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8828
8904
|
dashboardName: 'ebk-' + $app.stage + '-foundation',
|
|
8829
|
-
dashboardBody: JSON.stringify({ widgets: [{
|
|
8830
|
-
type: '
|
|
8831
|
-
properties: {
|
|
8832
|
-
|
|
8905
|
+
dashboardBody: router.distributionID.apply((distributionId: string) => JSON.stringify({ widgets: [{
|
|
8906
|
+
type: 'metric', x: 0, y: 0, width: 24, height: 6,
|
|
8907
|
+
properties: {
|
|
8908
|
+
title: 'Router requests and errors', region: 'us-east-1', period: 300,
|
|
8909
|
+
metrics: [
|
|
8910
|
+
['AWS/CloudFront', 'Requests', 'DistributionId', distributionId, 'Region', 'Global', { stat: 'Sum' }],
|
|
8911
|
+
['AWS/CloudFront', '5xxErrorRate', 'DistributionId', distributionId, 'Region', 'Global', { stat: 'Average', yAxis: 'right' }],
|
|
8912
|
+
],
|
|
8913
|
+
},
|
|
8914
|
+
}] })),
|
|
8833
8915
|
});`}
|
|
8834
8916
|
|
|
8835
8917
|
if (new Set(['development', 'staging', 'production']).has($app.stage)) {
|
|
@@ -8879,7 +8961,7 @@ ${foundationPlan.resources.containerCompute ? ' clusterId: cluster.id,' : ''}
|
|
|
8879
8961
|
contractVersion: '${foundationPlan.descriptor.contractVersion}',
|
|
8880
8962
|
costAnomalySubscriptionArn: accountCostAnomalySubscription?.arn,
|
|
8881
8963
|
${foundationPlan.resources.postgres ? ' databaseCapacityAlarmName: databaseCapacityAlarm.name,' : ''}
|
|
8882
|
-
dashboardName: dashboard
|
|
8964
|
+
dashboardName: dashboard?.dashboardName,
|
|
8883
8965
|
${foundationPlan.resources.postgres
|
|
8884
8966
|
? ` databaseClusterId: database.id,
|
|
8885
8967
|
databaseEventSubscriptionId: databaseEvents?.id,`
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one identity table for every alarm a Standard Slice registers.
|
|
3
|
+
*
|
|
4
|
+
* The seeded operations/reliability.json (its alarmRegistrations and
|
|
5
|
+
* deployedAlarmResources) and every managed MetricAlarm description
|
|
6
|
+
* (infra/reliability.ts, infra/product.ts, infra/key-value-retention.ts) are
|
|
7
|
+
* rendered from this table. The generated `scripts/verify-reliability.mjs
|
|
8
|
+
* --deployed` compares the inventory's owner, route and runbook with each
|
|
9
|
+
* deployed alarm's description, so a value written in two places can drift
|
|
10
|
+
* into a deployed alarm the verifier rejects (CROSS-SLICE-RETENTION-IDENTITY-003).
|
|
11
|
+
*
|
|
12
|
+
* Where the seeded and managed values disagreed, the seeded value is kept:
|
|
13
|
+
* an upgrade rewrites only the managed emitters, so aligning them with the
|
|
14
|
+
* seeded inventory repairs every existing adopter without a hand edit.
|
|
15
|
+
*
|
|
16
|
+
* For the same reason the runbook of an existing ID, and the owner and route
|
|
17
|
+
* from sliceAlarmOwnership, are frozen for existing adopters:
|
|
18
|
+
* built-in-plan-alarm-identity.spec.ts pins them, and changing one needs a
|
|
19
|
+
* seeded operations/reliability.json migration.
|
|
20
|
+
*/
|
|
21
|
+
declare const SLICE_ALARM_IDENTITIES: {
|
|
22
|
+
readonly 'alert-delivery-degraded': {
|
|
23
|
+
readonly businessSymptom: "The primary alert route is failing delivery.";
|
|
24
|
+
readonly runbook: "alert-delivery";
|
|
25
|
+
};
|
|
26
|
+
readonly 'api-fast-burn': {
|
|
27
|
+
readonly businessSymptom: "Critical API operations are failing.";
|
|
28
|
+
readonly runbook: "api-recovery";
|
|
29
|
+
};
|
|
30
|
+
readonly 'api-slow-burn': {
|
|
31
|
+
readonly businessSymptom: "Critical API operations have sustained failures.";
|
|
32
|
+
readonly runbook: "api-recovery";
|
|
33
|
+
};
|
|
34
|
+
readonly 'async-target-dlq-depth': {
|
|
35
|
+
readonly businessSymptom: "An asynchronous target has terminal failures.";
|
|
36
|
+
readonly runbook: "async-recovery";
|
|
37
|
+
};
|
|
38
|
+
readonly 'data-export-cleanup-deadline': {
|
|
39
|
+
readonly businessSymptom: "Confidential-export residue exceeded its deletion deadline.";
|
|
40
|
+
readonly runbook: "database-recovery";
|
|
41
|
+
};
|
|
42
|
+
readonly 'data-export-cleanup-failure': {
|
|
43
|
+
readonly businessSymptom: "The confidential-export cleanup invocation is failing.";
|
|
44
|
+
readonly runbook: "database-recovery";
|
|
45
|
+
};
|
|
46
|
+
readonly 'data-export-cleanup-invocation-missing': {
|
|
47
|
+
readonly businessSymptom: "The scheduled confidential-export cleanup is not running.";
|
|
48
|
+
readonly runbook: "database-recovery";
|
|
49
|
+
};
|
|
50
|
+
readonly 'data-protection-findings': {
|
|
51
|
+
readonly businessSymptom: "A managed log group contains a protected-data finding.";
|
|
52
|
+
readonly runbook: "log-investigation";
|
|
53
|
+
};
|
|
54
|
+
readonly 'database-capacity': {
|
|
55
|
+
readonly businessSymptom: "Slice data access or durable event delivery is being throttled.";
|
|
56
|
+
readonly runbook: "database-recovery";
|
|
57
|
+
};
|
|
58
|
+
readonly 'event-delivery-attempts': {
|
|
59
|
+
readonly businessSymptom: "A domain-event intent is repeatedly failing delivery.";
|
|
60
|
+
readonly runbook: "async-recovery";
|
|
61
|
+
};
|
|
62
|
+
readonly 'event-dlq-depth': {
|
|
63
|
+
readonly businessSymptom: "Domain-event processing has terminal failures.";
|
|
64
|
+
readonly runbook: "async-recovery";
|
|
65
|
+
};
|
|
66
|
+
readonly 'event-intent-rejected': {
|
|
67
|
+
readonly businessSymptom: "A retained domain-event intent cannot be delivered.";
|
|
68
|
+
readonly runbook: "async-recovery";
|
|
69
|
+
};
|
|
70
|
+
readonly 'function-failure': {
|
|
71
|
+
readonly businessSymptom: "The generated confidential-export cleanup Function has a terminal invocation error.";
|
|
72
|
+
readonly runbook: "api-recovery";
|
|
73
|
+
};
|
|
74
|
+
readonly 'inbox-cleanup-backlog': {
|
|
75
|
+
readonly businessSymptom: "Terminal asynchronous inbox records are accumulating.";
|
|
76
|
+
readonly runbook: "async-recovery";
|
|
77
|
+
};
|
|
78
|
+
readonly 'inbox-cleanup-errors': {
|
|
79
|
+
readonly businessSymptom: "The asynchronous inbox cleanup job is failing.";
|
|
80
|
+
readonly runbook: "async-recovery";
|
|
81
|
+
};
|
|
82
|
+
readonly 'key-value-reconciliation-errors': {
|
|
83
|
+
readonly businessSymptom: "Durable domain-event recovery is failing.";
|
|
84
|
+
readonly runbook: "async-recovery";
|
|
85
|
+
};
|
|
86
|
+
readonly 'key-value-stream-delivery-errors': {
|
|
87
|
+
readonly businessSymptom: "The key-value stream delivery Function failed an invocation.";
|
|
88
|
+
readonly runbook: "async-recovery";
|
|
89
|
+
};
|
|
90
|
+
readonly 'key-value-stream-iterator-age': {
|
|
91
|
+
readonly businessSymptom: "Prompt domain-event delivery from the key-value stream is falling behind.";
|
|
92
|
+
readonly runbook: "async-recovery";
|
|
93
|
+
};
|
|
94
|
+
readonly 'outbox-backlog': {
|
|
95
|
+
readonly businessSymptom: "Durable domain-event intents remain undelivered.";
|
|
96
|
+
readonly runbook: "async-recovery";
|
|
97
|
+
};
|
|
98
|
+
readonly 'outbox-relay-errors': {
|
|
99
|
+
readonly businessSymptom: "The isolated performance-sink outbox relay is failing.";
|
|
100
|
+
readonly runbook: "async-recovery";
|
|
101
|
+
};
|
|
102
|
+
readonly 'performance-load-cleanup-backlog': {
|
|
103
|
+
readonly businessSymptom: "Expired protected performance-load control records are accumulating.";
|
|
104
|
+
readonly runbook: "performance-capacity-cost";
|
|
105
|
+
};
|
|
106
|
+
readonly 'performance-load-cleanup-deadline': {
|
|
107
|
+
readonly businessSymptom: "Protected performance-load residue exceeded its cleanup deadline.";
|
|
108
|
+
readonly runbook: "performance-capacity-cost";
|
|
109
|
+
};
|
|
110
|
+
readonly 'provider-dlq-depth': {
|
|
111
|
+
readonly businessSymptom: "Provider deliveries have terminal failures.";
|
|
112
|
+
readonly runbook: "async-recovery";
|
|
113
|
+
};
|
|
114
|
+
readonly 'provider-queue-age': {
|
|
115
|
+
readonly businessSymptom: "Accepted provider work is missing its deadline.";
|
|
116
|
+
readonly runbook: "async-recovery";
|
|
117
|
+
};
|
|
118
|
+
readonly 'retention-job-failure': {
|
|
119
|
+
readonly businessSymptom: "The built-in retention Job terminated unsuccessfully.";
|
|
120
|
+
readonly runbook: "database-recovery";
|
|
121
|
+
};
|
|
122
|
+
readonly 'sql-outbox-attempts': {
|
|
123
|
+
readonly businessSymptom: "A relational event intent is repeatedly failing delivery.";
|
|
124
|
+
readonly runbook: "async-recovery";
|
|
125
|
+
};
|
|
126
|
+
readonly 'sql-outbox-backlog': {
|
|
127
|
+
readonly businessSymptom: "Relational event intents remain undelivered.";
|
|
128
|
+
readonly runbook: "async-recovery";
|
|
129
|
+
};
|
|
130
|
+
readonly 'sql-outbox-relay-errors': {
|
|
131
|
+
readonly businessSymptom: "Relational event delivery is failing.";
|
|
132
|
+
readonly runbook: "async-recovery";
|
|
133
|
+
};
|
|
134
|
+
readonly 'web-latency-fast-burn': {
|
|
135
|
+
readonly businessSymptom: "Server-rendered routes exceed the latency objective.";
|
|
136
|
+
readonly runbook: "web-recovery";
|
|
137
|
+
};
|
|
138
|
+
readonly 'web-latency-slow-burn': {
|
|
139
|
+
readonly businessSymptom: "Server-rendered routes have sustained latency degradation.";
|
|
140
|
+
readonly runbook: "web-recovery";
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
export type SliceAlarmId = keyof typeof SLICE_ALARM_IDENTITIES;
|
|
144
|
+
export interface SliceAlarmIdentity {
|
|
145
|
+
businessSymptom: string;
|
|
146
|
+
id: SliceAlarmId;
|
|
147
|
+
owner: string;
|
|
148
|
+
route: string;
|
|
149
|
+
/** The Slice-relative runbook path that the description and inventory name. */
|
|
150
|
+
runbook: string;
|
|
151
|
+
/** The alarm registration's reference to the same runbook. */
|
|
152
|
+
runbookRef: string;
|
|
153
|
+
}
|
|
154
|
+
/** The owner and escalation route every built-in Slice alarm carries. */
|
|
155
|
+
export declare function sliceAlarmOwnership(name: string): {
|
|
156
|
+
owner: string;
|
|
157
|
+
route: string;
|
|
158
|
+
};
|
|
159
|
+
export declare function sliceAlarmIdentity(name: string, id: SliceAlarmId): SliceAlarmIdentity;
|
|
160
|
+
/**
|
|
161
|
+
* The generated description helper's argument for one alarm, as TypeScript
|
|
162
|
+
* source. Both generated helpers (`alarmDescription` in infra/reliability.ts
|
|
163
|
+
* and `operationalAlarmDescription` in infra/product.ts) add the owner,
|
|
164
|
+
* route, schema version and Slice from sliceAlarmOwnership.
|
|
165
|
+
*/
|
|
166
|
+
export declare function renderSliceAlarmDescriptionInput(name: string, id: SliceAlarmId, indent: string): string;
|
|
167
|
+
/**
|
|
168
|
+
* The complete alarm description object for one alarm, as TypeScript source
|
|
169
|
+
* for an emitter without a description helper. Keys are in the helpers'
|
|
170
|
+
* order.
|
|
171
|
+
*/
|
|
172
|
+
export declare function renderSliceAlarmDescriptionObject(name: string, id: SliceAlarmId): string;
|
|
173
|
+
export {};
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sliceAlarmOwnership = sliceAlarmOwnership;
|
|
4
|
+
exports.sliceAlarmIdentity = sliceAlarmIdentity;
|
|
5
|
+
exports.renderSliceAlarmDescriptionInput = renderSliceAlarmDescriptionInput;
|
|
6
|
+
exports.renderSliceAlarmDescriptionObject = renderSliceAlarmDescriptionObject;
|
|
7
|
+
/**
|
|
8
|
+
* The one identity table for every alarm a Standard Slice registers.
|
|
9
|
+
*
|
|
10
|
+
* The seeded operations/reliability.json (its alarmRegistrations and
|
|
11
|
+
* deployedAlarmResources) and every managed MetricAlarm description
|
|
12
|
+
* (infra/reliability.ts, infra/product.ts, infra/key-value-retention.ts) are
|
|
13
|
+
* rendered from this table. The generated `scripts/verify-reliability.mjs
|
|
14
|
+
* --deployed` compares the inventory's owner, route and runbook with each
|
|
15
|
+
* deployed alarm's description, so a value written in two places can drift
|
|
16
|
+
* into a deployed alarm the verifier rejects (CROSS-SLICE-RETENTION-IDENTITY-003).
|
|
17
|
+
*
|
|
18
|
+
* Where the seeded and managed values disagreed, the seeded value is kept:
|
|
19
|
+
* an upgrade rewrites only the managed emitters, so aligning them with the
|
|
20
|
+
* seeded inventory repairs every existing adopter without a hand edit.
|
|
21
|
+
*
|
|
22
|
+
* For the same reason the runbook of an existing ID, and the owner and route
|
|
23
|
+
* from sliceAlarmOwnership, are frozen for existing adopters:
|
|
24
|
+
* built-in-plan-alarm-identity.spec.ts pins them, and changing one needs a
|
|
25
|
+
* seeded operations/reliability.json migration.
|
|
26
|
+
*/
|
|
27
|
+
const SLICE_ALARM_IDENTITIES = {
|
|
28
|
+
'alert-delivery-degraded': {
|
|
29
|
+
businessSymptom: 'The primary alert route is failing delivery.',
|
|
30
|
+
runbook: 'alert-delivery',
|
|
31
|
+
},
|
|
32
|
+
'api-fast-burn': {
|
|
33
|
+
businessSymptom: 'Critical API operations are failing.',
|
|
34
|
+
runbook: 'api-recovery',
|
|
35
|
+
},
|
|
36
|
+
'api-slow-burn': {
|
|
37
|
+
businessSymptom: 'Critical API operations have sustained failures.',
|
|
38
|
+
runbook: 'api-recovery',
|
|
39
|
+
},
|
|
40
|
+
'async-target-dlq-depth': {
|
|
41
|
+
businessSymptom: 'An asynchronous target has terminal failures.',
|
|
42
|
+
runbook: 'async-recovery',
|
|
43
|
+
},
|
|
44
|
+
'data-export-cleanup-deadline': {
|
|
45
|
+
businessSymptom: 'Confidential-export residue exceeded its deletion deadline.',
|
|
46
|
+
runbook: 'database-recovery',
|
|
47
|
+
},
|
|
48
|
+
'data-export-cleanup-failure': {
|
|
49
|
+
businessSymptom: 'The confidential-export cleanup invocation is failing.',
|
|
50
|
+
runbook: 'database-recovery',
|
|
51
|
+
},
|
|
52
|
+
'data-export-cleanup-invocation-missing': {
|
|
53
|
+
businessSymptom: 'The scheduled confidential-export cleanup is not running.',
|
|
54
|
+
runbook: 'database-recovery',
|
|
55
|
+
},
|
|
56
|
+
'data-protection-findings': {
|
|
57
|
+
businessSymptom: 'A managed log group contains a protected-data finding.',
|
|
58
|
+
runbook: 'log-investigation',
|
|
59
|
+
},
|
|
60
|
+
'database-capacity': {
|
|
61
|
+
businessSymptom: 'Slice data access or durable event delivery is being throttled.',
|
|
62
|
+
runbook: 'database-recovery',
|
|
63
|
+
},
|
|
64
|
+
'event-delivery-attempts': {
|
|
65
|
+
businessSymptom: 'A domain-event intent is repeatedly failing delivery.',
|
|
66
|
+
runbook: 'async-recovery',
|
|
67
|
+
},
|
|
68
|
+
'event-dlq-depth': {
|
|
69
|
+
businessSymptom: 'Domain-event processing has terminal failures.',
|
|
70
|
+
runbook: 'async-recovery',
|
|
71
|
+
},
|
|
72
|
+
'event-intent-rejected': {
|
|
73
|
+
businessSymptom: 'A retained domain-event intent cannot be delivered.',
|
|
74
|
+
runbook: 'async-recovery',
|
|
75
|
+
},
|
|
76
|
+
'function-failure': {
|
|
77
|
+
businessSymptom: 'The generated confidential-export cleanup Function has a terminal invocation error.',
|
|
78
|
+
runbook: 'api-recovery',
|
|
79
|
+
},
|
|
80
|
+
'inbox-cleanup-backlog': {
|
|
81
|
+
businessSymptom: 'Terminal asynchronous inbox records are accumulating.',
|
|
82
|
+
runbook: 'async-recovery',
|
|
83
|
+
},
|
|
84
|
+
'inbox-cleanup-errors': {
|
|
85
|
+
businessSymptom: 'The asynchronous inbox cleanup job is failing.',
|
|
86
|
+
runbook: 'async-recovery',
|
|
87
|
+
},
|
|
88
|
+
'key-value-reconciliation-errors': {
|
|
89
|
+
businessSymptom: 'Durable domain-event recovery is failing.',
|
|
90
|
+
runbook: 'async-recovery',
|
|
91
|
+
},
|
|
92
|
+
'key-value-stream-delivery-errors': {
|
|
93
|
+
businessSymptom: 'The key-value stream delivery Function failed an invocation.',
|
|
94
|
+
runbook: 'async-recovery',
|
|
95
|
+
},
|
|
96
|
+
'key-value-stream-iterator-age': {
|
|
97
|
+
businessSymptom: 'Prompt domain-event delivery from the key-value stream is falling behind.',
|
|
98
|
+
runbook: 'async-recovery',
|
|
99
|
+
},
|
|
100
|
+
'outbox-backlog': {
|
|
101
|
+
businessSymptom: 'Durable domain-event intents remain undelivered.',
|
|
102
|
+
runbook: 'async-recovery',
|
|
103
|
+
},
|
|
104
|
+
'outbox-relay-errors': {
|
|
105
|
+
businessSymptom: 'The isolated performance-sink outbox relay is failing.',
|
|
106
|
+
runbook: 'async-recovery',
|
|
107
|
+
},
|
|
108
|
+
'performance-load-cleanup-backlog': {
|
|
109
|
+
businessSymptom: 'Expired protected performance-load control records are accumulating.',
|
|
110
|
+
runbook: 'performance-capacity-cost',
|
|
111
|
+
},
|
|
112
|
+
'performance-load-cleanup-deadline': {
|
|
113
|
+
businessSymptom: 'Protected performance-load residue exceeded its cleanup deadline.',
|
|
114
|
+
runbook: 'performance-capacity-cost',
|
|
115
|
+
},
|
|
116
|
+
'provider-dlq-depth': {
|
|
117
|
+
businessSymptom: 'Provider deliveries have terminal failures.',
|
|
118
|
+
runbook: 'async-recovery',
|
|
119
|
+
},
|
|
120
|
+
'provider-queue-age': {
|
|
121
|
+
businessSymptom: 'Accepted provider work is missing its deadline.',
|
|
122
|
+
runbook: 'async-recovery',
|
|
123
|
+
},
|
|
124
|
+
// The Step Functions retention workflow is a database-lifecycle job: its
|
|
125
|
+
// recovery belongs with the other lifecycle alarms in database-recovery.md,
|
|
126
|
+
// which routes the operator to the Job's own README for the run procedure.
|
|
127
|
+
'retention-job-failure': {
|
|
128
|
+
businessSymptom: 'The built-in retention Job terminated unsuccessfully.',
|
|
129
|
+
runbook: 'database-recovery',
|
|
130
|
+
},
|
|
131
|
+
'sql-outbox-attempts': {
|
|
132
|
+
businessSymptom: 'A relational event intent is repeatedly failing delivery.',
|
|
133
|
+
runbook: 'async-recovery',
|
|
134
|
+
},
|
|
135
|
+
'sql-outbox-backlog': {
|
|
136
|
+
businessSymptom: 'Relational event intents remain undelivered.',
|
|
137
|
+
runbook: 'async-recovery',
|
|
138
|
+
},
|
|
139
|
+
'sql-outbox-relay-errors': {
|
|
140
|
+
businessSymptom: 'Relational event delivery is failing.',
|
|
141
|
+
runbook: 'async-recovery',
|
|
142
|
+
},
|
|
143
|
+
'web-latency-fast-burn': {
|
|
144
|
+
businessSymptom: 'Server-rendered routes exceed the latency objective.',
|
|
145
|
+
runbook: 'web-recovery',
|
|
146
|
+
},
|
|
147
|
+
'web-latency-slow-burn': {
|
|
148
|
+
businessSymptom: 'Server-rendered routes have sustained latency degradation.',
|
|
149
|
+
runbook: 'web-recovery',
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
/** The owner and escalation route every built-in Slice alarm carries. */
|
|
153
|
+
function sliceAlarmOwnership(name) {
|
|
154
|
+
return { owner: `${name}-product`, route: `${name}-on-call` };
|
|
155
|
+
}
|
|
156
|
+
function sliceAlarmIdentity(name, id) {
|
|
157
|
+
const { businessSymptom, runbook } = SLICE_ALARM_IDENTITIES[id];
|
|
158
|
+
return {
|
|
159
|
+
businessSymptom,
|
|
160
|
+
id,
|
|
161
|
+
...sliceAlarmOwnership(name),
|
|
162
|
+
runbook: `docs/runbooks/${runbook}.md`,
|
|
163
|
+
runbookRef: `runbook:${runbook}`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/** A TypeScript single-quoted string literal. */
|
|
167
|
+
function typescriptString(value) {
|
|
168
|
+
if (/[\\'\n\r\u2028\u2029]/u.test(value)) {
|
|
169
|
+
throw new Error(`Alarm identity text cannot be rendered: ${value}`);
|
|
170
|
+
}
|
|
171
|
+
return `'${value}'`;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The generated description helper's argument for one alarm, as TypeScript
|
|
175
|
+
* source. Both generated helpers (`alarmDescription` in infra/reliability.ts
|
|
176
|
+
* and `operationalAlarmDescription` in infra/product.ts) add the owner,
|
|
177
|
+
* route, schema version and Slice from sliceAlarmOwnership.
|
|
178
|
+
*/
|
|
179
|
+
function renderSliceAlarmDescriptionInput(name, id, indent) {
|
|
180
|
+
const identity = sliceAlarmIdentity(name, id);
|
|
181
|
+
const symptom = `${indent} businessSymptom: ${typescriptString(identity.businessSymptom)},`;
|
|
182
|
+
return [
|
|
183
|
+
'{',
|
|
184
|
+
// Wrap a symptom that would not fit 80 columns, as the template did.
|
|
185
|
+
symptom.length <= 80
|
|
186
|
+
? symptom
|
|
187
|
+
: `${indent} businessSymptom:\n${indent} ${typescriptString(identity.businessSymptom)},`,
|
|
188
|
+
`${indent} id: ${typescriptString(identity.id)},`,
|
|
189
|
+
`${indent} runbook: ${typescriptString(identity.runbook)},`,
|
|
190
|
+
`${indent}}`,
|
|
191
|
+
].join('\n');
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The complete alarm description object for one alarm, as TypeScript source
|
|
195
|
+
* for an emitter without a description helper. Keys are in the helpers'
|
|
196
|
+
* order.
|
|
197
|
+
*/
|
|
198
|
+
function renderSliceAlarmDescriptionObject(name, id) {
|
|
199
|
+
const identity = sliceAlarmIdentity(name, id);
|
|
200
|
+
return `{ businessSymptom: ${typescriptString(identity.businessSymptom)}, id: ${typescriptString(identity.id)}, owner: ${typescriptString(identity.owner)}, route: ${typescriptString(identity.route)}, runbook: ${typescriptString(identity.runbook)}, schemaVersion: 1, slice: ${typescriptString(name)} }`;
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=built-in-plan-alarm-identity.js.map
|