Skip to content

feat(metrics): add enhanced metrics support Co-authored-by: Brendan D…#711

Merged
sid88in merged 1 commit into
masterfrom
feat/enhanced-metrics
Jun 1, 2026
Merged

feat(metrics): add enhanced metrics support Co-authored-by: Brendan D…#711
sid88in merged 1 commit into
masterfrom
feat/enhanced-metrics

Conversation

@sid88in
Copy link
Copy Markdown
Owner

@sid88in sid88in commented May 30, 2026

Title: feat(metrics): add enhanced metrics support


Supersedes #644. Original implementation by Brendan Doyle (@DoyleBrendan) — rebased onto current master, corrected, and extended with tests. Because the branch diverged significantly (109+ commits, plus a jest 27 → 30 bump on master), this is opened as a fresh PR rather than an in-place update; the original work is credited via a Co-authored-by trailer.

What

Adds appSync.enhancedMetrics, which maps to the AppSync EnhancedMetricsConfig on AWS::AppSync::GraphQLApi, plus an optional per-resolver metricsConfig so resolver-level metrics can actually be enabled.

appSync:
  name: my-api
  enhancedMetrics:
    DataSourceLevelMetricsBehavior: 'PER_DATA_SOURCE_METRICS'
    OperationLevelMetricsConfig: 'ENABLED'
    ResolverLevelMetricsBehavior: 'PER_RESOLVER_METRICS'
  resolvers:
    Query.user:
      kind: UNIT
      dataSource: my_table
      metricsConfig: 'ENABLED' # opt this resolver into metrics

Correctness fixes on top of #644

  • OperationLevelMetricsConfig enum typo. The original value was ' DISABLED' (leading space) in both the type and the validation enum. AWS's value is DISABLED, so the correct value was rejected by validation while the space variant would fail at deploy — the disabled path was unusable. Fixed everywhere.
  • Required fields. AWS marks all three EnhancedMetricsConfig properties as required, but the schema required none, so enhancedMetrics: {} passed validation and would synthesize an incomplete config that fails at deploy. The schema now requires all three (and disallows unknown keys).
  • ResolverLevelMetricsBehavior was ignored. It was a required field in the public type but hardcoded to PER_RESOLVER_METRICS in the synthesized template. It's now honored from config.
  • Resolver MetricsConfig churn / non-functional feature. The original stamped MetricsConfig: 'DISABLED' onto every resolver unconditionally — changing the CloudFormation for every existing user on their next deploy, and (with PER_RESOLVER_METRICS + always-DISABLED) making it impossible to ever enable resolver metrics. Now MetricsConfig is emitted only when enhancedMetrics is configured, defaults to DISABLED, and is overridable per resolver via the new metricsConfig field. Stacks that don't use enhanced metrics get byte-identical CloudFormation.

New public config

  • resolvers.<Type>.<field>.metricsConfig: 'ENABLED' | 'DISABLED' (optional). Only emitted when enhancedMetrics is set. This is the only new public surface and the main thing to review — it's what makes PER_RESOLVER_METRICS meaningful.

Tests

  • Unit: API-level (EnhancedMetricsConfig emitted with all three values when set; absent otherwise), resolver-level (omitted without enhanced metrics; defaults to DISABLED; honors per-resolver override), and validation (valid full config; missing required field and bad value rejected).
  • e2e / CFN synthesis (offline): new examples/enhanced-metrics fixture + enhanced-metrics.e2e.test.ts asserting the synthesized template contains a complete EnhancedMetricsConfig and the expected per-resolver MetricsConfig values.
  • Local run: npm run lint clean, npm test (296 passing), npm run test:e2e (88 passing across 31 suites).

Reviewer notes / not covered here

  • Verified offline (CFN synthesis) only. A live serverless deploy is the final word on the in-place EnhancedMetricsConfig / MetricsConfig updates.
  • Not smoke-tested on Serverless Framework v4.

Co-authored-by: Brendan Doyle brendansdoyle@gmail.com

Summary by CodeRabbit

  • New Features

    • AppSync now supports Enhanced Metrics configuration, enabling metrics tracking at data source, operation, and resolver levels
    • Support for per-resolver metrics override settings
  • Documentation

    • Added comprehensive configuration guide for Enhanced Metrics with examples and reference values
    • New example project demonstrating Enhanced Metrics configuration

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

📝 Walkthrough

Walkthrough

This PR introduces comprehensive support for AppSync Enhanced Metrics configuration in the serverless-appsync-plugin, adding type definitions, validation rules, compilation logic, unit tests, and user documentation alongside a working example demonstrating the feature.

Changes

Enhanced Metrics Support

Layer / File(s) Summary
Type contracts and schema
src/types/common.ts, src/types/index.ts, src/types/plugin.ts, src/types/cloudFormation.ts
EnhancedMetricsConfig type defined with three metric-behavior fields; AppSyncConfig extended with optional enhancedMetrics; BaseResolverConfig extended with optional metricsConfig; CfnResolver.Properties extended with optional MetricsConfig string literal.
Validation schema
src/validation.ts
Validation rules added for metricsConfig enum and enhancedMetrics object; enhancedMetrics enforces required fields and rejects unknown properties via additionalProperties: false.
Core compilation logic
src/resources/Api.ts, src/resources/Resolver.ts
Api.compileEndpoint() conditionally merges EnhancedMetricsConfig into GraphQL API properties; Resolver.compile() conditionally emits MetricsConfig, defaulting to DISABLED when enhanced metrics are enabled and respecting per-resolver overrides.
Unit and validation tests
src/__tests__/api.test.ts, src/__tests__/resolvers.test.ts, src/__tests__/validation/base.test.ts
Added tests verifying endpoint compilation with and without enhanced metrics, resolver metrics config defaults and overrides, and validation of required fields and enum values.
Documentation and example
doc/enhancedMetrics.md, doc/general-config.md, examples/enhanced-metrics/schema.graphql, examples/enhanced-metrics/serverless.yml, e2e/enhanced-metrics.e2e.test.ts
Comprehensive documentation of enhanced metrics configuration and per-resolver behavior; updated general config reference; complete serverless.yml example with API key auth and mixed resolver metrics settings; e2e test validating the example synthesis and metrics configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • AlexHladin

