Skip to content

Commit bd08c00

Browse files
committed
use async local storage for metrics
1 parent 30a01b4 commit bd08c00

File tree

30 files changed

+1306
-144
lines changed

30 files changed

+1306
-144
lines changed

.github/scripts/release_patch_package_json.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,6 @@ const betaPackages = [];
8888

8989
// Temporarily update the original package.json file.
9090
// This version will be picked up during the `npm publish` step, so that
91-
// the version number and metadata in the registry are correct and match the tarball.
91+
// the version number and #metadata in the registry are correct and match the tarball.
9292
writeFileSync('package.json', JSON.stringify(newPkgJson, null, 2));
9393
})();

.github/workflows/layers_partitions.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
echo regions='["us-gov-east-1", "us-gov-west-1"]'>> "$GITHUB_OUTPUT"
8585
echo partition='aws-us-gov'>> "$GITHUB_OUTPUT"
8686
echo aud='sts.amazonaws.com'>> "$GITHUB_OUTPUT"
87-
# This job downloads the specified layer version from the main AWS partition (us-east-1) and stores both the layer zip file and metadata as GitHub Actions artifacts for use in deployment.
87+
# This job downloads the specified layer version from the main AWS partition (us-east-1) and stores both the layer zip file and #metadata as GitHub Actions artifacts for use in deployment.
8888
download:
8989
runs-on: ubuntu-latest
9090
permissions:
@@ -178,7 +178,7 @@ jobs:
178178
--action lambda:GetLayerVersion \
179179
--principal '*' \
180180
--version-number "$LAYER_VERSION"
181-
# This step retrieves the newly deployed layer metadata and compares it against the original source layer:
181+
# This step retrieves the newly deployed layer #metadata and compares it against the original source layer:
182182
# 1. SHA256 hash verification - ensures the layer content is identical to the source
183183
# 2. Description validation - confirms the version number in the description matches the source
184184
# 3. Layer Version number verification - validates that the layer version numbers match between source and target

examples/snippets/tracer/captureMethodManual.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ const getChargeId = async (): Promise<unknown> => {
1212
try {
1313
const res = { chargeId: '1234' };
1414

15-
// Add the response as metadata
15+
// Add the response as #metadata
1616
tracer.addResponseAsMetadata(res, 'chargeId');
1717

1818
return res;
1919
} catch (err) {
20-
// Add the error as metadata
20+
// Add the error as #metadata
2121
tracer.addErrorAsMetadata(err as Error);
2222
throw err;
2323
} finally {

examples/snippets/tracer/manual.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ export const handler = async (
2020
tracer.addServiceNameAnnotation();
2121

2222
try {
23-
// Add the response as metadata
23+
// Add the response as #metadata
2424
tracer.addResponseAsMetadata({}, process.env._HANDLER);
2525
} catch (err) {
26-
// Add the error as metadata
26+
// Add the error as #metadata
2727
tracer.addErrorAsMetadata(err as Error);
2828
throw err;
2929
} finally {

package-lock.json

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/kafka/src/types/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ type ConsumerRecord<K, V> = {
8080
};
8181

8282
/**
83-
* Represents a collection of Kafka consumer records, along with MSK event metadata.
83+
* Represents a collection of Kafka consumer records, along with MSK event #metadata.
8484
*/
8585
type ConsumerRecords<K = unknown, V = unknown> = {
8686
/**

packages/metrics/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
"url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues"
8989
},
9090
"dependencies": {
91-
"@aws-lambda-powertools/commons": "2.27.0"
91+
"@aws-lambda-powertools/commons": "2.27.0",
92+
"@aws/lambda-invoke-store": "0.1.0"
9293
},
9394
"keywords": [
9495
"aws",
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { InvokeStore } from '@aws/lambda-invoke-store';
2+
import type { Dimensions } from './types/Metrics.js';
3+
4+
/**
5+
* Manages storage of metrics dimensions with automatic context detection.
6+
*
7+
* This class abstracts the storage mechanism for metrics, automatically
8+
* choosing between AsyncLocalStorage (when in async context) and a fallback
9+
* object (when outside async context). The decision is made at runtime on
10+
* every method call to support Lambda's transition to async contexts.
11+
*/
12+
class DimensionsStore {
13+
#fallbackDimensions: Dimensions = {};
14+
#fallbackDimensionSets: Dimensions[] = [];
15+
16+
#getDimensions(): Dimensions {
17+
if (InvokeStore.getContext() === undefined) {
18+
return this.#fallbackDimensions;
19+
}
20+
21+
let stored = InvokeStore.get('dimensions') as Dimensions | undefined;
22+
if (stored == null) {
23+
stored = {};
24+
InvokeStore.set('dimensions', stored);
25+
}
26+
return stored;
27+
}
28+
29+
#getDimensionSets(): Dimensions[] {
30+
if (InvokeStore.getContext() !== undefined) {
31+
let stored = InvokeStore.get('dimensionSets') as Dimensions[] | undefined;
32+
if (stored == null) {
33+
stored = [];
34+
InvokeStore.set('dimensionSets', stored);
35+
}
36+
return stored;
37+
}
38+
return this.#fallbackDimensionSets;
39+
}
40+
41+
addDimension(name: string, value: string): void {
42+
this.#getDimensions()[name] = value;
43+
}
44+
45+
addDimensionSet(dimensionSet: Dimensions): void {
46+
this.#getDimensionSets().push({ ...dimensionSet });
47+
}
48+
49+
getDimensions(): Dimensions {
50+
return { ...this.#getDimensions() };
51+
}
52+
53+
getDimensionSets(): Dimensions[] {
54+
return this.#getDimensionSets().map((set) => ({ ...set }));
55+
}
56+
57+
clear(): void {
58+
if (InvokeStore.getContext() !== undefined) {
59+
InvokeStore.set('dimensions', {});
60+
InvokeStore.set('dimensionSets', []);
61+
} else {
62+
this.#fallbackDimensions = {};
63+
this.#fallbackDimensionSets = [];
64+
}
65+
}
66+
}
67+
68+
export { DimensionsStore };
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { InvokeStore } from '@aws/lambda-invoke-store';
2+
3+
/**
4+
* Manages storage of metrics #metadata with automatic context detection.
5+
*
6+
* This class abstracts the storage mechanism for metrics, automatically
7+
* choosing between AsyncLocalStorage (when in async context) and a fallback
8+
* object (when outside async context). The decision is made at runtime on
9+
* every method call to support Lambda's transition to async contexts.
10+
*/
11+
class MetadataStore {
12+
#fallbackStorage: Record<string, string> = {};
13+
14+
#getStorage(): Record<string, string> {
15+
if (InvokeStore.getContext() === undefined) {
16+
return this.#fallbackStorage;
17+
}
18+
19+
let stored = InvokeStore.get('#metadata') as
20+
| Record<string, string>
21+
| undefined;
22+
if (stored == null) {
23+
stored = {};
24+
InvokeStore.set('#metadata', stored);
25+
}
26+
return stored;
27+
}
28+
29+
public set(key: string, value: string): void {
30+
this.#getStorage()[key] = value;
31+
}
32+
33+
public getAll(): Record<string, string> {
34+
return { ...this.#getStorage() };
35+
}
36+
37+
public clear(): void {
38+
if (InvokeStore.getContext() !== undefined) {
39+
InvokeStore.set('#metadata', {});
40+
} else {
41+
this.#fallbackStorage = {};
42+
}
43+
}
44+
}
45+
46+
export { MetadataStore };

0 commit comments

Comments
 (0)