Skip to content

Commit 5609d9d

Browse files
benglrochdev
authored andcommitted
simplify storage.js, adding a bunch of comments for clarity (#5203)
* Make DatadogStorage extend from AsyncLocalStorage * Add comments everywhere
1 parent a1e2f67 commit 5609d9d

File tree

1 file changed

+38
-23
lines changed

1 file changed

+38
-23
lines changed

packages/datadog-core/src/storage.js

+38-23
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,81 @@
22

33
const { AsyncLocalStorage } = require('async_hooks')
44

5-
class DatadogStorage {
6-
constructor () {
7-
this._storage = new AsyncLocalStorage()
8-
}
9-
10-
disable () {
11-
this._storage.disable()
12-
}
13-
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.
11+
class DatadogStorage extends AsyncLocalStorage {
1412
enterWith (store) {
1513
const handle = {}
1614
stores.set(handle, store)
17-
this._storage.enterWith(handle)
18-
}
19-
20-
exit (callback, ...args) {
21-
this._storage.exit(callback, ...args)
15+
super.enterWith(handle)
2216
}
2317

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.
2420
// 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.
2525
getHandle () {
26-
return this._storage.getStore()
26+
return super.getStore()
2727
}
2828

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.
2934
getStore (handle) {
3035
if (!handle) {
31-
handle = this._storage.getStore()
36+
handle = super.getStore()
3237
}
3338

3439
return stores.get(handle)
3540
}
3641

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.
3747
run (store, fn, ...args) {
38-
const prior = this._storage.getStore()
48+
const prior = super.getStore()
3949
this.enterWith(store)
4050
try {
4151
return Reflect.apply(fn, null, args)
4252
} finally {
43-
this._storage.enterWith(prior)
53+
super.enterWith(prior)
4454
}
4555
}
4656
}
4757

48-
const storages = Object.create(null)
49-
const legacyStorage = new DatadogStorage()
58+
// This is the map from handles to real stores, used in the class above.
59+
const stores = new WeakMap()
5060

51-
const storage = function (namespace) {
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.
64+
const storages = Object.create(null)
65+
function storage (namespace) {
5266
if (!storages[namespace]) {
5367
storages[namespace] = new DatadogStorage()
5468
}
5569
return storages[namespace]
5670
}
5771

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()
5875
storage.disable = legacyStorage.disable.bind(legacyStorage)
5976
storage.enterWith = legacyStorage.enterWith.bind(legacyStorage)
6077
storage.exit = legacyStorage.exit.bind(legacyStorage)
6178
storage.getHandle = legacyStorage.getHandle.bind(legacyStorage)
6279
storage.getStore = legacyStorage.getStore.bind(legacyStorage)
6380
storage.run = legacyStorage.run.bind(legacyStorage)
6481

65-
const stores = new WeakMap()
66-
6782
module.exports = storage

0 commit comments

Comments
 (0)