2
2
3
3
const { AsyncLocalStorage } = require ( 'async_hooks' )
4
4
5
- /// This is exactly the same as AsyncLocalStorage, with the exception that it
6
- /// uses a WeakMap to store the store object. This is because ALS stores the
7
- /// store object as a property of the resource object, which causes all sorts
8
- /// of problems with logging and memory. We substitute the `store` object with
9
- /// a "handle" object, which is used as a key in a WeakMap, where the values
10
- /// are the real store objects.
5
+ /**
6
+ * This is exactly the same as AsyncLocalStorage, with the exception that it
7
+ * uses a WeakMap to store the store object. This is because ALS stores the
8
+ * store object as a property of the resource object, which causes all sorts
9
+ * of problems with logging and memory. We substitute the `store` object with
10
+ * a "handle" object, which is used as a key in a WeakMap, where the values
11
+ * are the real store objects.
12
+ *
13
+ * @template T
14
+ */
11
15
class DatadogStorage extends AsyncLocalStorage {
16
+ /**
17
+ *
18
+ * @param store {DatadogStorage}
19
+ */
12
20
enterWith ( store ) {
13
21
const handle = { }
14
22
stores . set ( handle , store )
15
23
super . enterWith ( handle )
16
24
}
17
25
18
- // This is method is a passthrough to the real `getStore()`, so that, when we
19
- // need it, we can use the handle rather than our mapped store.
20
- // TODO: Refactor the Scope class to use a span-only store and remove this.
21
- // It's only here because stores are currently used for a bunch of things,
22
- // and we don't want to hold on to all of them in spans
23
- // (see opentracing/span.js). Using a namespaced storage for spans would
24
- // solve this.
26
+ /**
27
+ * This is method is a passthrough to the real `getStore()`, so that, when we
28
+ * need it, we can use the handle rather than our mapped store.
29
+ *
30
+ * It's only here because stores are currently used for a bunch of things,
31
+ * and we don't want to hold on to all of them in spans
32
+ * (see opentracing/span.js). Using a namespaced storage for spans would
33
+ * solve this.
34
+ *
35
+ * TODO: Refactor the Scope class to use a span-only store and remove this.
36
+ *
37
+ * @returns {{} }
38
+ */
25
39
getHandle ( ) {
26
40
return super . getStore ( )
27
41
}
28
42
29
- // Here, we replicate the behavior of the original `getStore()` method by
30
- // passing in the handle, which we retrieve by calling it on super. Handles
31
- // retrieved through `getHandle()` can also be passed in to be used as the
32
- // key. This is useful if you've stashed a handle somewhere and want to
33
- // retrieve the store with it.
43
+ /**
44
+ * Here, we replicate the behavior of the original `getStore()` method by
45
+ * passing in the handle, which we retrieve by calling it on super. Handles
46
+ * retrieved through `getHandle()` can also be passed in to be used as the
47
+ * key. This is useful if you've stashed a handle somewhere and want to
48
+ * retrieve the store with it.
49
+ *
50
+ * @param handle {{}}
51
+ * @returns {T | undefined }
52
+ */
34
53
getStore ( handle ) {
35
54
if ( ! handle ) {
36
55
handle = super . getStore ( )
@@ -39,11 +58,19 @@ class DatadogStorage extends AsyncLocalStorage {
39
58
return stores . get ( handle )
40
59
}
41
60
42
- // Here, we replicate the behavior of the original `run()` method. We ensure
43
- // that our `enterWith()` is called internally, so that the handle to the
44
- // store is set. As an optimization, we use super for getStore and enterWith
45
- // when dealing with the parent store, so that we don't have to access the
46
- // WeakMap.
61
+ /**
62
+ * Here, we replicate the behavior of the original `run()` method. We ensure
63
+ * that our `enterWith()` is called internally, so that the handle to the
64
+ * store is set. As an optimization, we use super for getStore and enterWith
65
+ * when dealing with the parent store, so that we don't have to access the
66
+ * WeakMap.
67
+ * @template R
68
+ * @template TArgs extends any[]
69
+ * @param store {DatadogStorage}
70
+ * @param fn {() => R}
71
+ * @param args {TArgs}
72
+ * @returns {void }
73
+ */
47
74
run ( store , fn , ...args ) {
48
75
const prior = super . getStore ( )
49
76
this . enterWith ( store )
@@ -55,28 +82,31 @@ class DatadogStorage extends AsyncLocalStorage {
55
82
}
56
83
}
57
84
58
- // This is the map from handles to real stores, used in the class above.
85
+ /**
86
+ * This is the map from handles to real stores, used in the class above.
87
+ * @template T
88
+ * @type {WeakMap<WeakKey, T> }
89
+ */
59
90
const stores = new WeakMap ( )
60
91
61
- // For convenience, we use the `storage` function as a registry of namespaces
62
- // corresponding to DatadogStorage instances. This lets us have separate
63
- // storages for separate purposes.
92
+ /**
93
+ * For convenience, we use the `storage` function as a registry of namespaces
94
+ * corresponding to DatadogStorage instances. This lets us have separate
95
+ * storages for separate purposes.
96
+ * @type {Map<string, DatadogStorage> }
97
+ */
64
98
const storages = Object . create ( null )
99
+
100
+ /**
101
+ *
102
+ * @param namespace {string} the namespace to use
103
+ * @returns {DatadogStorage }
104
+ */
65
105
function storage ( namespace ) {
66
106
if ( ! storages [ namespace ] ) {
67
107
storages [ namespace ] = new DatadogStorage ( )
68
108
}
69
109
return storages [ namespace ]
70
110
}
71
111
72
- // Namespaces are a new concept, so for existing internal code that does not
73
- // use namespaces, we have a "legacy" storage object.
74
- const legacyStorage = new DatadogStorage ( )
75
- storage . disable = legacyStorage . disable . bind ( legacyStorage )
76
- storage . enterWith = legacyStorage . enterWith . bind ( legacyStorage )
77
- storage . exit = legacyStorage . exit . bind ( legacyStorage )
78
- storage . getHandle = legacyStorage . getHandle . bind ( legacyStorage )
79
- storage . getStore = legacyStorage . getStore . bind ( legacyStorage )
80
- storage . run = legacyStorage . run . bind ( legacyStorage )
81
-
82
- module . exports = storage
112
+ module . exports = { storage }
0 commit comments