Poem

🐰 Metrics blooming, enhanced and true,
Data flows sparkle in PER_RESOLVER hue,
Defaults to DISABLED, but you override,
From API down to resolvers we ride,
CloudFormation glows with metrics inside!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(metrics): add enhanced metrics support' clearly summarizes the main change: adding enhanced metrics support to the plugin, which is the primary objective across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/enhanced-metrics

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/enhanced-metrics/schema.graphql

Parsing error: '=' expected.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
e2e/enhanced-metrics.e2e.test.ts (1)

15-17: 💤 Low value

Guard cleanup() against a failed beforeAll.

If synthesize() throws in beforeAll, result remains undefined and afterAll will throw a TypeError, masking the real synthesis error in the test output.

♻️ Optional guard
   afterAll(() => {
-    result.cleanup();
+    result?.cleanup();
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/enhanced-metrics.e2e.test.ts` around lines 15 - 17, The afterAll hook
calls result.cleanup() unguarded so if synthesize() in beforeAll throws and
result is undefined the afterAll will throw a TypeError; update the afterAll to
check that result is defined (and optionally that result.cleanup is a function)
before calling cleanup, and ensure the beforeAll use of synthesize() remains
unchanged—look for the variables result, synthesize, beforeAll and afterAll in
the test to apply the guard.
src/resources/Resolver.ts (1)

34-41: AppSync ignores resolver-level MetricsConfig when resolverLevelMetricsBehavior is FULL_REQUEST_RESOLVER_METRICS, so defaulting to 'DISABLED' is behavior-neutral in that mode.

AWS AppSync documents that:

  • With FULL_REQUEST_RESOLVER_METRICS, enhanced metrics are emitted for all resolvers regardless of individual resolver MetricsConfig (so setting MetricsConfig: 'DISABLED' won’t opt a resolver out).
  • With PER_RESOLVER_METRICS, MetricsConfig acts as the per-resolver filter (so defaulting to 'DISABLED' when metricsConfig isn’t set is consistent with the intended behavior).

Optional: you could omit emitting MetricsConfig entirely when resolverLevelMetricsBehavior is FULL_REQUEST_RESOLVER_METRICS to reduce CloudFormation noise, but it won’t change runtime behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/resources/Resolver.ts` around lines 34 - 41, The current block always
sets Properties.MetricsConfig to a default 'DISABLED' whenever enhanced metrics
are enabled, but AppSync ignores per-resolver MetricsConfig when
resolverLevelMetricsBehavior is FULL_REQUEST_RESOLVER_METRICS; update the
conditional in Resolver.ts so you only set Properties.MetricsConfig (using
this.config.metricsConfig || 'DISABLED') when this.api.config.enhancedMetrics is
true AND this.api.config.resolverLevelMetricsBehavior !==
'FULL_REQUEST_RESOLVER_METRICS' (or omit the property entirely in that mode) so
CloudFormation noise is reduced and behavior remains correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@e2e/enhanced-metrics.e2e.test.ts`:
- Around line 15-17: The afterAll hook calls result.cleanup() unguarded so if
synthesize() in beforeAll throws and result is undefined the afterAll will throw
a TypeError; update the afterAll to check that result is defined (and optionally
that result.cleanup is a function) before calling cleanup, and ensure the
beforeAll use of synthesize() remains unchanged—look for the variables result,
synthesize, beforeAll and afterAll in the test to apply the guard.

In `@src/resources/Resolver.ts`:
- Around line 34-41: The current block always sets Properties.MetricsConfig to a
default 'DISABLED' whenever enhanced metrics are enabled, but AppSync ignores
per-resolver MetricsConfig when resolverLevelMetricsBehavior is
FULL_REQUEST_RESOLVER_METRICS; update the conditional in Resolver.ts so you only
set Properties.MetricsConfig (using this.config.metricsConfig || 'DISABLED')
when this.api.config.enhancedMetrics is true AND
this.api.config.resolverLevelMetricsBehavior !== 'FULL_REQUEST_RESOLVER_METRICS'
(or omit the property entirely in that mode) so CloudFormation noise is reduced
and behavior remains correct.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 62523da9-2f34-4151-9afc-c3df16e74dfe

📥 Commits

Reviewing files that changed from the base of the PR and between 082c00b and 3e60b0f.

⛔ Files ignored due to path filters (1)
  • src/__tests__/validation/__snapshots__/base.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (15)
  • doc/enhancedMetrics.md
  • doc/general-config.md
  • e2e/enhanced-metrics.e2e.test.ts
  • examples/enhanced-metrics/schema.graphql
  • examples/enhanced-metrics/serverless.yml
  • src/__tests__/api.test.ts
  • src/__tests__/resolvers.test.ts
  • src/__tests__/validation/base.test.ts
  • src/resources/Api.ts
  • src/resources/Resolver.ts
  • src/types/cloudFormation.ts
  • src/types/common.ts
  • src/types/index.ts
  • src/types/plugin.ts
  • src/validation.ts

@sid88in sid88in self-assigned this May 30, 2026
@sid88in sid88in merged commit ec624da into master Jun 1, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants