@fluidframework/container-runtime 2.0.0-internal.7.1.0 → 2.0.0-internal.7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api-report/container-runtime.api.md +2 -1
- package/dist/blobManager.d.ts +3 -6
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +17 -42
- package/dist/blobManager.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +4 -4
- package/dist/container-runtime-beta.d.ts +4 -4
- package/dist/container-runtime-public.d.ts +4 -4
- package/dist/container-runtime.d.ts +4 -4
- package/dist/containerRuntime.d.ts +5 -4
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +27 -6
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -0
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +39 -34
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +0 -16
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +0 -48
- package/dist/dataStores.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +12 -3
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +41 -18
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +1 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +12 -2
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +21 -7
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +12 -6
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +74 -42
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -5
- package/dist/gc/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/blobManager.d.ts +3 -6
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +18 -43
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +5 -4
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +28 -7
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -0
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +40 -35
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +0 -16
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +2 -50
- package/lib/dataStores.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +12 -3
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +42 -19
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +1 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +14 -4
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +21 -7
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +12 -6
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +74 -42
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +21 -17
- package/src/blobManager.ts +18 -58
- package/src/containerRuntime.ts +39 -16
- package/src/dataStoreContext.ts +17 -8
- package/src/dataStores.ts +2 -80
- package/src/gc/garbageCollection.ts +53 -24
- package/src/gc/gcConfigs.ts +22 -4
- package/src/gc/gcDefinitions.ts +22 -7
- package/src/gc/gcTelemetry.ts +103 -56
- package/src/gc/index.ts +0 -4
- package/src/packageVersion.ts +1 -1
package/src/gc/gcConfigs.ts
CHANGED
|
@@ -24,8 +24,10 @@ import {
|
|
|
24
24
|
runSessionExpiryKey,
|
|
25
25
|
runSweepKey,
|
|
26
26
|
stableGCVersion,
|
|
27
|
+
throwOnTombstoneLoadKey,
|
|
28
|
+
throwOnTombstoneUsageKey,
|
|
27
29
|
} from "./gcDefinitions";
|
|
28
|
-
import { getGCVersion, shouldAllowGcSweep } from "./gcHelpers";
|
|
30
|
+
import { getGCVersion, shouldAllowGcSweep, shouldAllowGcTombstoneEnforcement } from "./gcHelpers";
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Generates configurations for the Garbage Collector that it uses to determine what to run and how.
|
|
@@ -42,6 +44,7 @@ export function generateGCConfigs(
|
|
|
42
44
|
gcOptions: IGCRuntimeOptions;
|
|
43
45
|
metadata: IContainerRuntimeMetadata | undefined;
|
|
44
46
|
existing: boolean;
|
|
47
|
+
isSummarizerClient: boolean;
|
|
45
48
|
},
|
|
46
49
|
): IGarbageCollectorConfigs {
|
|
47
50
|
let gcEnabled: boolean;
|
|
@@ -152,8 +155,6 @@ export function generateGCConfigs(
|
|
|
152
155
|
throw new UsageError("inactive timeout should not be greater than the sweep timeout");
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
|
|
156
|
-
|
|
157
158
|
// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
|
|
158
159
|
const testMode =
|
|
159
160
|
mc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;
|
|
@@ -162,6 +163,20 @@ export function generateGCConfigs(
|
|
|
162
163
|
const tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;
|
|
163
164
|
const runFullGC = createParams.gcOptions.runFullGC;
|
|
164
165
|
|
|
166
|
+
const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
|
|
167
|
+
const tombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement(
|
|
168
|
+
createParams.metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */,
|
|
169
|
+
createParams.gcOptions[gcTombstoneGenerationOptionName] /* current */,
|
|
170
|
+
);
|
|
171
|
+
const throwOnTombstoneLoad =
|
|
172
|
+
mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
|
|
173
|
+
tombstoneEnforcementAllowed &&
|
|
174
|
+
!createParams.isSummarizerClient;
|
|
175
|
+
const throwOnTombstoneUsage =
|
|
176
|
+
mc.config.getBoolean(throwOnTombstoneUsageKey) === true &&
|
|
177
|
+
tombstoneEnforcementAllowed &&
|
|
178
|
+
!createParams.isSummarizerClient;
|
|
179
|
+
|
|
165
180
|
return {
|
|
166
181
|
gcEnabled,
|
|
167
182
|
sweepEnabled,
|
|
@@ -173,10 +188,13 @@ export function generateGCConfigs(
|
|
|
173
188
|
sessionExpiryTimeoutMs,
|
|
174
189
|
sweepTimeoutMs,
|
|
175
190
|
inactiveTimeoutMs,
|
|
176
|
-
throwOnInactiveLoad,
|
|
177
191
|
persistedGcFeatureMatrix,
|
|
178
192
|
gcVersionInBaseSnapshot,
|
|
179
193
|
gcVersionInEffect,
|
|
194
|
+
throwOnInactiveLoad,
|
|
195
|
+
tombstoneEnforcementAllowed,
|
|
196
|
+
throwOnTombstoneLoad,
|
|
197
|
+
throwOnTombstoneUsage,
|
|
180
198
|
};
|
|
181
199
|
}
|
|
182
200
|
|
package/src/gc/gcDefinitions.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
7
|
-
import {
|
|
7
|
+
import { IRequest } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
9
9
|
import {
|
|
10
10
|
IGarbageCollectionData,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
ICreateContainerMetadata,
|
|
20
20
|
IRefreshSummaryResult,
|
|
21
21
|
} from "../summary";
|
|
22
|
+
import { RuntimeHeaderData } from "../containerRuntime";
|
|
22
23
|
|
|
23
24
|
export type GCVersion = number;
|
|
24
25
|
|
|
@@ -193,8 +194,6 @@ export interface IGarbageCollectionRuntime {
|
|
|
193
194
|
getNodeType(nodePath: string): GCNodeType;
|
|
194
195
|
/** Called when the runtime should close because of an error. */
|
|
195
196
|
closeFn: (error?: ICriticalContainerError) => void;
|
|
196
|
-
/** If false, loading or using a Tombstoned object should merely log, not fail */
|
|
197
|
-
gcTombstoneEnforcementAllowed: boolean;
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
/** Defines the contract for the garbage collector. */
|
|
@@ -205,6 +204,12 @@ export interface IGarbageCollector {
|
|
|
205
204
|
readonly summaryStateNeedsReset: boolean;
|
|
206
205
|
/** The count of data stores whose GC state updated since the last summary. */
|
|
207
206
|
readonly updatedDSCountSinceLastSummary: number;
|
|
207
|
+
/** Tells whether tombstone feature is enabled and enforced. */
|
|
208
|
+
readonly tombstoneEnforcementAllowed: boolean;
|
|
209
|
+
/** Tells whether loading a tombstone object should fail or merely log. */
|
|
210
|
+
readonly throwOnTombstoneLoad: boolean;
|
|
211
|
+
/** Tells whether using a tombstone object should fail or merely log. */
|
|
212
|
+
readonly throwOnTombstoneUsage: boolean;
|
|
208
213
|
/** Initialize the state from the base snapshot after its creation. */
|
|
209
214
|
initializeBaseState(): Promise<void>;
|
|
210
215
|
/** Run garbage collection and update the reference / used state of the system. */
|
|
@@ -228,13 +233,17 @@ export interface IGarbageCollector {
|
|
|
228
233
|
getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;
|
|
229
234
|
/** Called when the latest summary of the system has been refreshed. */
|
|
230
235
|
refreshLatestSummary(result: IRefreshSummaryResult): Promise<void>;
|
|
231
|
-
/**
|
|
236
|
+
/**
|
|
237
|
+
* Called when a node with the given path is updated. If the node is inactive or tombstoned, this will log an error
|
|
238
|
+
* or throw an error if failing on incorrect usage is configured.
|
|
239
|
+
*/
|
|
232
240
|
nodeUpdated(
|
|
233
241
|
nodePath: string,
|
|
234
242
|
reason: "Loaded" | "Changed",
|
|
235
243
|
timestampMs?: number,
|
|
236
244
|
packagePath?: readonly string[],
|
|
237
|
-
|
|
245
|
+
request?: IRequest,
|
|
246
|
+
headerData?: RuntimeHeaderData,
|
|
238
247
|
): void;
|
|
239
248
|
/** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
|
|
240
249
|
addedOutboundReference(fromNodePath: string, toNodePath: string): void;
|
|
@@ -332,8 +341,6 @@ export interface IGarbageCollectorConfigs {
|
|
|
332
341
|
readonly sweepTimeoutMs: number | undefined;
|
|
333
342
|
/** The time after which an unreferenced node is inactive. */
|
|
334
343
|
readonly inactiveTimeoutMs: number;
|
|
335
|
-
/** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
|
|
336
|
-
readonly throwOnInactiveLoad: boolean | undefined;
|
|
337
344
|
/** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */
|
|
338
345
|
readonly testMode: boolean;
|
|
339
346
|
/**
|
|
@@ -349,6 +356,14 @@ export interface IGarbageCollectorConfigs {
|
|
|
349
356
|
readonly gcVersionInBaseSnapshot: GCVersion | undefined;
|
|
350
357
|
/** The current version of GC data in the running code */
|
|
351
358
|
readonly gcVersionInEffect: GCVersion;
|
|
359
|
+
/** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
|
|
360
|
+
readonly throwOnInactiveLoad: boolean | undefined;
|
|
361
|
+
/** If false, loading or using a Tombstoned object should merely log, not fail */
|
|
362
|
+
readonly tombstoneEnforcementAllowed: boolean;
|
|
363
|
+
/** If true, throw an error when a tombstone data store is retrieved */
|
|
364
|
+
readonly throwOnTombstoneLoad: boolean;
|
|
365
|
+
/** If true, throw an error when a tombstone data store is used. */
|
|
366
|
+
readonly throwOnTombstoneUsage: boolean;
|
|
352
367
|
}
|
|
353
368
|
|
|
354
369
|
/** The state of node that is unreferenced. */
|
package/src/gc/gcTelemetry.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
MonitoringContext,
|
|
12
12
|
tagCodeArtifacts,
|
|
13
13
|
} from "@fluidframework/telemetry-utils";
|
|
14
|
+
import { RuntimeHeaderData } from "../containerRuntime";
|
|
14
15
|
import { ICreateContainerMetadata } from "../summary";
|
|
15
16
|
import {
|
|
16
17
|
disableSweepLogKey,
|
|
@@ -32,7 +33,7 @@ interface ICommonProps {
|
|
|
32
33
|
completedGCRuns: number;
|
|
33
34
|
isTombstoned: boolean;
|
|
34
35
|
lastSummaryTime?: number;
|
|
35
|
-
|
|
36
|
+
headers?: RuntimeHeaderData;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/** The event that is logged when unreferenced node is used after a certain time. */
|
|
@@ -80,10 +81,13 @@ export class GCTelemetryTracker {
|
|
|
80
81
|
private readonly mc: MonitoringContext,
|
|
81
82
|
private readonly configs: Pick<
|
|
82
83
|
IGarbageCollectorConfigs,
|
|
83
|
-
|
|
84
|
+
| "inactiveTimeoutMs"
|
|
85
|
+
| "sweepTimeoutMs"
|
|
86
|
+
| "tombstoneEnforcementAllowed"
|
|
87
|
+
| "throwOnTombstoneLoad"
|
|
88
|
+
| "throwOnTombstoneUsage"
|
|
84
89
|
>,
|
|
85
90
|
private readonly isSummarizerClient: boolean,
|
|
86
|
-
private readonly gcTombstoneEnforcementAllowed: boolean,
|
|
87
91
|
private readonly createContainerMetadata: ICreateContainerMetadata,
|
|
88
92
|
private readonly getNodeType: (nodeId: string) => GCNodeType,
|
|
89
93
|
private readonly getNodeStateTracker: (
|
|
@@ -95,12 +99,12 @@ export class GCTelemetryTracker {
|
|
|
95
99
|
) {}
|
|
96
100
|
|
|
97
101
|
/**
|
|
98
|
-
* Returns whether an event should be logged for a node that isn't active anymore.
|
|
99
|
-
*
|
|
102
|
+
* Returns whether an event should be logged for a node that isn't active anymore. This does not apply to
|
|
103
|
+
* tombstoned nodes for which an event is always logged. Some scenarios where we won't log:
|
|
104
|
+
* 1. When a DDS is changed. The corresponding data store's event will be logged instead.
|
|
100
105
|
* 2. An event is logged only once per container instance per event per node.
|
|
101
106
|
*/
|
|
102
107
|
private shouldLogNonActiveEvent(
|
|
103
|
-
nodeId: string,
|
|
104
108
|
nodeType: GCNodeType,
|
|
105
109
|
usageType: NodeUsageType,
|
|
106
110
|
nodeStateTracker: UnreferencedStateTracker,
|
|
@@ -119,6 +123,8 @@ export class GCTelemetryTracker {
|
|
|
119
123
|
return false;
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
// Non-tombstone events are logged once per event per node. A unique id is generated by joining
|
|
127
|
+
// node state (inactive / sweep ready), node's id and usage (loaded / changed / revived).
|
|
122
128
|
if (this.loggedUnreferencedEvents.has(uniqueEventId)) {
|
|
123
129
|
return false;
|
|
124
130
|
}
|
|
@@ -126,24 +132,61 @@ export class GCTelemetryTracker {
|
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
/**
|
|
129
|
-
* Called when a node is used. If the node is not active, log
|
|
135
|
+
* Called when a node is used. If the node is not active or tombstoned, log telemetry indicating object is used
|
|
136
|
+
* when it should not have been.
|
|
130
137
|
*/
|
|
131
138
|
public nodeUsed(nodeUsageProps: INodeUsageProps) {
|
|
132
139
|
// If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
|
|
133
140
|
// logging as nothing interesting would have happened worth logging.
|
|
134
|
-
|
|
135
|
-
const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
|
|
136
|
-
if (!nodeStateTracker || nodeUsageProps.currentReferenceTimestampMs === undefined) {
|
|
141
|
+
if (nodeUsageProps.currentReferenceTimestampMs === undefined) {
|
|
137
142
|
return;
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
|
|
141
|
-
// node's id and usage (loaded / changed / revived).
|
|
142
|
-
const uniqueEventId = `${nodeStateTracker.state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
|
|
145
|
+
const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
|
|
143
146
|
const nodeType = this.getNodeType(nodeUsageProps.id);
|
|
147
|
+
const {
|
|
148
|
+
usageType,
|
|
149
|
+
currentReferenceTimestampMs,
|
|
150
|
+
packagePath,
|
|
151
|
+
id: untaggedId,
|
|
152
|
+
fromId: untaggedFromId,
|
|
153
|
+
...propsToLog
|
|
154
|
+
} = nodeUsageProps;
|
|
155
|
+
const unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
|
|
156
|
+
type: nodeType,
|
|
157
|
+
unrefTime: nodeStateTracker?.unreferencedTimestampMs ?? -1,
|
|
158
|
+
age:
|
|
159
|
+
nodeStateTracker !== undefined
|
|
160
|
+
? nodeUsageProps.currentReferenceTimestampMs -
|
|
161
|
+
nodeStateTracker.unreferencedTimestampMs
|
|
162
|
+
: -1,
|
|
163
|
+
timeout:
|
|
164
|
+
nodeStateTracker?.state === UnreferencedState.Inactive
|
|
165
|
+
? this.configs.inactiveTimeoutMs
|
|
166
|
+
: this.configs.sweepTimeoutMs,
|
|
167
|
+
...tagCodeArtifacts({ id: untaggedId, fromId: untaggedFromId }),
|
|
168
|
+
...propsToLog,
|
|
169
|
+
...this.createContainerMetadata,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// If the node that is used is tombstoned, log a tombstone telemetry.
|
|
173
|
+
// Note that this is done before checking if "nodeStateTracker" is undefined below because unreferenced
|
|
174
|
+
// tracking may not have yet been enabled. That happens only after the client transitions to write mode.
|
|
175
|
+
if (nodeUsageProps.isTombstoned) {
|
|
176
|
+
this.logTombstoneUsageTelemetry(nodeUsageProps, unrefEventProps, nodeType, usageType);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// After logging tombstone telemetry, if the node's unreferenced state is not tracked, there is nothing
|
|
180
|
+
// else to log.
|
|
181
|
+
if (nodeStateTracker === undefined) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const state = nodeStateTracker.state;
|
|
186
|
+
const uniqueEventId = `${state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
|
|
187
|
+
|
|
144
188
|
if (
|
|
145
189
|
!this.shouldLogNonActiveEvent(
|
|
146
|
-
nodeUsageProps.id,
|
|
147
190
|
nodeType,
|
|
148
191
|
nodeUsageProps.usageType,
|
|
149
192
|
nodeStateTracker,
|
|
@@ -153,42 +196,9 @@ export class GCTelemetryTracker {
|
|
|
153
196
|
return;
|
|
154
197
|
}
|
|
155
198
|
|
|
156
|
-
// Add the unique event id so that we don't generate a log for this event again in this session
|
|
199
|
+
// Add the unique event id so that we don't generate a log for this event again in this session.
|
|
157
200
|
this.loggedUnreferencedEvents.add(uniqueEventId);
|
|
158
201
|
|
|
159
|
-
const state = nodeStateTracker.state;
|
|
160
|
-
const { usageType, currentReferenceTimestampMs, packagePath, id, fromId, ...propsToLog } =
|
|
161
|
-
nodeUsageProps;
|
|
162
|
-
const eventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
|
|
163
|
-
type: nodeType,
|
|
164
|
-
unrefTime: nodeStateTracker.unreferencedTimestampMs,
|
|
165
|
-
age:
|
|
166
|
-
nodeUsageProps.currentReferenceTimestampMs -
|
|
167
|
-
nodeStateTracker.unreferencedTimestampMs,
|
|
168
|
-
timeout:
|
|
169
|
-
state === UnreferencedState.Inactive
|
|
170
|
-
? this.configs.inactiveTimeoutMs
|
|
171
|
-
: this.configs.sweepTimeoutMs,
|
|
172
|
-
...tagCodeArtifacts({ id, fromId }),
|
|
173
|
-
...propsToLog,
|
|
174
|
-
...this.createContainerMetadata,
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// This will log the following events:
|
|
178
|
-
// GC_Tombstone_DataStore_Revived, GC_Tombstone_SubDataStore_Revived, GC_Tombstone_Blob_Revived
|
|
179
|
-
if (nodeUsageProps.usageType === "Revived" && nodeUsageProps.isTombstoned) {
|
|
180
|
-
sendGCUnexpectedUsageEvent(
|
|
181
|
-
this.mc,
|
|
182
|
-
{
|
|
183
|
-
eventName: `GC_Tombstone_${nodeType}_Revived`,
|
|
184
|
-
category: "generic",
|
|
185
|
-
...tagCodeArtifacts({ url: id }),
|
|
186
|
-
gcTombstoneEnforcementAllowed: this.gcTombstoneEnforcementAllowed,
|
|
187
|
-
},
|
|
188
|
-
undefined /* packagePath */,
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
202
|
// For summarizer client, queue the event so it is logged the next time GC runs if the event is still valid.
|
|
193
203
|
// For non-summarizer client, log the event now since GC won't run on it. This may result in false positives
|
|
194
204
|
// but it's a good signal nonetheless and we can consume it with a grain of salt.
|
|
@@ -196,7 +206,7 @@ export class GCTelemetryTracker {
|
|
|
196
206
|
// SweepReady errors are usages of Objects that will be deleted by GC Sweep!
|
|
197
207
|
if (this.isSummarizerClient) {
|
|
198
208
|
this.pendingEventsQueue.push({
|
|
199
|
-
...
|
|
209
|
+
...unrefEventProps,
|
|
200
210
|
usageType: nodeUsageProps.usageType,
|
|
201
211
|
state,
|
|
202
212
|
});
|
|
@@ -206,16 +216,15 @@ export class GCTelemetryTracker {
|
|
|
206
216
|
// Events generated:
|
|
207
217
|
// InactiveObject_Loaded, SweepReadyObject_Loaded
|
|
208
218
|
if (nodeUsageProps.usageType === "Loaded") {
|
|
209
|
-
const { id
|
|
219
|
+
const { id, fromId, headers, ...detailedProps } = unrefEventProps;
|
|
210
220
|
const event = {
|
|
211
221
|
eventName: `${state}Object_${nodeUsageProps.usageType}`,
|
|
212
|
-
|
|
222
|
+
...tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }),
|
|
213
223
|
stack: generateStack(),
|
|
214
|
-
id
|
|
215
|
-
fromId
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}),
|
|
224
|
+
id,
|
|
225
|
+
fromId,
|
|
226
|
+
headers: { ...headers },
|
|
227
|
+
details: detailedProps,
|
|
219
228
|
};
|
|
220
229
|
|
|
221
230
|
// Do not log the inactive object x events as error events as they are not the best signal for
|
|
@@ -229,6 +238,44 @@ export class GCTelemetryTracker {
|
|
|
229
238
|
}
|
|
230
239
|
}
|
|
231
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Logs telemetry when a tombstoned object is changed, revived or loaded.
|
|
243
|
+
*/
|
|
244
|
+
private logTombstoneUsageTelemetry(
|
|
245
|
+
nodeUsageProps: INodeUsageProps,
|
|
246
|
+
unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType">,
|
|
247
|
+
nodeType: GCNodeType,
|
|
248
|
+
usageType: NodeUsageType,
|
|
249
|
+
) {
|
|
250
|
+
// This will log the following events:
|
|
251
|
+
// GC_Tombstone_DataStore_Requested, GC_Tombstone_DataStore_Changed, GC_Tombstone_DataStore_Revived
|
|
252
|
+
// GC_Tombstone_SubDataStore_Requested, GC_Tombstone_SubDataStore_Changed, GC_Tombstone_SubDataStore_Revived
|
|
253
|
+
// GC_Tombstone_Blob_Requested, GC_Tombstone_Blob_Changed, GC_Tombstone_Blob_Revived
|
|
254
|
+
const { id, fromId, headers, ...detailedProps } = unrefEventProps;
|
|
255
|
+
const eventUsageName = usageType === "Loaded" ? "Requested" : usageType;
|
|
256
|
+
const event = {
|
|
257
|
+
eventName: `GC_Tombstone_${nodeType}_${eventUsageName}`,
|
|
258
|
+
pkg: tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }).pkg,
|
|
259
|
+
stack: generateStack(),
|
|
260
|
+
id,
|
|
261
|
+
fromId,
|
|
262
|
+
headers: { ...headers },
|
|
263
|
+
details: detailedProps,
|
|
264
|
+
gcTombstoneEnforcementAllowed: this.configs.tombstoneEnforcementAllowed,
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
if (
|
|
268
|
+
(usageType === "Loaded" &&
|
|
269
|
+
this.configs.throwOnTombstoneLoad &&
|
|
270
|
+
!headers?.allowTombstone) ||
|
|
271
|
+
(usageType === "Changed" && this.configs.throwOnTombstoneUsage)
|
|
272
|
+
) {
|
|
273
|
+
this.mc.logger.sendErrorEvent(event);
|
|
274
|
+
} else {
|
|
275
|
+
this.mc.logger.sendTelemetryEvent(event);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
232
279
|
/**
|
|
233
280
|
* Log all new references or outbound routes in the current graph that haven't been explicitly notified to GC.
|
|
234
281
|
* The principle is that every new reference or outbound route must be notified to GC via the
|
package/src/gc/index.ts
CHANGED
|
@@ -31,15 +31,11 @@ export {
|
|
|
31
31
|
stableGCVersion,
|
|
32
32
|
disableAttachmentBlobSweepKey,
|
|
33
33
|
disableDatastoreSweepKey,
|
|
34
|
-
throwOnTombstoneLoadKey,
|
|
35
|
-
throwOnTombstoneUsageKey,
|
|
36
34
|
UnreferencedState,
|
|
37
35
|
} from "./gcDefinitions";
|
|
38
36
|
export {
|
|
39
37
|
cloneGCData,
|
|
40
38
|
concatGarbageCollectionStates,
|
|
41
|
-
shouldAllowGcTombstoneEnforcement,
|
|
42
|
-
shouldAllowGcSweep,
|
|
43
39
|
trimLeadingAndTrailingSlashes,
|
|
44
40
|
unpackChildNodesGCDetails,
|
|
45
41
|
} from "./gcHelpers";
|
package/src/packageVersion.ts
CHANGED