Skip to content

Conversation

svozza
Copy link
Contributor

@svozza svozza commented Oct 17, 2025

Summary

This PR adds support for using an async context (specifically from the InvokeStore package) in the Metrics utility. This allows users to emit metrics that are isolated specifically to the current lambda invocation, isolated from any other executions.

Changes

  • Added specific storage classes for metrics, metadata and dimensions:
    • MetricsStore
    • MetadataStore
    • DimensionStore
  • The Metrics class only accesses the data in these stores through this interface and never touches the stored objects directly.
  • These storage classes check whether they are running in the InvokeStore context: if they are then the metrics are stored in the current async context, otherwise we fallback to a plain instance wide object as per the current implementation.
  • The storage class handle converting the data into the correct format now rather than the Metrics class, e.g., setMetric will check if the metric already exists and handle converting values into an array if the metric is already there. Likewise with setting timestamps.
  • Added specific concurrency tests to ensure isolation is working as intended for all three stores and the Metrics class as a whole.

Issue number: closes #4662


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

@pull-request-size pull-request-size bot added the size/XXL PRs with 1K+ LOC, largely documentation related label Oct 17, 2025
@boring-cyborg boring-cyborg bot added dependencies Changes that touch dependencies, e.g. Dependabot, etc. metrics This item relates to the Metrics Utility tests PRs that add or change tests labels Oct 17, 2025
@svozza svozza force-pushed the async-local-storage-metrics branch from b387413 to bd08c00 Compare October 17, 2025 16:35
@boring-cyborg boring-cyborg bot added automation This item relates to automation parser This item relates to the Parser Utility tracer This item relates to the Tracer Utility labels Oct 17, 2025
@svozza svozza force-pushed the async-local-storage-metrics branch 3 times, most recently from 2a9645b to bc27232 Compare October 17, 2025 16:42
@svozza svozza force-pushed the async-local-storage-metrics branch from 62d0f60 to 1c3040a Compare October 17, 2025 18:31
@svozza svozza changed the title use async local storage for metrics feat(metrics): use async local storage for metrics Oct 17, 2025
@svozza svozza force-pushed the async-local-storage-metrics branch from 1c3040a to b73b723 Compare October 17, 2025 19:57
@svozza svozza requested a review from sdangol October 17, 2025 21:42
@svozza svozza force-pushed the async-local-storage-metrics branch 2 times, most recently from fdf5b61 to a0a78f4 Compare October 17, 2025 21:47
@svozza svozza removed dependencies Changes that touch dependencies, e.g. Dependabot, etc. automation This item relates to automation tracer This item relates to the Tracer Utility parser This item relates to the Parser Utility labels Oct 17, 2025
@svozza svozza self-assigned this Oct 17, 2025
@svozza svozza force-pushed the async-local-storage-metrics branch from a0a78f4 to f5cae92 Compare October 18, 2025 05:16
@boring-cyborg boring-cyborg bot added the dependencies Changes that touch dependencies, e.g. Dependabot, etc. label Oct 18, 2025
@svozza svozza force-pushed the async-local-storage-metrics branch 4 times, most recently from 2214107 to d3d0801 Compare October 18, 2025 05:47
@svozza svozza force-pushed the async-local-storage-metrics branch 4 times, most recently from 0c2cbd2 to d03a774 Compare October 18, 2025 06:20
@svozza svozza force-pushed the async-local-storage-metrics branch from d03a774 to a3340db Compare October 18, 2025 06:27
dreamorosi
dreamorosi previously approved these changes Oct 18, 2025
Copy link
Contributor

@dreamorosi dreamorosi left a comment

Choose a reason for hiding this comment

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

Very nice work here, I haven't tested it and I won't be able to for a while's but the implementation makes a lot of sense - please if possible run some tests on your machine with the correct setup as we discussed.

Other than that, do you have any idea of whether there's a significant performance impact for this new implementation when used on a Lambda on demand?

"dependencies": {
"@aws-lambda-powertools/commons": "2.27.0"
"@aws-lambda-powertools/commons": "2.27.0",
"@aws/lambda-invoke-store": "0.1.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we added this as dependency of the commons pkg, do we need to declare it here again?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh that's a good point, we may not. Let me play around with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe showing my ignorance of npm workspaces but if it's used in multiple packages across the workspace, should it not be in the root package.json file rather than commons or metrics or whatever?

Copy link
Contributor

Choose a reason for hiding this comment

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

The main package.json doesn't get published to npm, only the package ones do. This means it won't be installed when the package gets installed.

In this case, it should be either in both or just in commons, since metrics depends on it.

When present in both, if the dependency version is aligned, it gets deduplicated, so only one copy gets installed.

In this case I was suggesting to bypass this risk entirely and just keep it as dependency for commons, but I don't feel too strongly about it since I don't expect this package to change very often.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, I knew I was missing something. Honestly, I'd rather be explicit so you can see what dependencies a package uses when you look at the dependency file so I'd be in favour of keeping it here.

}

getDimensions(): Dimensions {
return { ...this.#getDimensions() };
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we spreading and creating a new object here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because I don't want it to be possible to get a reference to the underlying object and be able to mutate it without going through the store interface.

@svozza
Copy link
Contributor Author

svozza commented Oct 18, 2025

Very nice work here, I haven't tested it and I won't be able to for a while's but the implementation makes a lot of sense - please if possible run some tests on your machine with the correct setup as we discussed.

Other than that, do you have any idea of whether there's a significant performance impact for this new implementation when used on a Lambda on demand?

Yes, I plan to do some perf testing (vs the original version) in a real lambda function on Monday.

Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Changes that touch dependencies, e.g. Dependabot, etc. metrics This item relates to the Metrics Utility size/XXL PRs with 1K+ LOC, largely documentation related tests PRs that add or change tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Allow use of InvokeStore in Metrics

2 participants