Skip to content

Commit b387413

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

File tree

11 files changed

+1228
-67
lines changed

11 files changed

+1228
-67
lines changed

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/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: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
let stored = InvokeStore.get('dimensions') as Dimensions | undefined;
19+
if (stored == null) {
20+
stored = {};
21+
InvokeStore.set('dimensions', stored);
22+
}
23+
return stored;
24+
}
25+
return this.#fallbackDimensions;
26+
}
27+
28+
#getDimensionSets(): Dimensions[] {
29+
if (InvokeStore.getContext() !== undefined) {
30+
let stored = InvokeStore.get('dimensionSets') as Dimensions[] | undefined;
31+
if (stored == null) {
32+
stored = [];
33+
InvokeStore.set('dimensionSets', stored);
34+
}
35+
return stored;
36+
}
37+
return this.#fallbackDimensionSets;
38+
}
39+
40+
addDimension(name: string, value: string): void {
41+
this.#getDimensions()[name] = value;
42+
}
43+
44+
addDimensionSet(dimensionSet: Dimensions): void {
45+
this.#getDimensionSets().push({ ...dimensionSet });
46+
}
47+
48+
getDimensions(): Dimensions {
49+
return { ...this.#getDimensions() };
50+
}
51+
52+
getDimensionSets(): Dimensions[] {
53+
return this.#getDimensionSets().map((set) => ({ ...set }));
54+
}
55+
56+
clear(): void {
57+
if (InvokeStore.getContext() !== undefined) {
58+
InvokeStore.set('dimensions', {});
59+
InvokeStore.set('dimensionSets', []);
60+
} else {
61+
this.#fallbackDimensions = {};
62+
this.#fallbackDimensionSets = [];
63+
}
64+
}
65+
}
66+
67+
export { DimensionsStore };
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
let stored = InvokeStore.get('metadata') as
17+
| Record<string, string>
18+
| undefined;
19+
if (stored == null) {
20+
stored = {};
21+
InvokeStore.set('metadata', stored);
22+
}
23+
return stored;
24+
}
25+
return this.#fallbackStorage;
26+
}
27+
28+
public set(key: string, value: string): void {
29+
this.#getStorage()[key] = value;
30+
}
31+
32+
public getAll(): Record<string, string> {
33+
return { ...this.#getStorage() };
34+
}
35+
36+
public clear(): void {
37+
if (InvokeStore.getContext() !== undefined) {
38+
InvokeStore.set('metadata', {});
39+
} else {
40+
this.#fallbackStorage = {};
41+
}
42+
}
43+
}
44+
45+
export { MetadataStore };

0 commit comments

Comments
 (0)